This commit is contained in:
Justin Mazzocchi 2020-08-26 14:35:06 -07:00
parent dd2f70a3f8
commit ea6b1edd3d
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
8 changed files with 42 additions and 39 deletions

View file

@ -52,23 +52,23 @@ extension AppEnvironment {
inMemoryContent: true) inMemoryContent: true)
} }
extension IdentitiesService { extension AllIdentitiesService {
static func fresh( static func fresh(
identityDatabase: IdentityDatabase = .fresh(), identityDatabase: IdentityDatabase = .fresh(),
keychainService: KeychainService = MockKeychainService(), keychainService: KeychainService = MockKeychainService(),
environment: AppEnvironment = .development) -> IdentitiesService { environment: AppEnvironment = .development) -> AllIdentitiesService {
IdentitiesService( AllIdentitiesService(
identityDatabase: identityDatabase, identityDatabase: identityDatabase,
environment: environment) environment: environment)
} }
static let development = IdentitiesService( static let development = AllIdentitiesService(
identityDatabase: .development, identityDatabase: .development,
environment: .development) environment: .development)
} }
extension IdentityService { extension IdentityService {
static let development = try! IdentitiesService.development.identityService(id: devIdentityID) static let development = try! AllIdentitiesService.development.identityService(id: devIdentityID)
} }
extension UserNotificationService { extension UserNotificationService {
@ -78,7 +78,7 @@ extension UserNotificationService {
extension RootViewModel { extension RootViewModel {
static let development = RootViewModel( static let development = RootViewModel(
appDelegate: AppDelegate(), appDelegate: AppDelegate(),
identitiesService: .development, allIdentitiesService: .development,
userNotificationService: .development) userNotificationService: .development)
} }
@ -113,7 +113,8 @@ extension NotificationTypesPreferencesViewModel {
} }
extension StatusListViewModel { extension StatusListViewModel {
static let development = StatusListViewModel(statusListService: IdentityService.development.service(timeline: .home)) static let development = StatusListViewModel(
statusListService: IdentityService.development.service(timeline: .home))
} }
// swiftlint:enable force_try // swiftlint:enable force_try

View file

@ -213,8 +213,8 @@
D0EC8DC624DF842700A08489 /* KeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DC424DF842700A08489 /* KeychainService.swift */; }; D0EC8DC624DF842700A08489 /* KeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DC424DF842700A08489 /* KeychainService.swift */; };
D0EC8DC824DF8B3C00A08489 /* SecretsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DC724DF8B3C00A08489 /* SecretsService.swift */; }; D0EC8DC824DF8B3C00A08489 /* SecretsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DC724DF8B3C00A08489 /* SecretsService.swift */; };
D0EC8DC924DF8B3C00A08489 /* SecretsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DC724DF8B3C00A08489 /* SecretsService.swift */; }; D0EC8DC924DF8B3C00A08489 /* SecretsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DC724DF8B3C00A08489 /* SecretsService.swift */; };
D0EC8DCB24DFA06700A08489 /* IdentitiesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DCA24DFA06700A08489 /* IdentitiesService.swift */; }; D0EC8DCB24DFA06700A08489 /* AllIdentitiesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DCA24DFA06700A08489 /* AllIdentitiesService.swift */; };
D0EC8DCC24DFA06700A08489 /* IdentitiesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DCA24DFA06700A08489 /* IdentitiesService.swift */; }; D0EC8DCC24DFA06700A08489 /* AllIdentitiesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DCA24DFA06700A08489 /* AllIdentitiesService.swift */; };
D0EC8DCE24DFB64200A08489 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DCD24DFB64200A08489 /* AuthenticationService.swift */; }; D0EC8DCE24DFB64200A08489 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DCD24DFB64200A08489 /* AuthenticationService.swift */; };
D0EC8DCF24DFB64200A08489 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DCD24DFB64200A08489 /* AuthenticationService.swift */; }; D0EC8DCF24DFB64200A08489 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DCD24DFB64200A08489 /* AuthenticationService.swift */; };
D0EC8DD424DFE38900A08489 /* AuthenticationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DD324DFE38900A08489 /* AuthenticationServiceTests.swift */; }; D0EC8DD424DFE38900A08489 /* AuthenticationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EC8DD324DFE38900A08489 /* AuthenticationServiceTests.swift */; };
@ -394,7 +394,7 @@
D0EC8DC124DF7D9C00A08489 /* IdentityService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IdentityService.swift; sourceTree = "<group>"; }; D0EC8DC124DF7D9C00A08489 /* IdentityService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IdentityService.swift; sourceTree = "<group>"; };
D0EC8DC424DF842700A08489 /* KeychainService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainService.swift; sourceTree = "<group>"; }; D0EC8DC424DF842700A08489 /* KeychainService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainService.swift; sourceTree = "<group>"; };
D0EC8DC724DF8B3C00A08489 /* SecretsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsService.swift; sourceTree = "<group>"; }; D0EC8DC724DF8B3C00A08489 /* SecretsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsService.swift; sourceTree = "<group>"; };
D0EC8DCA24DFA06700A08489 /* IdentitiesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentitiesService.swift; sourceTree = "<group>"; }; D0EC8DCA24DFA06700A08489 /* AllIdentitiesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllIdentitiesService.swift; sourceTree = "<group>"; };
D0EC8DCD24DFB64200A08489 /* AuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationService.swift; sourceTree = "<group>"; }; D0EC8DCD24DFB64200A08489 /* AuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationService.swift; sourceTree = "<group>"; };
D0EC8DD324DFE38900A08489 /* AuthenticationServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceTests.swift; sourceTree = "<group>"; }; D0EC8DD324DFE38900A08489 /* AuthenticationServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceTests.swift; sourceTree = "<group>"; };
D0EC8DD724E096C900A08489 /* UserNotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationService.swift; sourceTree = "<group>"; }; D0EC8DD724E096C900A08489 /* UserNotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationService.swift; sourceTree = "<group>"; };
@ -533,7 +533,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D0EC8DCD24DFB64200A08489 /* AuthenticationService.swift */, D0EC8DCD24DFB64200A08489 /* AuthenticationService.swift */,
D0EC8DCA24DFA06700A08489 /* IdentitiesService.swift */, D0EC8DCA24DFA06700A08489 /* AllIdentitiesService.swift */,
D0EC8DC124DF7D9C00A08489 /* IdentityService.swift */, D0EC8DC124DF7D9C00A08489 /* IdentityService.swift */,
D0EC8DC424DF842700A08489 /* KeychainService.swift */, D0EC8DC424DF842700A08489 /* KeychainService.swift */,
D0EC8DC724DF8B3C00A08489 /* SecretsService.swift */, D0EC8DC724DF8B3C00A08489 /* SecretsService.swift */,
@ -1122,7 +1122,7 @@
D019E6F024DF7C2F00697C7D /* DatabaseError.swift in Sources */, D019E6F024DF7C2F00697C7D /* DatabaseError.swift in Sources */,
D019E6D724DF728400697C7D /* MastodonEncoder.swift in Sources */, D019E6D724DF728400697C7D /* MastodonEncoder.swift in Sources */,
D0EC8DE524E0B44500A08489 /* UserNotificationService.swift in Sources */, D0EC8DE524E0B44500A08489 /* UserNotificationService.swift in Sources */,
D0EC8DCB24DFA06700A08489 /* IdentitiesService.swift in Sources */, D0EC8DCB24DFA06700A08489 /* AllIdentitiesService.swift in Sources */,
D0091B7124DD68220040E8D2 /* PreferencesViewModel.swift in Sources */, D0091B7124DD68220040E8D2 /* PreferencesViewModel.swift in Sources */,
D0A2453724EF346800B07068 /* StatusListViewController.swift in Sources */, D0A2453724EF346800B07068 /* StatusListViewController.swift in Sources */,
D057426A24EA32AC00839EBA /* Timeline.swift in Sources */, D057426A24EA32AC00839EBA /* Timeline.swift in Sources */,
@ -1192,7 +1192,7 @@
D0ED1BC224CED48800B4899C /* HTTPClient.swift in Sources */, D0ED1BC224CED48800B4899C /* HTTPClient.swift in Sources */,
D0666A4C24C6C37700F3F04B /* Identity.swift in Sources */, D0666A4C24C6C37700F3F04B /* Identity.swift in Sources */,
D0EC8DE424E0B44400A08489 /* UserNotificationService.swift in Sources */, D0EC8DE424E0B44400A08489 /* UserNotificationService.swift in Sources */,
D0EC8DCC24DFA06700A08489 /* IdentitiesService.swift in Sources */, D0EC8DCC24DFA06700A08489 /* AllIdentitiesService.swift in Sources */,
D0666A5524C6C3E500F3F04B /* Emoji.swift in Sources */, D0666A5524C6C3E500F3F04B /* Emoji.swift in Sources */,
D019E6EE24DF7BF300697C7D /* IdentityDatabase.swift in Sources */, D019E6EE24DF7BF300697C7D /* IdentityDatabase.swift in Sources */,
D0A652AE24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */, D0A652AE24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */,

