A lot of stuff

This commit is contained in:
Justin Mazzocchi 2020-07-31 14:40:57 -07:00
parent f384c659df
commit 5ca8d84604
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
14 changed files with 359 additions and 17 deletions

View file

@ -1,2 +1,5 @@
disabled_rules: disabled_rules:
identifier_name - identifier_name
# Swift 5.3
- multiple_closures_with_trailing_closure
- no_space_in_method_call

View file

@ -0,0 +1,69 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
import Combine
// swiftlint:disable force_try
private let decoder = MastodonDecoder()
private var cancellables = Set<AnyCancellable>()
private let devIdentityID = "DEVELOPMENT_IDENTITY_ID"
extension Secrets {
static let development: Secrets = {
let secrets = Secrets(keychain: FakeKeychain())
try! secrets.set("DEVELOPMENT_CLIENT_ID", forItem: .clientID, forIdentityID: devIdentityID)
try! secrets.set("DEVELOPMENT_CLIENT_SECRET", forItem: .clientSecret, forIdentityID: devIdentityID)
try! secrets.set("DEVELOPMENT_ACCESS_TOKEN", forItem: .accessToken, forIdentityID: devIdentityID)
return secrets
}()
}
extension MastodonClient {
static let development = MastodonClient(configuration: .stubbing)
}
extension Account {
static let development = try! decoder.decode(Account.self, from: Data(officialAccountJSON.utf8))
}
extension Instance {
static let development = try! decoder.decode(Instance.self, from: Data(officialInstanceJSON.utf8))
}
extension IdentityDatabase {
static var development: IdentityDatabase = {
let db = try! IdentityDatabase(inMemory: true)
db.createIdentity(id: devIdentityID, url: URL(string: "https://mastodon.social")!)
.receive(on: ImmediateScheduler.shared)
.sink(receiveCompletion: { _ in }, receiveValue: { _ in })
.store(in: &cancellables)
db.updateAccount(.development, forIdentityID: devIdentityID)
.receive(on: ImmediateScheduler.shared)
.sink(receiveCompletion: { _ in }, receiveValue: { _ in })
.store(in: &cancellables)
db.updateInstance(.development, forIdentityID: devIdentityID)
.receive(on: ImmediateScheduler.shared)
.sink(receiveCompletion: { _ in }, receiveValue: { _ in })
.store(in: &cancellables)
return db
}()
}
extension Identity {
static let development = try! IdentityDatabase.development.identity(id: devIdentityID)!
}
extension SceneViewModel {
static let development = SceneViewModel(
networkClient: .development,
identityDatabase: .development,
secrets: .development)
}
// swiftlint:enable force_try

View file

