diff --git a/Development Assets/DevelopmentModels.swift b/Development Assets/DevelopmentModels.swift index 9002158..0691bc0 100644 --- a/Development Assets/DevelopmentModels.swift +++ b/Development Assets/DevelopmentModels.swift @@ -92,6 +92,10 @@ extension AppEnvironment { webAuthSessionType: SuccessfulStubbingWebAuthSession.self) } +extension IdentityRepository { + static let development = try! IdentityRepository(identityID: devIdentityID, appEnvironment: .development) +} + extension RootViewModel { static let development = RootViewModel(environment: .development) } @@ -100,20 +104,22 @@ extension MainNavigationViewModel { static let development = RootViewModel.development.mainNavigationViewModel(identityID: devIdentityID)! } +#if os(iOS) extension SecondaryNavigationViewModel { static let development = MainNavigationViewModel.development.secondaryNavigationViewModel() } extension IdentitiesViewModel { - static let development = SecondaryNavigationViewModel.development.identitiesViewModel() + static let development = IdentitiesViewModel(identityRepository: .development) } +#endif extension PreferencesViewModel { - static let development = SecondaryNavigationViewModel.development.preferencesViewModel() + static let development = PreferencesViewModel(identityRepository: .development) } extension PostingReadingPreferencesViewModel { - static let development = PreferencesViewModel.development.postingReadingPreferencesViewModel() + static let development = PostingReadingPreferencesViewModel(identityRepository: .development) } // swiftlint:enable force_try diff --git a/Metatext.xcodeproj/project.pbxproj b/Metatext.xcodeproj/project.pbxproj index 6c28b60..701436e 100644 --- a/Metatext.xcodeproj/project.pbxproj +++ b/Metatext.xcodeproj/project.pbxproj @@ -17,14 +17,18 @@ D0091B7224DD68220040E8D2 /* PreferencesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0091B7024DD68220040E8D2 /* PreferencesViewModel.swift */; }; D0091B7424DDF4860040E8D2 /* IdentityRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0091B7324DDF4860040E8D2 /* IdentityRepository.swift */; }; D0091B7524DDF4860040E8D2 /* IdentityRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0091B7324DDF4860040E8D2 /* IdentityRepository.swift */; }; + D0159F8624DE742F00E78478 /* TabNavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0159F8324DE742F00E78478 /* TabNavigationViewModel.swift */; }; + D0159F8824DE742F00E78478 /* SecondaryNavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0159F8424DE742F00E78478 /* SecondaryNavigationViewModel.swift */; }; + D0159F8A24DE742F00E78478 /* IdentitiesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0159F8524DE742F00E78478 /* IdentitiesViewModel.swift */; }; + D0159F8F24DE743700E78478 /* IdentitiesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0159F8C24DE743700E78478 /* IdentitiesView.swift */; }; + D0159F9124DE743700E78478 /* TabNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0159F8D24DE743700E78478 /* TabNavigationView.swift */; }; + D0159F9324DE743700E78478 /* SecondaryNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0159F8E24DE743700E78478 /* SecondaryNavigationView.swift */; }; + D0159F9B24DE748900E78478 /* SidebarNavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0159F9524DE743E00E78478 /* SidebarNavigationViewModel.swift */; }; + D0159F9C24DE748C00E78478 /* SidebarNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0159F9824DE744500E78478 /* SidebarNavigationView.swift */; }; D047FAAE24C3E21200AF17C5 /* 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 */; }; D047FAB324C3E21200AF17C5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D047FA8724C3E21200AF17C5 /* Assets.xcassets */; }; - D04FD73324D48F37007D572D /* SecondaryNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73224D48F37007D572D /* SecondaryNavigationView.swift */; }; - D04FD73424D48F37007D572D /* SecondaryNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73224D48F37007D572D /* SecondaryNavigationView.swift */; }; - D04FD73624D49506007D572D /* SecondaryNavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73524D49506007D572D /* SecondaryNavigationViewModel.swift */; }; - D04FD73724D49506007D572D /* SecondaryNavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04FD73524D49506007D572D /* SecondaryNavigationViewModel.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 */; }; @@ -38,8 +42,6 @@ D052BBD024D750C000A80A7A /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D052BBCE24D750C000A80A7A /* Defaults.swift */; }; D052BBD124D750CA00A80A7A /* AppEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D052BBCC24D750A100A80A7A /* AppEnvironment.swift */; }; D052BBD224D750CB00A80A7A /* AppEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D052BBCC24D750A100A80A7A /* AppEnvironment.swift */; }; - D052BBE024D805E300A80A7A /* MainNavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D052BBDF24D805E300A80A7A /* MainNavigationViewModel.swift */; }; - D052BBE124D805E300A80A7A /* MainNavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D052BBDF24D805E300A80A7A /* MainNavigationViewModel.swift */; }; D065F53924D37E5100741304 /* CombineExpectations in Frameworks */ = {isa = PBXBuildFile; productRef = D065F53824D37E5100741304 /* CombineExpectations */; }; 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 */; }; @@ -73,10 +75,6 @@ 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 */; }; - D06BAB4E24D942BD0081B8FD /* IdentitiesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06BAB4D24D942BC0081B8FD /* IdentitiesViewModel.swift */; }; - D06BAB4F24D942BD0081B8FD /* IdentitiesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06BAB4D24D942BC0081B8FD /* IdentitiesViewModel.swift */; }; - D06BAB5124D942CF0081B8FD /* IdentitiesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06BAB5024D942CF0081B8FD /* IdentitiesView.swift */; }; - D06BAB5224D942CF0081B8FD /* IdentitiesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06BAB5024D942CF0081B8FD /* IdentitiesView.swift */; }; D074577724D29006004758DB /* StubbingWebAuthSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577624D29006004758DB /* StubbingWebAuthSession.swift */; }; D074577824D29006004758DB /* StubbingWebAuthSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577624D29006004758DB /* StubbingWebAuthSession.swift */; }; D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */; }; @@ -97,8 +95,6 @@ D0BEC94824CA22C400E864C4 /* TimelineViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEC94624CA22C400E864C4 /* TimelineViewModel.swift */; }; D0BEC94A24CA231200E864C4 /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEC94924CA231200E864C4 /* TimelineView.swift */; }; D0BEC94B24CA231200E864C4 /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEC94924CA231200E864C4 /* TimelineView.swift */; }; - D0BEC94F24CA2B5300E864C4 /* SidebarNavigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEC94E24CA2B5300E864C4 /* SidebarNavigation.swift */; }; - D0BEC95124CA2B7E00E864C4 /* TabNavigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEC95024CA2B7E00E864C4 /* TabNavigation.swift */; }; D0C963FB24CC359D003BD330 /* AlertItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C963FA24CC359D003BD330 /* AlertItem.swift */; }; D0C963FC24CC359D003BD330 /* AlertItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C963FA24CC359D003BD330 /* AlertItem.swift */; }; D0C963FE24CC3812003BD330 /* Publisher+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C963FD24CC3812003BD330 /* Publisher+Extensions.swift */; }; @@ -176,6 +172,14 @@ D0091B6D24DD68090040E8D2 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; D0091B7024DD68220040E8D2 /* PreferencesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesViewModel.swift; sourceTree = ""; }; D0091B7324DDF4860040E8D2 /* IdentityRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityRepository.swift; sourceTree = ""; }; + D0159F8324DE742F00E78478 /* TabNavigationViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabNavigationViewModel.swift; sourceTree = ""; }; + D0159F8424DE742F00E78478 /* SecondaryNavigationViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondaryNavigationViewModel.swift; sourceTree = ""; }; + D0159F8524DE742F00E78478 /* IdentitiesViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IdentitiesViewModel.swift; sourceTree = ""; }; + D0159F8C24DE743700E78478 /* IdentitiesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IdentitiesView.swift; sourceTree = ""; }; + D0159F8D24DE743700E78478 /* TabNavigationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabNavigationView.swift; sourceTree = ""; }; + D0159F8E24DE743700E78478 /* SecondaryNavigationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondaryNavigationView.swift; sourceTree = ""; }; + D0159F9524DE743E00E78478 /* SidebarNavigationViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SidebarNavigationViewModel.swift; sourceTree = ""; }; + D0159F9824DE744500E78478 /* SidebarNavigationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SidebarNavigationView.swift; sourceTree = ""; }; D047FA8524C3E21000AF17C5 /* MetatextApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetatextApp.swift; sourceTree = ""; }; D047FA8724C3E21200AF17C5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; D047FA8C24C3E21200AF17C5 /* Metatext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metatext.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -183,8 +187,6 @@ 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 = ""; }; D047FA9724C3E21200AF17C5 /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = ""; }; - D04FD73224D48F37007D572D /* SecondaryNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondaryNavigationView.swift; sourceTree = ""; }; - D04FD73524D49506007D572D /* SecondaryNavigationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondaryNavigationViewModel.swift; sourceTree = ""; }; D04FD73824D4A7B4007D572D /* AccountEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountEndpoint+Stubbing.swift"; sourceTree = ""; }; D04FD73B24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "InstanceEndpoint+Stubbing.swift"; sourceTree = ""; }; D04FD74124D4AA34007D572D /* DevelopmentModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevelopmentModels.swift; sourceTree = ""; }; @@ -192,7 +194,6 @@ D052BBC824D74B6400A80A7A /* FakeUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeUserDefaults.swift; sourceTree = ""; }; D052BBCC24D750A100A80A7A /* AppEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppEnvironment.swift; sourceTree = ""; }; D052BBCE24D750C000A80A7A /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = ""; }; - D052BBDF24D805E300A80A7A /* MainNavigationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainNavigationViewModel.swift; sourceTree = ""; }; D065F53A24D3B33A00741304 /* View+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = ""; }; D065F53D24D3D20300741304 /* InstanceEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceEndpoint.swift; sourceTree = ""; }; D0666A2124C677B400F3F04B /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -209,8 +210,6 @@ D0666A6E24C6DFB300F3F04B /* AccessToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessToken.swift; sourceTree = ""; }; D0666A7124C6E0D300F3F04B /* Secrets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = ""; }; D06B491E24D3F7FE00642749 /* Localizable.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = ""; }; - D06BAB4D24D942BC0081B8FD /* IdentitiesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentitiesViewModel.swift; sourceTree = ""; }; - D06BAB5024D942CF0081B8FD /* IdentitiesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentitiesView.swift; sourceTree = ""; }; D074577624D29006004758DB /* StubbingWebAuthSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StubbingWebAuthSession.swift; sourceTree = ""; }; D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSessionConfiguration+Extensions.swift"; sourceTree = ""; }; D081A40424D0F1A8001B016E /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; @@ -221,8 +220,6 @@ D0BEC93A24C96FD500E864C4 /* RootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = ""; }; D0BEC94624CA22C400E864C4 /* TimelineViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewModel.swift; sourceTree = ""; }; D0BEC94924CA231200E864C4 /* TimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineView.swift; sourceTree = ""; }; - D0BEC94E24CA2B5300E864C4 /* SidebarNavigation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarNavigation.swift; sourceTree = ""; }; - D0BEC95024CA2B7E00E864C4 /* TabNavigation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabNavigation.swift; sourceTree = ""; }; D0C963FA24CC359D003BD330 /* AlertItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertItem.swift; sourceTree = ""; }; D0C963FD24CC3812003BD330 /* Publisher+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Publisher+Extensions.swift"; sourceTree = ""; }; D0CD847224DBDEC700CF380C /* MastodonPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonPreferences.swift; sourceTree = ""; }; @@ -286,6 +283,42 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + D0159F7F24DE739000E78478 /* Views */ = { + isa = PBXGroup; + children = ( + D0159F8C24DE743700E78478 /* IdentitiesView.swift */, + D0159F8E24DE743700E78478 /* SecondaryNavigationView.swift */, + D0159F8D24DE743700E78478 /* TabNavigationView.swift */, + ); + path = Views; + sourceTree = ""; + }; + D0159F8024DE739500E78478 /* View Models */ = { + isa = PBXGroup; + children = ( + D0159F8524DE742F00E78478 /* IdentitiesViewModel.swift */, + D0159F8424DE742F00E78478 /* SecondaryNavigationViewModel.swift */, + D0159F8324DE742F00E78478 /* TabNavigationViewModel.swift */, + ); + path = "View Models"; + sourceTree = ""; + }; + D0159F8124DE739D00E78478 /* Views */ = { + isa = PBXGroup; + children = ( + D0159F9824DE744500E78478 /* SidebarNavigationView.swift */, + ); + path = Views; + sourceTree = ""; + }; + D0159F8224DE73A300E78478 /* View Models */ = { + isa = PBXGroup; + children = ( + D0159F9524DE743E00E78478 /* SidebarNavigationViewModel.swift */, + ); + path = "View Models"; + sourceTree = ""; + }; D047FA7F24C3E21000AF17C5 = { isa = PBXGroup; children = ( @@ -328,7 +361,8 @@ isa = PBXGroup; children = ( D047FA8F24C3E21200AF17C5 /* Info.plist */, - D0BEC95024CA2B7E00E864C4 /* TabNavigation.swift */, + D0159F8024DE739500E78478 /* View Models */, + D0159F7F24DE739000E78478 /* Views */, ); path = iOS; sourceTree = ""; @@ -338,7 +372,8 @@ children = ( D047FA9624C3E21200AF17C5 /* Info.plist */, D047FA9724C3E21200AF17C5 /* macOS.entitlements */, - D0BEC94E24CA2B5300E864C4 /* SidebarNavigation.swift */, + D0159F8224DE73A300E78478 /* View Models */, + D0159F8124DE739D00E78478 /* Views */, ); path = macOS; sourceTree = ""; @@ -397,11 +432,9 @@ isa = PBXGroup; children = ( D0DB6EF324C5228A00D965FE /* AddIdentityView.swift */, - D06BAB5024D942CF0081B8FD /* IdentitiesView.swift */, D0091B6724DC10B30040E8D2 /* PostingReadingPreferencesView.swift */, D0091B6D24DD68090040E8D2 /* PreferencesView.swift */, D0BEC93A24C96FD500E864C4 /* RootView.swift */, - D04FD73224D48F37007D572D /* SecondaryNavigationView.swift */, D0BEC94924CA231200E864C4 /* TimelineView.swift */, ); path = Views; @@ -424,12 +457,9 @@ isa = PBXGroup; children = ( D0DB6F0824C65AC000D965FE /* AddIdentityViewModel.swift */, - D06BAB4D24D942BC0081B8FD /* IdentitiesViewModel.swift */, - D052BBDF24D805E300A80A7A /* MainNavigationViewModel.swift */, D0091B6A24DC10CE0040E8D2 /* PostingReadingPreferencesViewModel.swift */, D0091B7024DD68220040E8D2 /* PreferencesViewModel.swift */, D0BEC93724C9632800E864C4 /* RootViewModel.swift */, - D04FD73524D49506007D572D /* SecondaryNavigationViewModel.swift */, D0BEC94624CA22C400E864C4 /* TimelineViewModel.swift */, ); path = "View Models"; @@ -703,10 +733,11 @@ D0ED1BE324CFA84400B4899C /* MastodonError.swift in Sources */, D0666A6324C6DC6C00F3F04B /* AppAuthorization.swift in Sources */, D065F53B24D3B33A00741304 /* View+Extensions.swift in Sources */, - D04FD73324D48F37007D572D /* SecondaryNavigationView.swift in Sources */, D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */, + D0159F8A24DE742F00E78478 /* IdentitiesViewModel.swift in Sources */, D0666A5A24C6C64100F3F04B /* MastodonEncoder.swift in Sources */, D0666A5124C6C3BC00F3F04B /* Account.swift in Sources */, + D0159F8824DE742F00E78478 /* SecondaryNavigationViewModel.swift in Sources */, D0ED1BE024CF98FB00B4899C /* AccountEndpoint.swift in Sources */, D052BBD224D750CB00A80A7A /* AppEnvironment.swift in Sources */, D081A40524D0F1A8001B016E /* String+Extensions.swift in Sources */, @@ -715,18 +746,17 @@ D0666A4524C6BC0A00F3F04B /* DatabaseError.swift in Sources */, D0ED1BDD24CF982600B4899C /* AccessTokenEndpoint.swift in Sources */, D0CD847F24DBF1BB00CF380C /* PreferencesEndpoint.swift in Sources */, + D0159F9324DE743700E78478 /* SecondaryNavigationView.swift in Sources */, D0666A4B24C6C37700F3F04B /* Identity.swift in Sources */, D0666A5424C6C3E500F3F04B /* Emoji.swift in Sources */, D0A652AD24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift in Sources */, D0DC175524D00F0A00A75C65 /* AccessTokenEndpoint+Stubbing.swift in Sources */, D0B23F0D24D210E90066F411 /* NSError+Extensions.swift in Sources */, D052BBCA24D74C9200A80A7A /* FakeUserDefaults.swift in Sources */, - D06BAB4E24D942BD0081B8FD /* IdentitiesViewModel.swift in Sources */, D0DC175224D008E300A75C65 /* MastodonTarget+Stubbing.swift in Sources */, D0666A4224C6BB7B00F3F04B /* IdentityDatabase.swift in Sources */, D0BEC94A24CA231200E864C4 /* TimelineView.swift in Sources */, D0BEC93B24C96FD500E864C4 /* RootView.swift in Sources */, - D04FD73624D49506007D572D /* SecondaryNavigationViewModel.swift in Sources */, D04FD74224D4AA34007D572D /* DevelopmentModels.swift in Sources */, D0DC175824D0130800A75C65 /* HTTPStubs.swift in Sources */, D0DC177724D0CF2600A75C65 /* FakeKeychain.swift in Sources */, @@ -735,18 +765,19 @@ D0091B7124DD68220040E8D2 /* PreferencesViewModel.swift in Sources */, D0DC174D24CFF1F100A75C65 /* Stubbing.swift in Sources */, D0091B6B24DC10CE0040E8D2 /* PostingReadingPreferencesViewModel.swift in Sources */, + D0159F8624DE742F00E78478 /* TabNavigationViewModel.swift in Sources */, D0666A5724C6C63400F3F04B /* MastodonDecoder.swift in Sources */, D0091B6E24DD68090040E8D2 /* PreferencesView.swift in Sources */, + D0159F8F24DE743700E78478 /* IdentitiesView.swift in Sources */, D0DB6EF424C5228A00D965FE /* AddIdentityView.swift in Sources */, D0DC177424D0B58800A75C65 /* Keychain.swift in Sources */, - D06BAB5124D942CF0081B8FD /* IdentitiesView.swift in Sources */, D074577724D29006004758DB /* StubbingWebAuthSession.swift in Sources */, D0ED1BCE24CF768200B4899C /* MastodonEndpoint.swift in Sources */, D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */, D0ED1BB724CE47F400B4899C /* WebAuthSession.swift in Sources */, D0666A7224C6E0D300F3F04B /* Secrets.swift in Sources */, - D0BEC95124CA2B7E00E864C4 /* TabNavigation.swift in Sources */, D0A1CA7424DAC2F1003063E9 /* KingfisherOptionsInfo+Extensions.swift in Sources */, + D0159F9124DE743700E78478 /* TabNavigationView.swift in Sources */, D0ED1BC424CED54D00B4899C /* HTTPTarget.swift in Sources */, D0C963FE24CC3812003BD330 /* Publisher+Extensions.swift in Sources */, D04FD73C24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */, @@ -758,7 +789,6 @@ D0ED1BCB24CF744200B4899C /* MastodonClient.swift in Sources */, D0091B6824DC10B30040E8D2 /* PostingReadingPreferencesView.swift in Sources */, D0CD847624DBDF3C00CF380C /* Status.swift in Sources */, - D052BBE024D805E300A80A7A /* MainNavigationViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -779,7 +809,6 @@ D0ED1BE424CFA84400B4899C /* MastodonError.swift in Sources */, D0666A6424C6DC6C00F3F04B /* AppAuthorization.swift in Sources */, D065F53C24D3B33A00741304 /* View+Extensions.swift in Sources */, - D04FD73424D48F37007D572D /* SecondaryNavigationView.swift in Sources */, D0DC174B24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */, D0666A5B24C6C64100F3F04B /* MastodonEncoder.swift in Sources */, D0666A5224C6C3BC00F3F04B /* Account.swift in Sources */, @@ -797,12 +826,11 @@ D0DC175624D00F0A00A75C65 /* AccessTokenEndpoint+Stubbing.swift in Sources */, D0B23F0E24D210E90066F411 /* NSError+Extensions.swift in Sources */, D052BBCB24D74C9300A80A7A /* FakeUserDefaults.swift in Sources */, - D06BAB4F24D942BD0081B8FD /* IdentitiesViewModel.swift in Sources */, D0DC175324D008E300A75C65 /* MastodonTarget+Stubbing.swift in Sources */, D0666A4324C6BB7B00F3F04B /* IdentityDatabase.swift in Sources */, D0BEC94B24CA231200E864C4 /* TimelineView.swift in Sources */, D0BEC93C24C96FD500E864C4 /* RootView.swift in Sources */, - D04FD73724D49506007D572D /* SecondaryNavigationViewModel.swift in Sources */, + D0159F9B24DE748900E78478 /* SidebarNavigationViewModel.swift in Sources */, D04FD74324D4AA34007D572D /* DevelopmentModels.swift in Sources */, D0DC175924D0130800A75C65 /* HTTPStubs.swift in Sources */, D0DC177824D0CF2600A75C65 /* FakeKeychain.swift in Sources */, @@ -815,12 +843,11 @@ D0091B6F24DD68090040E8D2 /* PreferencesView.swift in Sources */, D0DB6EF524C5233E00D965FE /* AddIdentityView.swift in Sources */, D0DC177524D0B58800A75C65 /* Keychain.swift in Sources */, - D06BAB5224D942CF0081B8FD /* IdentitiesView.swift in Sources */, + D0159F9C24DE748C00E78478 /* SidebarNavigationView.swift in Sources */, D074577824D29006004758DB /* StubbingWebAuthSession.swift in Sources */, D0ED1BCF24CF768200B4899C /* MastodonEndpoint.swift in Sources */, D074577B24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */, D0ED1BB824CE47F400B4899C /* WebAuthSession.swift in Sources */, - D0BEC94F24CA2B5300E864C4 /* SidebarNavigation.swift in Sources */, D0666A7324C6E0D300F3F04B /* Secrets.swift in Sources */, D0A1CA7524DAC2F1003063E9 /* KingfisherOptionsInfo+Extensions.swift in Sources */, D0ED1BC524CED54D00B4899C /* HTTPTarget.swift in Sources */, @@ -834,7 +861,6 @@ D0ED1BCC24CF744200B4899C /* MastodonClient.swift in Sources */, D0091B6924DC10B30040E8D2 /* PostingReadingPreferencesView.swift in Sources */, D0CD847724DBDF3C00CF380C /* Status.swift in Sources */, - D052BBE124D805E300A80A7A /* MainNavigationViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Shared/Views/RootView.swift b/Shared/Views/RootView.swift index 112aee6..1830b87 100644 --- a/Shared/Views/RootView.swift +++ b/Shared/Views/RootView.swift @@ -2,6 +2,12 @@ import SwiftUI +#if os(macOS) +typealias MainNavigationViewModel = SidebarNavigationViewModel +#else +typealias MainNavigationViewModel = TabNavigationViewModel +#endif + struct RootView: View { @StateObject var viewModel: RootViewModel @@ -24,10 +30,10 @@ private extension RootView { @ViewBuilder private static func mainNavigation(mainNavigationViewModel: MainNavigationViewModel) -> some View { #if os(macOS) - SidebarNavigation(viewModel: mainNavigationViewModel) + SidebarNavigationView(viewModel: mainNavigationViewModel) .frame(minWidth: 900, maxWidth: .infinity, minHeight: 500, maxHeight: .infinity) #else - TabNavigation(viewModel: mainNavigationViewModel) + TabNavigationView(viewModel: mainNavigationViewModel) #endif } } diff --git a/Shared/Views/SecondaryNavigationView.swift b/Shared/Views/SecondaryNavigationView.swift deleted file mode 100644 index edd3399..0000000 --- a/Shared/Views/SecondaryNavigationView.swift +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright © 2020 Metabolist. All rights reserved. - -import SwiftUI -import KingfisherSwiftUI - -struct SecondaryNavigationView: View { - @StateObject var viewModel: SecondaryNavigationViewModel - @EnvironmentObject var rootViewModel: RootViewModel - @Environment(\.presentationMode) var presentationMode - @Environment(\.displayScale) var displayScale: CGFloat - - var body: some View { - VStack(spacing: 0) { - NavigationView { - Form { - Section { - NavigationLink( - destination: IdentitiesView(viewModel: viewModel.identitiesViewModel()) - .environmentObject(rootViewModel), - label: { - HStack { - KFImage(viewModel.identity.image, - options: .downsampled(dimension: 50, scaleFactor: displayScale)) - VStack(alignment: .leading) { - Text(viewModel.identity.handle) - .font(.headline) - .lineLimit(1) - .minimumScaleFactor(0.5) - Spacer() - Text("secondary-navigation.accounts") - .font(.subheadline) - .foregroundColor(.secondary) - } - .padding() - } - }) - } - Section { - NavigationLink( - "secondary-navigation.preferences", - destination: PreferencesView( - viewModel: viewModel.preferencesViewModel())) - } - } - .navigationItems(presentationMode: presentationMode) - } - .navigationViewStyle - #if os(macOS) - Divider() - HStack { - Spacer() - Button(action: { presentationMode.wrappedValue.dismiss() }) { - Text("Done") - } - .keyboardShortcut(.defaultAction) - } - .padding() - - #endif - } - .frame - } -} - -private extension View { - func navigationItems(presentationMode: Binding) -> some View { - #if os(iOS) - return navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .cancellationAction) { - Button { - presentationMode.wrappedValue.dismiss() - } label: { - Image(systemName: "xmark.circle.fill") - } - } - } - #else - return self - #endif - } - - var navigationViewStyle: some View { - #if os(iOS) - return navigationViewStyle(StackNavigationViewStyle()) - #else - return self - #endif - } - - var frame: some View { - #if os(macOS) - return frame(minWidth: 400, maxWidth: 600, minHeight: 350, maxHeight: 500) - #else - return self - #endif - } -} - -#if DEBUG -struct SecondaryNavigationView_Previews: PreviewProvider { - static var previews: some View { - SecondaryNavigationView(viewModel: .development) - .environmentObject(RootViewModel.development) - } -} -#endif diff --git a/Shared/View Models/IdentitiesViewModel.swift b/iOS/View Models/IdentitiesViewModel.swift similarity index 100% rename from Shared/View Models/IdentitiesViewModel.swift rename to iOS/View Models/IdentitiesViewModel.swift diff --git a/Shared/View Models/SecondaryNavigationViewModel.swift b/iOS/View Models/SecondaryNavigationViewModel.swift similarity index 100% rename from Shared/View Models/SecondaryNavigationViewModel.swift rename to iOS/View Models/SecondaryNavigationViewModel.swift diff --git a/Shared/View Models/MainNavigationViewModel.swift b/iOS/View Models/TabNavigationViewModel.swift similarity index 90% rename from Shared/View Models/MainNavigationViewModel.swift rename to iOS/View Models/TabNavigationViewModel.swift index 1321f5d..e2e0d2a 100644 --- a/Shared/View Models/MainNavigationViewModel.swift +++ b/iOS/View Models/TabNavigationViewModel.swift @@ -3,7 +3,7 @@ import Foundation import Combine -class MainNavigationViewModel: ObservableObject { +class TabNavigationViewModel: ObservableObject { @Published private(set) var identity: Identity @Published private(set) var recentIdentities = [Identity]() @Published var presentingSecondaryNavigation = false @@ -24,7 +24,7 @@ class MainNavigationViewModel: ObservableObject { } } -extension MainNavigationViewModel { +extension TabNavigationViewModel { func refreshIdentity() { if identityRepository.isAuthorized { identityRepository.verifyCredentials() @@ -51,7 +51,7 @@ extension MainNavigationViewModel { } } -extension MainNavigationViewModel { +extension TabNavigationViewModel { enum Tab: CaseIterable { case timelines case search @@ -60,7 +60,7 @@ extension MainNavigationViewModel { } } -extension MainNavigationViewModel.Tab { +extension TabNavigationViewModel.Tab { var title: String { switch self { case .timelines: return "Timelines" @@ -72,7 +72,7 @@ extension MainNavigationViewModel.Tab { var systemImageName: String { switch self { - case .timelines: return "house" + case .timelines: return "scroll" case .search: return "magnifyingglass" case .notifications: return "bell" case .messages: return "envelope" @@ -80,6 +80,6 @@ extension MainNavigationViewModel.Tab { } } -extension MainNavigationViewModel.Tab: Identifiable { +extension TabNavigationViewModel.Tab: Identifiable { var id: Self { self } } diff --git a/Shared/Views/IdentitiesView.swift b/iOS/Views/IdentitiesView.swift similarity index 100% rename from Shared/Views/IdentitiesView.swift rename to iOS/Views/IdentitiesView.swift diff --git a/iOS/Views/SecondaryNavigationView.swift b/iOS/Views/SecondaryNavigationView.swift new file mode 100644 index 0000000..4558869 --- /dev/null +++ b/iOS/Views/SecondaryNavigationView.swift @@ -0,0 +1,66 @@ +// Copyright © 2020 Metabolist. All rights reserved. + +import SwiftUI +import KingfisherSwiftUI + +struct SecondaryNavigationView: View { + @StateObject var viewModel: SecondaryNavigationViewModel + @EnvironmentObject var rootViewModel: RootViewModel + @Environment(\.presentationMode) var presentationMode + @Environment(\.displayScale) var displayScale: CGFloat + + var body: some View { + NavigationView { + Form { + Section { + NavigationLink( + destination: IdentitiesView(viewModel: viewModel.identitiesViewModel()) + .environmentObject(rootViewModel), + label: { + HStack { + KFImage(viewModel.identity.image, + options: .downsampled(dimension: 50, scaleFactor: displayScale)) + VStack(alignment: .leading) { + Text(viewModel.identity.handle) + .font(.headline) + .lineLimit(1) + .minimumScaleFactor(0.5) + Spacer() + Text("secondary-navigation.accounts") + .font(.subheadline) + .foregroundColor(.secondary) + } + .padding() + } + }) + } + Section { + NavigationLink( + "secondary-navigation.preferences", + destination: PreferencesView( + viewModel: viewModel.preferencesViewModel())) + } + } + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button { + presentationMode.wrappedValue.dismiss() + } label: { + Image(systemName: "xmark.circle.fill") + } + } + } + } + .navigationViewStyle(StackNavigationViewStyle()) + } +} + +#if DEBUG +struct SecondaryNavigationView_Previews: PreviewProvider { + static var previews: some View { + SecondaryNavigationView(viewModel: .development) + .environmentObject(RootViewModel.development) + } +} +#endif diff --git a/iOS/TabNavigation.swift b/iOS/Views/TabNavigationView.swift similarity index 90% rename from iOS/TabNavigation.swift rename to iOS/Views/TabNavigationView.swift index 4bfd418..6c565f5 100644 --- a/iOS/TabNavigation.swift +++ b/iOS/Views/TabNavigationView.swift @@ -3,14 +3,14 @@ import SwiftUI import KingfisherSwiftUI -struct TabNavigation: View { - @ObservedObject var viewModel: MainNavigationViewModel +struct TabNavigationView: View { + @ObservedObject var viewModel: TabNavigationViewModel @EnvironmentObject var rootViewModel: RootViewModel @Environment(\.displayScale) var displayScale: CGFloat var body: some View { TabView(selection: $viewModel.selectedTab) { - ForEach(MainNavigationViewModel.Tab.allCases) { tab in + ForEach(TabNavigationViewModel.Tab.allCases) { tab in NavigationView { view(tab: tab) } @@ -35,9 +35,9 @@ struct TabNavigation: View { } } -private extension TabNavigation { +private extension TabNavigationView { @ViewBuilder - func view(tab: MainNavigationViewModel.Tab) -> some View { + func view(tab: TabNavigationViewModel.Tab) -> some View { switch tab { case .timelines: TimelineView() @@ -74,7 +74,7 @@ private extension TabNavigation { #if DEBUG struct TabNavigation_Previews: PreviewProvider { static var previews: some View { - TabNavigation(viewModel: .development) + TabNavigationView(viewModel: .development) .environmentObject(RootViewModel.development) } } diff --git a/macOS/View Models/SidebarNavigationViewModel.swift b/macOS/View Models/SidebarNavigationViewModel.swift new file mode 100644 index 0000000..03c27a2 --- /dev/null +++ b/macOS/View Models/SidebarNavigationViewModel.swift @@ -0,0 +1,52 @@ +// Copyright © 2020 Metabolist. All rights reserved. + +import Foundation +import Combine + +class SidebarNavigationViewModel: ObservableObject { + @Published private(set) var identity: Identity + @Published var alertItem: AlertItem? + var selectedTab: Tab? = .timelines + + private let identityRepository: IdentityRepository + private var cancellables = Set() + + init(identityRepository: IdentityRepository) { + self.identityRepository = identityRepository + identity = identityRepository.identity + identityRepository.$identity.dropFirst().assign(to: &$identity) + } +} + +extension SidebarNavigationViewModel { + enum Tab: CaseIterable { + case timelines + case search + case notifications + case messages + } +} + +extension SidebarNavigationViewModel.Tab { + var title: String { + switch self { + case .timelines: return "Timelines" + case .search: return "Search" + case .notifications: return "Notifications" + case .messages: return "Messages" + } + } + + var systemImageName: String { + switch self { + case .timelines: return "scroll" + case .search: return "magnifyingglass" + case .notifications: return "bell" + case .messages: return "envelope" + } + } +} + +extension SidebarNavigationViewModel.Tab: Identifiable { + var id: Self { self } +} diff --git a/macOS/SidebarNavigation.swift b/macOS/Views/SidebarNavigationView.swift similarity index 66% rename from macOS/SidebarNavigation.swift rename to macOS/Views/SidebarNavigationView.swift index 3afecf7..7115410 100644 --- a/macOS/SidebarNavigation.swift +++ b/macOS/Views/SidebarNavigationView.swift @@ -2,16 +2,14 @@ import SwiftUI import KingfisherSwiftUI -import struct Kingfisher.DownsamplingImageProcessor -import struct Kingfisher.RoundCornerImageProcessor -struct SidebarNavigation: View { - @StateObject var viewModel: MainNavigationViewModel +struct SidebarNavigationView: View { + @StateObject var viewModel: SidebarNavigationViewModel @EnvironmentObject var rootViewModel: RootViewModel var sidebar: some View { List(selection: $viewModel.selectedTab) { - ForEach(MainNavigationViewModel.Tab.allCases) { tab in + ForEach(SidebarNavigationViewModel.Tab.allCases) { tab in NavigationLink(destination: view(topLevelNavigation: tab)) { Label(tab.title, systemImage: tab.systemImageName) } @@ -24,12 +22,6 @@ struct SidebarNavigation: View { .environmentObject(rootViewModel), alignment: .bottom) .listStyle(SidebarListStyle()) - .onAppear(perform: viewModel.refreshIdentity) - .onReceive(NotificationCenter.default - .publisher(for: NSWindow.didBecomeKeyNotification) - .dropFirst() - .map { _ in () }, - perform: viewModel.refreshIdentity) } var body: some View { @@ -42,8 +34,8 @@ struct SidebarNavigation: View { } } -private extension SidebarNavigation { - func view(topLevelNavigation: MainNavigationViewModel.Tab) -> some View { +private extension SidebarNavigationView { + func view(topLevelNavigation: SidebarNavigationViewModel.Tab) -> some View { Group { switch topLevelNavigation { case .timelines: @@ -54,14 +46,14 @@ private extension SidebarNavigation { } struct Pocket: View { - @EnvironmentObject var viewModel: MainNavigationViewModel + @EnvironmentObject var viewModel: SidebarNavigationViewModel @EnvironmentObject var rootViewModel: RootViewModel @Environment(\.displayScale) var displayScale: CGFloat var body: some View { VStack(alignment: .leading, spacing: 0) { Divider() - Button(action: { viewModel.presentingSecondaryNavigation.toggle() }) { + Button(action: { /*viewModel.presentingSecondaryNavigation.toggle()*/ }) { KFImage(viewModel.identity.image, options: .downsampled(dimension: 28, scaleFactor: displayScale)) .placeholder { Image(systemName: "gear") } @@ -76,11 +68,6 @@ private extension SidebarNavigation { .padding(.horizontal, 16) .buttonStyle(PlainButtonStyle()) } - .sheet(isPresented: $viewModel.presentingSecondaryNavigation) { - SecondaryNavigationView(viewModel: viewModel.secondaryNavigationViewModel()) - .environmentObject(viewModel) - .environmentObject(rootViewModel) - } } } } @@ -88,7 +75,7 @@ private extension SidebarNavigation { #if DEBUG struct SidebarNavigation_Previews: PreviewProvider { static var previews: some View { - SidebarNavigation(viewModel: .development) + SidebarNavigationView(viewModel: .development) .environmentObject(RootViewModel.development) } }