View file

@ -12,7 +12,7 @@ struct MetatextApp: App {
#endif #endif
// swiftlint:enable weak_delegate // swiftlint:enable weak_delegate
private let identitiesService: IdentitiesService = { private let allIdentitiesService: AllIdentitiesService = {
let identityDatabase: IdentityDatabase let identityDatabase: IdentityDatabase
do { do {
@ -21,14 +21,14 @@ struct MetatextApp: App {
fatalError("Failed to initialize identity database") fatalError("Failed to initialize identity database")
} }
return IdentitiesService(identityDatabase: identityDatabase, environment: .live) return AllIdentitiesService(identityDatabase: identityDatabase, environment: .live)
}() }()
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
RootView( RootView(
viewModel: RootViewModel(appDelegate: appDelegate, viewModel: RootViewModel(appDelegate: appDelegate,
identitiesService: identitiesService, allIdentitiesService: allIdentitiesService,
userNotificationService: UserNotificationService())) userNotificationService: UserNotificationService()))
} }
} }

View file

@ -3,7 +3,7 @@
import Foundation import Foundation
import Combine import Combine
struct IdentitiesService { struct AllIdentitiesService {
let mostRecentlyUsedIdentityID: AnyPublisher<UUID?, Never> let mostRecentlyUsedIdentityID: AnyPublisher<UUID?, Never>
private let identityDatabase: IdentityDatabase private let identityDatabase: IdentityDatabase
@ -19,7 +19,7 @@ struct IdentitiesService {
} }
} }
extension IdentitiesService { extension AllIdentitiesService {
func identityService(id: UUID) throws -> IdentityService { func identityService(id: UUID) throws -> IdentityService {
try IdentityService(identityID: id, try IdentityService(identityID: id,
identityDatabase: identityDatabase, identityDatabase: identityDatabase,

View file

@ -9,12 +9,12 @@ class AddIdentityViewModel: ObservableObject {
@Published private(set) var loading = false @Published private(set) var loading = false
let addedIdentityID: AnyPublisher<UUID, Never> let addedIdentityID: AnyPublisher<UUID, Never>
private let identitiesService: IdentitiesService private let allIdentitiesService: AllIdentitiesService
private let addedIdentityIDInput = PassthroughSubject<UUID, Never>() private let addedIdentityIDInput = PassthroughSubject<UUID, Never>()
private var cancellables = Set<AnyCancellable>() private var cancellables = Set<AnyCancellable>()
init(identitiesService: IdentitiesService) { init(allIdentitiesService: AllIdentitiesService) {
self.identitiesService = identitiesService self.allIdentitiesService = allIdentitiesService
addedIdentityID = addedIdentityIDInput.eraseToAnyPublisher() addedIdentityID = addedIdentityIDInput.eraseToAnyPublisher()
} }
@ -30,10 +30,10 @@ class AddIdentityViewModel: ObservableObject {
return return
} }
identitiesService.authorizeIdentity(id: identityID, instanceURL: instanceURL) allIdentitiesService.authorizeIdentity(id: identityID, instanceURL: instanceURL)
.collect() .collect()
.map { _ in (identityID, instanceURL) } .map { _ in (identityID, instanceURL) }
.flatMap(identitiesService.createIdentity(id:instanceURL:)) .flatMap(allIdentitiesService.createIdentity(id:instanceURL:))
.assignErrorsToAlertItem(to: \.alertItem, on: self) .assignErrorsToAlertItem(to: \.alertItem, on: self)
.receive(on: RunLoop.main) .receive(on: RunLoop.main)
.handleEvents( .handleEvents(
@ -60,7 +60,7 @@ class AddIdentityViewModel: ObservableObject {
} }
// TODO: Ensure instance has not disabled public preview // TODO: Ensure instance has not disabled public preview
identitiesService.createIdentity(id: identityID, instanceURL: instanceURL) allIdentitiesService.createIdentity(id: identityID, instanceURL: instanceURL)
.assignErrorsToAlertItem(to: \.alertItem, on: self) .assignErrorsToAlertItem(to: \.alertItem, on: self)
.sink { [weak self] in .sink { [weak self] in
guard let self = self, case .finished = $0 else { return } guard let self = self, case .finished = $0 else { return }

View file

@ -10,18 +10,18 @@ class RootViewModel: ObservableObject {
// swiftlint:disable weak_delegate // swiftlint:disable weak_delegate
private let appDelegate: AppDelegate private let appDelegate: AppDelegate
// swiftlint:enable weak_delegate // swiftlint:enable weak_delegate
private let identitiesService: IdentitiesService private let allIdentitiesService: AllIdentitiesService
private let userNotificationService: UserNotificationService private let userNotificationService: UserNotificationService
private var cancellables = Set<AnyCancellable>() private var cancellables = Set<AnyCancellable>()
init(appDelegate: AppDelegate, init(appDelegate: AppDelegate,
identitiesService: IdentitiesService, allIdentitiesService: AllIdentitiesService,
userNotificationService: UserNotificationService) { userNotificationService: UserNotificationService) {
self.appDelegate = appDelegate self.appDelegate = appDelegate
self.identitiesService = identitiesService self.allIdentitiesService = allIdentitiesService
self.userNotificationService = userNotificationService self.userNotificationService = userNotificationService
identitiesService.mostRecentlyUsedIdentityID.assign(to: &$mostRecentlyUsedIdentityID) allIdentitiesService.mostRecentlyUsedIdentityID.assign(to: &$mostRecentlyUsedIdentityID)
newIdentitySelected(id: mostRecentlyUsedIdentityID) newIdentitySelected(id: mostRecentlyUsedIdentityID)
@ -29,7 +29,7 @@ class RootViewModel: ObservableObject {
.filter { $0 } .filter { $0 }
.zip(appDelegate.registerForRemoteNotifications()) .zip(appDelegate.registerForRemoteNotifications())
.map { $1 } .map { $1 }
.flatMap(identitiesService.updatePushSubscriptions(deviceToken:)) .flatMap(allIdentitiesService.updatePushSubscriptions(deviceToken:))
.sink { _ in } receiveValue: { _ in } .sink { _ in } receiveValue: { _ in }
.store(in: &cancellables) .store(in: &cancellables)
} }
@ -46,7 +46,7 @@ extension RootViewModel {
let identityService: IdentityService let identityService: IdentityService
do { do {
identityService = try identitiesService.identityService(id: id) identityService = try allIdentitiesService.identityService(id: id)
} catch { } catch {
return return
} }
@ -74,12 +74,12 @@ extension RootViewModel {
} }
func deleteIdentity(_ identity: Identity) { func deleteIdentity(_ identity: Identity) {
identitiesService.deleteIdentity(identity) allIdentitiesService.deleteIdentity(identity)
.sink { _ in } receiveValue: { _ in } .sink { _ in } receiveValue: { _ in }
.store(in: &cancellables) .store(in: &cancellables)
} }
func addIdentityViewModel() -> AddIdentityViewModel { func addIdentityViewModel() -> AddIdentityViewModel {
AddIdentityViewModel(identitiesService: identitiesService) AddIdentityViewModel(allIdentitiesService: allIdentitiesService)
} }
} }

View file

@ -8,7 +8,7 @@ import CombineExpectations
class AddIdentityViewModelTests: XCTestCase { class AddIdentityViewModelTests: XCTestCase {
func testAddIdentity() throws { func testAddIdentity() throws {
let identityDatabase = IdentityDatabase.fresh() let identityDatabase = IdentityDatabase.fresh()
let sut = AddIdentityViewModel(identitiesService: .fresh(identityDatabase: identityDatabase)) let sut = AddIdentityViewModel(allIdentitiesService: .fresh(identityDatabase: identityDatabase))
let addedIDRecorder = sut.addedIdentityID.record() let addedIDRecorder = sut.addedIdentityID.record()
sut.urlFieldText = "https://mastodon.social" sut.urlFieldText = "https://mastodon.social"
@ -19,7 +19,7 @@ class AddIdentityViewModelTests: XCTestCase {
func testAddIdentityWithoutScheme() throws { func testAddIdentityWithoutScheme() throws {
let identityDatabase = IdentityDatabase.fresh() let identityDatabase = IdentityDatabase.fresh()
let sut = AddIdentityViewModel(identitiesService: .fresh(identityDatabase: identityDatabase)) let sut = AddIdentityViewModel(allIdentitiesService: .fresh(identityDatabase: identityDatabase))
let addedIDRecorder = sut.addedIdentityID.record() let addedIDRecorder = sut.addedIdentityID.record()
sut.urlFieldText = "mastodon.social" sut.urlFieldText = "mastodon.social"
@ -29,7 +29,7 @@ class AddIdentityViewModelTests: XCTestCase {
} }
func testInvalidURL() throws { func testInvalidURL() throws {
let sut = AddIdentityViewModel(identitiesService: .fresh()) let sut = AddIdentityViewModel(allIdentitiesService: .fresh())
let recorder = sut.$alertItem.record() let recorder = sut.$alertItem.record()
XCTAssertNil(try wait(for: recorder.next(), timeout: 1)) XCTAssertNil(try wait(for: recorder.next(), timeout: 1))
@ -46,11 +46,13 @@ class AddIdentityViewModelTests: XCTestCase {
let environment = AppEnvironment( let environment = AppEnvironment(
session: Session(configuration: .stubbing), session: Session(configuration: .stubbing),
webAuthSessionType: CanceledLoginMockWebAuthSession.self, webAuthSessionType: CanceledLoginMockWebAuthSession.self,
keychainServiceType: MockKeychainService.self) keychainServiceType: MockKeychainService.self,
let identitiesService = IdentitiesService( userDefaults: MockUserDefaults(),
inMemoryContent: true)
let allIdentitiesService = AllIdentitiesService(
identityDatabase: .fresh(), identityDatabase: .fresh(),
environment: environment) environment: environment)
let sut = AddIdentityViewModel(identitiesService: identitiesService) let sut = AddIdentityViewModel(allIdentitiesService: allIdentitiesService)
let recorder = sut.$alertItem.record() let recorder = sut.$alertItem.record()
XCTAssertNil(try wait(for: recorder.next(), timeout: 1)) XCTAssertNil(try wait(for: recorder.next(), timeout: 1))

View file

@ -10,7 +10,7 @@ class RootViewModelTests: XCTestCase {
func testAddIdentity() throws { func testAddIdentity() throws {
let sut = RootViewModel(appDelegate: AppDelegate(), let sut = RootViewModel(appDelegate: AppDelegate(),
identitiesService: IdentitiesService( allIdentitiesService: AllIdentitiesService(
identityDatabase: .fresh(), identityDatabase: .fresh(),
environment: .development), environment: .development),
userNotificationService: UserNotificationService()) userNotificationService: UserNotificationService())