@ -0,0 +1,50 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
// swiftlint:disable line_length
let officialAccountJSON = #"""
{
"id": "13179",
"username": "Mastodon",
"acct": "Mastodon",
"display_name": "Mastodon",
"locked": false,
"bot": false,
"discoverable": false,
"group": false,
"created_at": "2016-11-23T04:32:45.703Z",
"note": "<p>Official account of the Mastodon project. News, releases, announcements. All in micro-blog form! Toot toot!</p>",
"url": "https://mastodon.social/@Mastodon",
"avatar": "https://files.mastodon.social/accounts/avatars/000/013/179/original/27bc451c7713091b.jpg",
"avatar_static": "https://files.mastodon.social/accounts/avatars/000/013/179/original/27bc451c7713091b.jpg",
"header": "https://files.mastodon.social/accounts/headers/000/013/179/original/4835294a8ed4c5a2.png",
"header_static": "https://files.mastodon.social/accounts/headers/000/013/179/original/4835294a8ed4c5a2.png",
"followers_count": 531199,
"following_count": 10,
"statuses_count": 166,
"last_status_at": "2020-07-26",
"emojis": [],
"fields": [
{
"name": "Homepage",
"value": "<a href=\"https://joinmastodon.org\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">joinmastodon.org</span><span class=\"invisible\"></span></a>",
"verified_at": "2018-10-31T04:11:00.076+00:00"
},
{
"name": "Patreon",
"value": "<a href=\"https://patreon.com/mastodon\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">patreon.com/mastodon</span><span class=\"invisible\"></span></a>",
"verified_at": null
}
]
}
"""#
extension AccountEndpoint: Stubbing {
func dataString(url: URL) -> String? {
switch self {
case .verifyCredentials: return officialAccountJSON
}
}
}
// swiftlint:enable line_length

View file

@ -0,0 +1,74 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
// swiftlint:disable line_length
let officialInstanceJSON = #"""
{
"uri": "mastodon.social",
"title": "Mastodon",
"short_description": "Server run by the main developers of the project <img draggable=\"false\" alt=\"\ud83d\udc18\" class=\"emojione\" src=\"https://mastodon.social/emoji/1f418.svg\" /> It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!",
"description": "Server run by the main developers of the project <img draggable=\"false\" alt=\"\ud83d\udc18\" class=\"emojione\" src=\"https://mastodon.social/emoji/1f418.svg\" /> It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!",
"email": "staff@mastodon.social",
"version": "3.2.0",
"urls": {
"streaming_api": "wss://mastodon.social"
},
"stats": {
"user_count": 528991,
"status_count": 24588857,
"domain_count": 14857
},
"thumbnail": "https://files.mastodon.social/site_uploads/files/000/000/001/original/vlcsnap-2018-08-27-16h43m11s127.png",
"languages": [
"en"
],
"registrations": false,
"approval_required": false,
"invites_enabled": true,
"contact_account": {
"id": "1",
"username": "Gargron",
"acct": "Gargron",
"display_name": "Eugen",
"locked": false,
"bot": false,
"discoverable": true,
"group": false,
"created_at": "2016-03-16T14:34:26.392Z",
"note": "<p>Developer of Mastodon and administrator of mastodon.social. I post service announcements, development updates, and personal stuff.</p>",
"url": "https://mastodon.social/@Gargron",
"avatar": "https://files.mastodon.social/accounts/avatars/000/000/001/original/d96d39a0abb45b92.jpg",
"avatar_static": "https://files.mastodon.social/accounts/avatars/000/000/001/original/d96d39a0abb45b92.jpg",
"header": "https://files.mastodon.social/accounts/headers/000/000/001/original/c91b871f294ea63e.png",
"header_static": "https://files.mastodon.social/accounts/headers/000/000/001/original/c91b871f294ea63e.png",
"followers_count": 425409,
"following_count": 440,
"statuses_count": 66170,
"last_status_at": "2020-07-31",
"emojis": [],
"fields": [
{
"name": "Patreon",
"value": "<a href=\"https://www.patreon.com/mastodon\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://www.</span><span class=\"\">patreon.com/mastodon</span><span class=\"invisible\"></span></a>",
"verified_at": null
},
{
"name": "Homepage",
"value": "<a href=\"https://zeonfederated.com\" rel=\"me nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">zeonfederated.com</span><span class=\"invisible\"></span></a>",
"verified_at": "2019-07-15T18:29:57.191+00:00"
}
]
}
}
"""#
extension InstanceEndpoint: Stubbing {
func dataString(url: URL) -> String? {
switch self {
case .instance: return officialInstanceJSON
}
}
}
// swiftlint:enable line_length

View file

@ -11,6 +11,16 @@
D047FAAF24C3E21200AF17C5 /* MetatextApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D047FA8524C3E21000AF17C5 /* MetatextApp.swift */; }; D047FAAF24C3E21200AF17C5 /* MetatextApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D047FA8524C3E21000AF17C5 /* MetatextApp.swift */; };
D047FAB224C3E21200AF17C5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D047FA8724C3E21200AF17C5 /* Assets.xcassets */; }; D047FAB224C3E21200AF17C5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D047FA8724C3E21200AF17C5 /* Assets.xcassets */; };
D047FAB324C3E21200AF17C5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D047FA8724C3E21200AF17C5 /* Assets.xcassets */; }; D047FAB324C3E21200AF17C5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D047FA8724C3E21200AF17C5 /* Assets.xcassets */; };
D04FD73324D48F37007D572D /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73224D48F37007D572D /* SettingsView.swift */; };
D04FD73424D48F37007D572D /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73224D48F37007D572D /* SettingsView.swift */; };
D04FD73624D49506007D572D /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73524D49506007D572D /* SettingsViewModel.swift */; };
D04FD73724D49506007D572D /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73524D49506007D572D /* SettingsViewModel.swift */; };
D04FD73924D4A7B4007D572D /* AccountEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73824D4A7B4007D572D /* AccountEndpoint+Stubbing.swift */; };
D04FD73A24D4A7B4007D572D /* AccountEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73824D4A7B4007D572D /* AccountEndpoint+Stubbing.swift */; };
D04FD73C24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73B24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift */; };
D04FD73D24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73B24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift */; };
D04FD74224D4AA34007D572D /* DevelopmentModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD74124D4AA34007D572D /* DevelopmentModels.swift */; };
D04FD74324D4AA34007D572D /* DevelopmentModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD74124D4AA34007D572D /* DevelopmentModels.swift */; };
D065F53924D37E5100741304 /* CombineExpectations in Frameworks */ = {isa = PBXBuildFile; productRef = D065F53824D37E5100741304 /* CombineExpectations */; }; D065F53924D37E5100741304 /* CombineExpectations in Frameworks */ = {isa = PBXBuildFile; productRef = D065F53824D37E5100741304 /* CombineExpectations */; };
D065F53B24D3B33A00741304 /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D065F53A24D3B33A00741304 /* View+Extensions.swift */; }; D065F53B24D3B33A00741304 /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D065F53A24D3B33A00741304 /* View+Extensions.swift */; };
D065F53C24D3B33A00741304 /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D065F53A24D3B33A00741304 /* View+Extensions.swift */; }; D065F53C24D3B33A00741304 /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D065F53A24D3B33A00741304 /* View+Extensions.swift */; };
@ -42,6 +52,8 @@
D0666A7D24C7745A00F3F04B /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = D0666A7C24C7745A00F3F04B /* GRDB */; }; D0666A7D24C7745A00F3F04B /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = D0666A7C24C7745A00F3F04B /* GRDB */; };
D06B491F24D3F7FE00642749 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D06B491E24D3F7FE00642749 /* Localizable.strings */; }; D06B491F24D3F7FE00642749 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D06B491E24D3F7FE00642749 /* Localizable.strings */; };
D06B492024D3FB8000642749 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D06B491E24D3F7FE00642749 /* Localizable.strings */; }; D06B492024D3FB8000642749 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D06B491E24D3F7FE00642749 /* Localizable.strings */; };
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = D06B492224D4611300642749 /* KingfisherSwiftUI */; };
D06B492524D4612400642749 /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = D06B492424D4612400642749 /* KingfisherSwiftUI */; };
D074577724D29006004758DB /* StubbingWebAuthenticationSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577624D29006004758DB /* StubbingWebAuthenticationSession.swift */; }; D074577724D29006004758DB /* StubbingWebAuthenticationSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577624D29006004758DB /* StubbingWebAuthenticationSession.swift */; };
D074577824D29006004758DB /* StubbingWebAuthenticationSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577624D29006004758DB /* StubbingWebAuthenticationSession.swift */; }; D074577824D29006004758DB /* StubbingWebAuthenticationSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577624D29006004758DB /* StubbingWebAuthenticationSession.swift */; };
D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */; }; D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */; };
@ -131,6 +143,11 @@
D047FA9424C3E21200AF17C5 /* Metatext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metatext.app; sourceTree = BUILT_PRODUCTS_DIR; }; D047FA9424C3E21200AF17C5 /* Metatext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metatext.app; sourceTree = BUILT_PRODUCTS_DIR; };
D047FA9624C3E21200AF17C5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; D047FA9624C3E21200AF17C5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D047FA9724C3E21200AF17C5 /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = "<group>"; }; D047FA9724C3E21200AF17C5 /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = "<group>"; };
D04FD73224D48F37007D572D /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
D04FD73524D49506007D572D /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
D04FD73824D4A7B4007D572D /* AccountEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountEndpoint+Stubbing.swift"; sourceTree = "<group>"; };
D04FD73B24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "InstanceEndpoint+Stubbing.swift"; sourceTree = "<group>"; };
D04FD74124D4AA34007D572D /* DevelopmentModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevelopmentModels.swift; sourceTree = "<group>"; };
D065F53A24D3B33A00741304 /* View+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = "<group>"; }; D065F53A24D3B33A00741304 /* View+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = "<group>"; };
D065F53D24D3D20300741304 /* InstanceEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceEndpoint.swift; sourceTree = "<group>"; }; D065F53D24D3D20300741304 /* InstanceEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceEndpoint.swift; sourceTree = "<group>"; };
D0666A2124C677B400F3F04B /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D0666A2124C677B400F3F04B /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@ -189,6 +206,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */,
D0666A4924C6C1A300F3F04B /* GRDB in Frameworks */, D0666A4924C6C1A300F3F04B /* GRDB in Frameworks */,
D0DC175F24D016EA00A75C65 /* Alamofire in Frameworks */, D0DC175F24D016EA00A75C65 /* Alamofire in Frameworks */,
); );
@ -198,6 +216,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D06B492524D4612400642749 /* KingfisherSwiftUI in Frameworks */,
D0DC176124D0171800A75C65 /* Alamofire in Frameworks */, D0DC176124D0171800A75C65 /* Alamofire in Frameworks */,
D0666A7D24C7745A00F3F04B /* GRDB in Frameworks */, D0666A7D24C7745A00F3F04B /* GRDB in Frameworks */,
); );
@ -321,6 +340,7 @@
D0DB6EF324C5228A00D965FE /* AddIdentityView.swift */, D0DB6EF324C5228A00D965FE /* AddIdentityView.swift */,
D0BEC93A24C96FD500E864C4 /* ContentView.swift */, D0BEC93A24C96FD500E864C4 /* ContentView.swift */,
D0BEC94924CA231200E864C4 /* TimelineView.swift */, D0BEC94924CA231200E864C4 /* TimelineView.swift */,
D04FD73224D48F37007D572D /* SettingsView.swift */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@ -343,6 +363,7 @@
children = ( children = (
D0DB6F0824C65AC000D965FE /* AddIdentityViewModel.swift */, D0DB6F0824C65AC000D965FE /* AddIdentityViewModel.swift */,
D0BEC93724C9632800E864C4 /* SceneViewModel.swift */, D0BEC93724C9632800E864C4 /* SceneViewModel.swift */,
D04FD73524D49506007D572D /* SettingsViewModel.swift */,
D0BEC94624CA22C400E864C4 /* TimelineViewModel.swift */, D0BEC94624CA22C400E864C4 /* TimelineViewModel.swift */,
); );
path = "View Models"; path = "View Models";
@ -363,7 +384,9 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D0DC175424D00F0A00A75C65 /* AccessTokenEndpoint+Stubbing.swift */, D0DC175424D00F0A00A75C65 /* AccessTokenEndpoint+Stubbing.swift */,
D04FD73824D4A7B4007D572D /* AccountEndpoint+Stubbing.swift */,
D0DC174924CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift */, D0DC174924CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift */,
D04FD73B24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift */,
D0DC175124D008E300A75C65 /* MastodonTarget+Stubbing.swift */, D0DC175124D008E300A75C65 /* MastodonTarget+Stubbing.swift */,
); );
path = "Mastodon API Stubs"; path = "Mastodon API Stubs";
@ -380,6 +403,7 @@
D0ED1BB224CE3A1600B4899C /* Development Assets */ = { D0ED1BB224CE3A1600B4899C /* Development Assets */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D04FD74124D4AA34007D572D /* DevelopmentModels.swift */,
D0DC177624D0CF2600A75C65 /* FakeKeychain.swift */, D0DC177624D0CF2600A75C65 /* FakeKeychain.swift */,
D0DC175724D0130800A75C65 /* HTTPStubs.swift */, D0DC175724D0130800A75C65 /* HTTPStubs.swift */,
D0DC174824CFF13700A75C65 /* Mastodon API Stubs */, D0DC174824CFF13700A75C65 /* Mastodon API Stubs */,
@ -426,6 +450,7 @@
packageProductDependencies = ( packageProductDependencies = (
D0666A4824C6C1A300F3F04B /* GRDB */, D0666A4824C6C1A300F3F04B /* GRDB */,
D0DC175E24D016EA00A75C65 /* Alamofire */, D0DC175E24D016EA00A75C65 /* Alamofire */,
D06B492224D4611300642749 /* KingfisherSwiftUI */,
); );
productName = "Metatext (iOS)"; productName = "Metatext (iOS)";
productReference = D047FA8C24C3E21200AF17C5 /* Metatext.app */; productReference = D047FA8C24C3E21200AF17C5 /* Metatext.app */;
@ -448,6 +473,7 @@
packageProductDependencies = ( packageProductDependencies = (
D0666A7C24C7745A00F3F04B /* GRDB */, D0666A7C24C7745A00F3F04B /* GRDB */,
D0DC176024D0171800A75C65 /* Alamofire */, D0DC176024D0171800A75C65 /* Alamofire */,
D06B492424D4612400642749 /* KingfisherSwiftUI */,
); );
productName = "Metatext (macOS)"; productName = "Metatext (macOS)";
productReference = D047FA9424C3E21200AF17C5 /* Metatext.app */; productReference = D047FA9424C3E21200AF17C5 /* Metatext.app */;
@ -510,6 +536,7 @@
D0666A4724C6C1A300F3F04B /* XCRemoteSwiftPackageReference "GRDB" */, D0666A4724C6C1A300F3F04B /* XCRemoteSwiftPackageReference "GRDB" */,
D0DC175D24D016EA00A75C65 /* XCRemoteSwiftPackageReference "Alamofire" */, D0DC175D24D016EA00A75C65 /* XCRemoteSwiftPackageReference "Alamofire" */,
D065F53724D37E5100741304 /* XCRemoteSwiftPackageReference "CombineExpectations" */, D065F53724D37E5100741304 /* XCRemoteSwiftPackageReference "CombineExpectations" */,
D06B492124D4611300642749 /* XCRemoteSwiftPackageReference "Kingfisher" */,
); );
productRefGroup = D047FA8D24C3E21200AF17C5 /* Products */; productRefGroup = D047FA8D24C3E21200AF17C5 /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -592,6 +619,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D04FD73924D4A7B4007D572D /* AccountEndpoint+Stubbing.swift in Sources */,
D0DB6F0924C65AC000D965FE /* AddIdentityViewModel.swift in Sources */, D0DB6F0924C65AC000D965FE /* AddIdentityViewModel.swift in Sources */,
D0ED1BD724CF94B200B4899C /* Application.swift in Sources */, D0ED1BD724CF94B200B4899C /* Application.swift in Sources */,
D047FAAE24C3E21200AF17C5 /* MetatextApp.swift in Sources */, D047FAAE24C3E21200AF17C5 /* MetatextApp.swift in Sources */,
@ -601,6 +629,7 @@
D0ED1BE324CFA84400B4899C /* MastodonError.swift in Sources */, D0ED1BE324CFA84400B4899C /* MastodonError.swift in Sources */,
D0666A6324C6DC6C00F3F04B /* AppAuthorization.swift in Sources */, D0666A6324C6DC6C00F3F04B /* AppAuthorization.swift in Sources */,
D065F53B24D3B33A00741304 /* View+Extensions.swift in Sources */, D065F53B24D3B33A00741304 /* View+Extensions.swift in Sources */,
D04FD73324D48F37007D572D /* SettingsView.swift in Sources */,
D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */, D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */,
D0666A5A24C6C64100F3F04B /* MastodonEncoder.swift in Sources */, D0666A5A24C6C64100F3F04B /* MastodonEncoder.swift in Sources */,
D0666A5124C6C3BC00F3F04B /* Account.swift in Sources */, D0666A5124C6C3BC00F3F04B /* Account.swift in Sources */,
@ -618,6 +647,8 @@
D0666A4224C6BB7B00F3F04B /* IdentityDatabase.swift in Sources */, D0666A4224C6BB7B00F3F04B /* IdentityDatabase.swift in Sources */,
D0BEC94A24CA231200E864C4 /* TimelineView.swift in Sources */, D0BEC94A24CA231200E864C4 /* TimelineView.swift in Sources */,
D0BEC93B24C96FD500E864C4 /* ContentView.swift in Sources */, D0BEC93B24C96FD500E864C4 /* ContentView.swift in Sources */,
D04FD73624D49506007D572D /* SettingsViewModel.swift in Sources */,
D04FD74224D4AA34007D572D /* DevelopmentModels.swift in Sources */,
D0DC175824D0130800A75C65 /* HTTPStubs.swift in Sources */, D0DC175824D0130800A75C65 /* HTTPStubs.swift in Sources */,
D0DC177724D0CF2600A75C65 /* FakeKeychain.swift in Sources */, D0DC177724D0CF2600A75C65 /* FakeKeychain.swift in Sources */,
D0C963FB24CC359D003BD330 /* AlertItem.swift in Sources */, D0C963FB24CC359D003BD330 /* AlertItem.swift in Sources */,
@ -634,6 +665,7 @@
D0BEC95124CA2B7E00E864C4 /* TabNavigation.swift in Sources */, D0BEC95124CA2B7E00E864C4 /* TabNavigation.swift in Sources */,
D0ED1BC424CED54D00B4899C /* HTTPTarget.swift in Sources */, D0ED1BC424CED54D00B4899C /* HTTPTarget.swift in Sources */,
D0C963FE24CC3812003BD330 /* Publisher+Extensions.swift in Sources */, D0C963FE24CC3812003BD330 /* Publisher+Extensions.swift in Sources */,
D04FD73C24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */,
D0DC175B24D0154F00A75C65 /* MastodonAPI.swift in Sources */, D0DC175B24D0154F00A75C65 /* MastodonAPI.swift in Sources */,
D0ED1BD124CF779B00B4899C /* MastodonTarget.swift in Sources */, D0ED1BD124CF779B00B4899C /* MastodonTarget.swift in Sources */,
D065F53E24D3D20300741304 /* InstanceEndpoint.swift in Sources */, D065F53E24D3D20300741304 /* InstanceEndpoint.swift in Sources */,
@ -646,6 +678,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D04FD73A24D4A7B4007D572D /* AccountEndpoint+Stubbing.swift in Sources */,
D0DB6F0A24C65AC000D965FE /* AddIdentityViewModel.swift in Sources */, D0DB6F0A24C65AC000D965FE /* AddIdentityViewModel.swift in Sources */,
D0ED1BD824CF94B200B4899C /* Application.swift in Sources */, D0ED1BD824CF94B200B4899C /* Application.swift in Sources */,
D047FAAF24C3E21200AF17C5 /* MetatextApp.swift in Sources */, D047FAAF24C3E21200AF17C5 /* MetatextApp.swift in Sources */,
@ -655,6 +688,7 @@
D0ED1BE424CFA84400B4899C /* MastodonError.swift in Sources */, D0ED1BE424CFA84400B4899C /* MastodonError.swift in Sources */,
D0666A6424C6DC6C00F3F04B /* AppAuthorization.swift in Sources */, D0666A6424C6DC6C00F3F04B /* AppAuthorization.swift in Sources */,
D065F53C24D3B33A00741304 /* View+Extensions.swift in Sources */, D065F53C24D3B33A00741304 /* View+Extensions.swift in Sources */,
D04FD73424D48F37007D572D /* SettingsView.swift in Sources */,
D0DC174B24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */, D0DC174B24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */,
D0666A5B24C6C64100F3F04B /* MastodonEncoder.swift in Sources */, D0666A5B24C6C64100F3F04B /* MastodonEncoder.swift in Sources */,
D0666A5224C6C3BC00F3F04B /* Account.swift in Sources */, D0666A5224C6C3BC00F3F04B /* Account.swift in Sources */,
@ -672,6 +706,8 @@
D0666A4324C6BB7B00F3F04B /* IdentityDatabase.swift in Sources */, D0666A4324C6BB7B00F3F04B /* IdentityDatabase.swift in Sources */,
D0BEC94B24CA231200E864C4 /* TimelineView.swift in Sources */, D0BEC94B24CA231200E864C4 /* TimelineView.swift in Sources */,
D0BEC93C24C96FD500E864C4 /* ContentView.swift in Sources */, D0BEC93C24C96FD500E864C4 /* ContentView.swift in Sources */,
D04FD73724D49506007D572D /* SettingsViewModel.swift in Sources */,
D04FD74324D4AA34007D572D /* DevelopmentModels.swift in Sources */,
D0DC175924D0130800A75C65 /* HTTPStubs.swift in Sources */, D0DC175924D0130800A75C65 /* HTTPStubs.swift in Sources */,
D0DC177824D0CF2600A75C65 /* FakeKeychain.swift in Sources */, D0DC177824D0CF2600A75C65 /* FakeKeychain.swift in Sources */,
D0C963FC24CC359D003BD330 /* AlertItem.swift in Sources */, D0C963FC24CC359D003BD330 /* AlertItem.swift in Sources */,
@ -688,6 +724,7 @@
D0666A7324C6E0D300F3F04B /* Secrets.swift in Sources */, D0666A7324C6E0D300F3F04B /* Secrets.swift in Sources */,
D0ED1BC524CED54D00B4899C /* HTTPTarget.swift in Sources */, D0ED1BC524CED54D00B4899C /* HTTPTarget.swift in Sources */,
D0C963FF24CC3812003BD330 /* Publisher+Extensions.swift in Sources */, D0C963FF24CC3812003BD330 /* Publisher+Extensions.swift in Sources */,
D04FD73D24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */,
D0DC175C24D0154F00A75C65 /* MastodonAPI.swift in Sources */, D0DC175C24D0154F00A75C65 /* MastodonAPI.swift in Sources */,
D0ED1BD224CF779B00B4899C /* MastodonTarget.swift in Sources */, D0ED1BD224CF779B00B4899C /* MastodonTarget.swift in Sources */,
D065F53F24D3D20300741304 /* InstanceEndpoint.swift in Sources */, D065F53F24D3D20300741304 /* InstanceEndpoint.swift in Sources */,
@ -832,7 +869,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "Development\\ Assets"; DEVELOPMENT_ASSET_PATHS = "Development\\ Assets Development\\ Assets/Mastodon\\ API\\ Stubs";
DEVELOPMENT_TEAM = 82HL67AXQ2; DEVELOPMENT_TEAM = 82HL67AXQ2;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = iOS/Info.plist; INFOPLIST_FILE = iOS/Info.plist;
@ -855,7 +892,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "Development\\ Assets"; DEVELOPMENT_ASSET_PATHS = "Development\\ Assets Development\\ Assets/Mastodon\\ API\\ Stubs";
DEVELOPMENT_TEAM = 82HL67AXQ2; DEVELOPMENT_TEAM = 82HL67AXQ2;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = iOS/Info.plist; INFOPLIST_FILE = iOS/Info.plist;
@ -881,7 +918,7 @@
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements; CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_ASSET_PATHS = "Development\\ Assets"; DEVELOPMENT_ASSET_PATHS = "Development\\ Assets Development\\ Assets/Mastodon\\ API\\ Stubs";
DEVELOPMENT_TEAM = 82HL67AXQ2; DEVELOPMENT_TEAM = 82HL67AXQ2;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@ -906,7 +943,7 @@
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements; CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_ASSET_PATHS = "Development\\ Assets"; DEVELOPMENT_ASSET_PATHS = "Development\\ Assets Development\\ Assets/Mastodon\\ API\\ Stubs";
DEVELOPMENT_TEAM = 82HL67AXQ2; DEVELOPMENT_TEAM = 82HL67AXQ2;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@ -1029,6 +1066,14 @@
minimumVersion = "5.0.0-beta.10"; minimumVersion = "5.0.0-beta.10";
}; };
}; };
D06B492124D4611300642749 /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/onevcat/Kingfisher";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 5.14.1;
};
};
D0DC175D24D016EA00A75C65 /* XCRemoteSwiftPackageReference "Alamofire" */ = { D0DC175D24D016EA00A75C65 /* XCRemoteSwiftPackageReference "Alamofire" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Alamofire/Alamofire"; repositoryURL = "https://github.com/Alamofire/Alamofire";
@ -1055,6 +1100,16 @@
package = D0666A4724C6C1A300F3F04B /* XCRemoteSwiftPackageReference "GRDB" */; package = D0666A4724C6C1A300F3F04B /* XCRemoteSwiftPackageReference "GRDB" */;
productName = GRDB; productName = GRDB;
}; };
D06B492224D4611300642749 /* KingfisherSwiftUI */ = {
isa = XCSwiftPackageProductDependency;
package = D06B492124D4611300642749 /* XCRemoteSwiftPackageReference "Kingfisher" */;
productName = KingfisherSwiftUI;
};
D06B492424D4612400642749 /* KingfisherSwiftUI */ = {
isa = XCSwiftPackageProductDependency;
package = D06B492124D4611300642749 /* XCRemoteSwiftPackageReference "Kingfisher" */;
productName = KingfisherSwiftUI;
};
D0DC175E24D016EA00A75C65 /* Alamofire */ = { D0DC175E24D016EA00A75C65 /* Alamofire */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = D0DC175D24D016EA00A75C65 /* XCRemoteSwiftPackageReference "Alamofire" */; package = D0DC175D24D016EA00A75C65 /* XCRemoteSwiftPackageReference "Alamofire" */;

View file

@ -27,6 +27,15 @@
"revision": "ededd8668abd5a3c4c43cc9ebcfd611082b47f65", "revision": "ededd8668abd5a3c4c43cc9ebcfd611082b47f65",
"version": "5.0.0-beta.10" "version": "5.0.0-beta.10"
} }
},
{
"package": "Kingfisher",
"repositoryURL": "https://github.com/onevcat/Kingfisher",
"state": {
"branch": null,
"revision": "1339ebea9498ef6c3fc75cc195d7163d7c7167f9",
"version": "5.14.1"
}
} }
] ]
}, },

View file

@ -3,3 +3,4 @@
"go" = "Go"; "go" = "Go";
"add-identity.instance-url" = "Instance URL"; "add-identity.instance-url" = "Instance URL";
"oauth.error.code-not-found" = "OAuth error: code not found"; "oauth.error.code-not-found" = "OAuth error: code not found";
"settings" = "Settings";

View file

@ -20,6 +20,7 @@ class SceneViewModel: ObservableObject {
} }
@Published var alertItem: AlertItem? @Published var alertItem: AlertItem?
@Published var presentingSettings = false
var selectedTopLevelNavigation: TopLevelNavigation? = .timelines var selectedTopLevelNavigation: TopLevelNavigation? = .timelines
private let networkClient: MastodonClient private let networkClient: MastodonClient

View file

@ -0,0 +1,11 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
class SettingsViewModel: ObservableObject {
let identity: Identity
init(identity: Identity) {
self.identity = identity
}
}

View file

@ -36,13 +36,15 @@ extension AddIdentityView {
} }
} }
#if DEBUG
struct AddAccountView_Previews: PreviewProvider { struct AddAccountView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
AddIdentityView(viewModel: AddIdentityViewModel( AddIdentityView(viewModel: AddIdentityViewModel(
networkClient: MastodonClient(configuration: .stubbing), networkClient: MastodonClient.development,
// swiftlint:disable force_try // swiftlint:disable force_try
identityDatabase: try! IdentityDatabase(inMemory: true), identityDatabase: try! IdentityDatabase(inMemory: true),
// swiftlint:enable force_try // swiftlint:enable force_try
secrets: Secrets(keychain: FakeKeychain()))) secrets: Secrets(keychain: FakeKeychain())))
} }
} }
#endif

View file

@ -7,8 +7,8 @@ struct ContentView: View {
@Environment(\.scenePhase) private var scenePhase @Environment(\.scenePhase) private var scenePhase
var body: some View { var body: some View {
if sceneViewModel.identity != nil { if let identity = sceneViewModel.identity {
mainNavigation mainNavigation(identity: identity)
.onChange(of: scenePhase) { .onChange(of: scenePhase) {
if case .active = $0 { if case .active = $0 {
sceneViewModel.refreshIdentity() sceneViewModel.refreshIdentity()
@ -22,11 +22,11 @@ struct ContentView: View {
} }
private extension ContentView { private extension ContentView {
private var mainNavigation: some View { private func mainNavigation(identity: Identity) -> some View {
#if os(macOS) #if os(macOS)
return SidebarNavigation().frame(minWidth: 900, maxWidth: .infinity, minHeight: 500, maxHeight: .infinity) return SidebarNavigation().frame(minWidth: 900, maxWidth: .infinity, minHeight: 500, maxHeight: .infinity)
#else #else
return TabNavigation() return TabNavigation(identity: identity)
#endif #endif
} }
@ -35,8 +35,11 @@ private extension ContentView {
} }
} }
//struct ContentView_Previews: PreviewProvider { #if DEBUG
// static var previews: some View { struct ContentView_Previews: PreviewProvider {
// ContentView() static var previews: some View {
// } ContentView()
//} .environmentObject(SceneViewModel.development)
}
}
#endif

View file

@ -0,0 +1,33 @@
// Copyright © 2020 Metabolist. All rights reserved.
import SwiftUI
struct SettingsView: View {
@StateObject var viewModel: SettingsViewModel
@EnvironmentObject var sceneViewModel: SceneViewModel
var body: some View {
NavigationView {
Form {
Text(viewModel.identity.handle)
}
.navigationBarTitle(Text("settings"), displayMode: .inline)
.navigationBarItems(
leading: Button {
sceneViewModel.presentingSettings.toggle()
} label: {
Image(systemName: "xmark.circle.fill").imageScale(.large)
})
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
#if DEBUG
struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
SettingsView(viewModel: SettingsViewModel(identity: .development))
.environmentObject(SceneViewModel.development)
}
}
#endif

View file

@ -8,8 +8,10 @@ struct TimelineView: View {
} }
} }
#if DEBUG
struct TimelineView_Previews: PreviewProvider { struct TimelineView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
TimelineView() TimelineView()
} }
} }
#endif

View file

@ -1,8 +1,12 @@
// Copyright © 2020 Metabolist. All rights reserved. // Copyright © 2020 Metabolist. All rights reserved.
import SwiftUI import SwiftUI
import KingfisherSwiftUI
import struct Kingfisher.DownsamplingImageProcessor
import struct Kingfisher.RoundCornerImageProcessor
struct TabNavigation: View { struct TabNavigation: View {
let identity: Identity
@EnvironmentObject var sceneViewModel: SceneViewModel @EnvironmentObject var sceneViewModel: SceneViewModel
var body: some View { var body: some View {
@ -11,6 +15,7 @@ struct TabNavigation: View {
NavigationView { NavigationView {
view(topLevelNavigation: topLevelNavigation) view(topLevelNavigation: topLevelNavigation)
} }
.navigationViewStyle(StackNavigationViewStyle())
.tabItem { .tabItem {
Label(topLevelNavigation.title, systemImage: topLevelNavigation.systemImageName) Label(topLevelNavigation.title, systemImage: topLevelNavigation.systemImageName)
.accessibility(label: Text(topLevelNavigation.title)) .accessibility(label: Text(topLevelNavigation.title))
@ -18,6 +23,10 @@ struct TabNavigation: View {
.tag(topLevelNavigation) .tag(topLevelNavigation)
} }
} }
.sheet(isPresented: $sceneViewModel.presentingSettings) {
SettingsView(viewModel: SettingsViewModel(identity: identity))
.environmentObject(sceneViewModel)
}
} }
} }
@ -27,7 +36,24 @@ private extension TabNavigation {
switch topLevelNavigation { switch topLevelNavigation {
case .timelines: case .timelines:
TimelineView() TimelineView()
.navigationBarTitle(sceneViewModel.identity?.handle ?? "", displayMode: .inline) .navigationBarTitle(identity.handle, displayMode: .inline)
.navigationBarItems(
leading: Button {
sceneViewModel.presentingSettings.toggle()
} label: {
KFImage(identity.account?.avatar
?? identity.instance?.thumbnail,
options: [
.processor(
DownsamplingImageProcessor(size: CGSize(width: 28, height: 28))
.append(another: RoundCornerImageProcessor(radius: .widthFraction(0.5)))
),
.scaleFactor(UIScreen.main.scale),
.cacheOriginalImage
])
.placeholder { Image(systemName: "gear") }
.renderingMode(.original)
})
default: Text(topLevelNavigation.title) default: Text(topLevelNavigation.title)
} }
} }
@ -36,8 +62,11 @@ private extension TabNavigation {
// MARK: Preview // MARK: Preview
#if DEBUG
struct TabNavigation_Previews: PreviewProvider { struct TabNavigation_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
TabNavigation() TabNavigation(identity: .development)
.environmentObject(SceneViewModel.development)
} }
} }
#endif