diff --git a/Localizations/de.lproj/Localizable.strings b/Localizations/de.lproj/Localizable.strings index 95fd69b..a3265ac 100644 --- a/Localizations/de.lproj/Localizable.strings +++ b/Localizations/de.lproj/Localizable.strings @@ -160,6 +160,7 @@ "registration.agree-to-server-rules-and-terms-of-service" = "Ich stimme den Serverregeln und Nutzungsbedingungen zu"; "registration.password-confirmation-mismatch" = "Das Passwort und die Passwortbestätigung stimmen nicht überein"; "secondary-navigation.about" = "Über diese App"; +"secondary-navigation.account-settings" = "Kontoeinstellungen"; "secondary-navigation.accounts" = "Accounts"; "secondary-navigation.lists" = "Listen"; "secondary-navigation.my-profile" = "Mein Profil"; diff --git a/Localizations/en.lproj/Localizable.strings b/Localizations/en.lproj/Localizable.strings index 1c8dfdd..4689fa2 100644 --- a/Localizations/en.lproj/Localizable.strings +++ b/Localizations/en.lproj/Localizable.strings @@ -160,6 +160,7 @@ "registration.agree-to-server-rules-and-terms-of-service" = "I agree to the server rules and terms of service"; "registration.password-confirmation-mismatch" = "Password and password confirmation do not match"; "secondary-navigation.about" = "About This App"; +"secondary-navigation.account-settings" = "Account Settings"; "secondary-navigation.accounts" = "Accounts"; "secondary-navigation.lists" = "Lists"; "secondary-navigation.my-profile" = "My Profile"; diff --git a/Localizations/es.lproj/Localizable.strings b/Localizations/es.lproj/Localizable.strings index 5a1211c..8894b6d 100644 --- a/Localizations/es.lproj/Localizable.strings +++ b/Localizations/es.lproj/Localizable.strings @@ -160,6 +160,7 @@ "registration.agree-to-server-rules-and-terms-of-service" = "Estoy de acuerdo con las reglas del servidor y los términos del servicio"; "registration.password-confirmation-mismatch" = "La contraseña no coincide con su confirmación"; "secondary-navigation.about" = "Acerca de esta aplicación"; +"secondary-navigation.account-settings" = "Configuración de Cuenta"; "secondary-navigation.accounts" = "Cuentas"; "secondary-navigation.lists" = "Listas"; "secondary-navigation.my-profile" = "Mi perfil"; diff --git a/Localizations/ja.lproj/Localizable.strings b/Localizations/ja.lproj/Localizable.strings index be00709..6e80048 100644 --- a/Localizations/ja.lproj/Localizable.strings +++ b/Localizations/ja.lproj/Localizable.strings @@ -160,6 +160,7 @@ "registration.agree-to-server-rules-and-terms-of-service" = "サーバーのルールとプライバシーポリシーに同意します"; "registration.password-confirmation-mismatch" = "パスワードと確認用パスワードが一致しません"; "secondary-navigation.about" = "このアプリについて"; +"secondary-navigation.account-settings" = "アカウント設定"; "secondary-navigation.accounts" = "アカウント"; "secondary-navigation.lists" = "リスト"; "secondary-navigation.my-profile" = "マイプロフィール"; diff --git a/Localizations/ko.lproj/Localizable.strings b/Localizations/ko.lproj/Localizable.strings index cb84f2f..805b1cb 100644 --- a/Localizations/ko.lproj/Localizable.strings +++ b/Localizations/ko.lproj/Localizable.strings @@ -160,6 +160,7 @@ "registration.agree-to-server-rules-and-terms-of-service" = "서버 규칙 및 개인정보처리방침에 동의해요"; "registration.password-confirmation-mismatch" = "입력한 비밀번호가 일치하지 않아요"; "secondary-navigation.about" = "이 앱에 대해서"; +"secondary-navigation.account-settings" = "계정 설정"; "secondary-navigation.accounts" = "계정"; "secondary-navigation.lists" = "목록"; "secondary-navigation.my-profile" = "내 프로필"; diff --git a/Localizations/pl.lproj/Localizable.strings b/Localizations/pl.lproj/Localizable.strings index 1823d5e..a3ac58b 100644 --- a/Localizations/pl.lproj/Localizable.strings +++ b/Localizations/pl.lproj/Localizable.strings @@ -160,6 +160,7 @@ "registration.agree-to-server-rules-and-terms-of-service" = "Zgadzam się na zasady stosowane na serwerze i warunki świadczenia usługi"; "registration.password-confirmation-mismatch" = "Hasło i powtórzone hasło się nie zgadzają"; "secondary-navigation.about" = "O aplikacji"; +"secondary-navigation.account-settings" = "Ustawienia konta"; "secondary-navigation.accounts" = "Konta"; "secondary-navigation.lists" = "Listy"; "secondary-navigation.my-profile" = "Mój profil"; diff --git a/Localizations/ru.lproj/Localizable.strings b/Localizations/ru.lproj/Localizable.strings index 23199ca..9ac2a0d 100644 --- a/Localizations/ru.lproj/Localizable.strings +++ b/Localizations/ru.lproj/Localizable.strings @@ -160,6 +160,7 @@ "registration.agree-to-server-rules-and-terms-of-service" = "Я принимаю правила сервера и условия предоставления услуг"; "registration.password-confirmation-mismatch" = "Пароли не совпадают"; "secondary-navigation.about" = "О приложении"; +"secondary-navigation.account-settings" = "Настройки аккаунта"; "secondary-navigation.accounts" = "Аккаунты"; "secondary-navigation.lists" = "Списки"; "secondary-navigation.my-profile" = "Профиль"; diff --git a/Localizations/zh-Hans.lproj/Localizable.strings b/Localizations/zh-Hans.lproj/Localizable.strings index f57f3a5..76c88d0 100644 --- a/Localizations/zh-Hans.lproj/Localizable.strings +++ b/Localizations/zh-Hans.lproj/Localizable.strings @@ -160,6 +160,7 @@ "registration.agree-to-server-rules-and-terms-of-service" = "我同意实例规则和服务条款"; "registration.password-confirmation-mismatch" = "密码和确认密码不匹配"; "secondary-navigation.about" = "关于这个应用"; +"secondary-navigation.account-settings" = "账号设置"; "secondary-navigation.accounts" = "账户"; "secondary-navigation.lists" = "列表"; "secondary-navigation.my-profile" = "我的个人资料"; diff --git a/ServiceLayer/Sources/ServiceLayer/Services/AccountSettingsService.swift b/ServiceLayer/Sources/ServiceLayer/Services/AccountSettingsService.swift new file mode 100644 index 0000000..4a0e7d0 --- /dev/null +++ b/ServiceLayer/Sources/ServiceLayer/Services/AccountSettingsService.swift @@ -0,0 +1,41 @@ +// +// File.swift +// +// +// Created by Justin Mazzocchi on 11/8/22. +// + +import Combine +import Foundation + +public struct AccountSettingsService { + private let instanceURI: String + private let webAuthSessionType: WebAuthSession.Type + private let webAuthSessionContextProvider = WebAuthSessionContextProvider() + + public init(instanceURI: String, environment: AppEnvironment) { + self.instanceURI = instanceURI + webAuthSessionType = environment.webAuthSessionType + } +} + +public extension AccountSettingsService { + func openAccountSettings() -> AnyPublisher { + guard let url = URL(string: "https://\(instanceURI)/auth/edit") else { + return Fail(error: URLError(.badURL)).eraseToAnyPublisher() + } + + print(webAuthSessionContextProvider) + + return webAuthSessionType.publisher( + url: url, + callbackURLScheme: nil, + presentationContextProvider: webAuthSessionContextProvider) + } +} + +private extension AccountSettingsService { + func accountSettingsURL(instanceURI: String) -> URL? { + URL(string: "https://\(instanceURI)/auth/edit") + } +} diff --git a/ServiceLayer/Sources/ServiceLayer/Utilities/WebAuthSession.swift b/ServiceLayer/Sources/ServiceLayer/Utilities/WebAuthSession.swift index fc876f3..c068206 100644 --- a/ServiceLayer/Sources/ServiceLayer/Utilities/WebAuthSession.swift +++ b/ServiceLayer/Sources/ServiceLayer/Utilities/WebAuthSession.swift @@ -30,9 +30,8 @@ extension WebAuthSession { } } - webAuthSession.presentationContextProvider = presentationContextProvider - DispatchQueue.main.async { + webAuthSession.presentationContextProvider = presentationContextProvider webAuthSession.start() } } diff --git a/ViewModels/Sources/PreviewViewModels/PreviewViewModels.swift b/ViewModels/Sources/PreviewViewModels/PreviewViewModels.swift index 8859fb1..85d4410 100644 --- a/ViewModels/Sources/PreviewViewModels/PreviewViewModels.swift +++ b/ViewModels/Sources/PreviewViewModels/PreviewViewModels.swift @@ -56,6 +56,10 @@ extension ContentDatabase { keychain: MockKeychain.self) } +public extension AppEnvironment { + static let preview = environment +} + public extension URL { static let previewInstanceURL = URL(string: "https://mastodon.social")! } diff --git a/ViewModels/Sources/ViewModels/View Models/NavigationViewModel.swift b/ViewModels/Sources/ViewModels/View Models/NavigationViewModel.swift index 304d6f5..ab37a22 100644 --- a/ViewModels/Sources/ViewModels/View Models/NavigationViewModel.swift +++ b/ViewModels/Sources/ViewModels/View Models/NavigationViewModel.swift @@ -16,10 +16,12 @@ public final class NavigationViewModel: ObservableObject { @Published public var alertItem: AlertItem? private let navigationsSubject = PassthroughSubject() + private let environment: AppEnvironment private var cancellables = Set() - public init(identityContext: IdentityContext) { + public init(identityContext: IdentityContext, environment: AppEnvironment) { self.identityContext = identityContext + self.environment = environment navigations = navigationsSubject.eraseToAnyPublisher() identityContext.$identity @@ -104,6 +106,12 @@ public extension NavigationViewModel { navigationsSubject.send(.profile(identityContext.service.navigationService.profileService(id: id))) } + func navigateToAccountSettings(instanceURI: String) { + AccountSettingsService(instanceURI: instanceURI, environment: environment).openAccountSettings() + .sink { _ in } receiveValue: { _ in } + .store(in: &cancellables) + } + func navigate(timeline: Timeline) { presentingSecondaryNavigation = false presentedNewStatusViewModel = nil diff --git a/ViewModels/Sources/ViewModels/View Models/RootViewModel.swift b/ViewModels/Sources/ViewModels/View Models/RootViewModel.swift index cd31fc6..c8f4796 100644 --- a/ViewModels/Sources/ViewModels/View Models/RootViewModel.swift +++ b/ViewModels/Sources/ViewModels/View Models/RootViewModel.swift @@ -143,7 +143,7 @@ private extension RootViewModel { self.notifyIdentityChange(identityContext: identityContext) } - return NavigationViewModel(identityContext: identityContext) + return NavigationViewModel(identityContext: identityContext, environment: self.environment) } .assign(to: &$navigationViewModel) } diff --git a/Views/SwiftUI/AboutView.swift b/Views/SwiftUI/AboutView.swift index b737cf8..d8e4012 100644 --- a/Views/SwiftUI/AboutView.swift +++ b/Views/SwiftUI/AboutView.swift @@ -88,7 +88,7 @@ import PreviewViewModels struct AboutView_Previews: PreviewProvider { static var previews: some View { - AboutView(viewModel: NavigationViewModel(identityContext: .preview)) + AboutView(viewModel: NavigationViewModel(identityContext: .preview, environment: .preview)) } } #endif diff --git a/Views/SwiftUI/ListsView.swift b/Views/SwiftUI/ListsView.swift index 1fa7c6f..e6dd0cf 100644 --- a/Views/SwiftUI/ListsView.swift +++ b/Views/SwiftUI/ListsView.swift @@ -64,7 +64,7 @@ import PreviewViewModels struct ListsView_Previews: PreviewProvider { static var previews: some View { ListsView(viewModel: .init(identityContext: .preview)) - .environmentObject(NavigationViewModel(identityContext: .preview)) + .environmentObject(NavigationViewModel(identityContext: .preview, environment: .preview)) } } #endif diff --git a/Views/SwiftUI/SecondaryNavigationView.swift b/Views/SwiftUI/SecondaryNavigationView.swift index b4541bf..b49a818 100644 --- a/Views/SwiftUI/SecondaryNavigationView.swift +++ b/Views/SwiftUI/SecondaryNavigationView.swift @@ -22,6 +22,17 @@ struct SecondaryNavigationView: View { } } } + if let instanceURI = viewModel.identityContext.identity.instance?.uri { + Button { + viewModel.navigateToAccountSettings(instanceURI: instanceURI) + } label: { + Label { + Text("secondary-navigation.account-settings").foregroundColor(.primary) + } icon: { + Image(systemName: "person.crop.square") + } + } + } NavigationLink( destination: IdentitiesView { .init(identityContext: viewModel.identityContext) } .environmentObject(rootViewModel)) { @@ -84,7 +95,7 @@ import PreviewViewModels struct SecondaryNavigationView_Previews: PreviewProvider { static var previews: some View { - SecondaryNavigationView(viewModel: NavigationViewModel(identityContext: .preview)) + SecondaryNavigationView(viewModel: NavigationViewModel(identityContext: .preview, environment: .preview)) .environmentObject(RootViewModel.preview) } } diff --git a/Views/SwiftUI/View Controller Representables/MainNavigationView.swift b/Views/SwiftUI/View Controller Representables/MainNavigationView.swift index b663ea1..3d5cb05 100644 --- a/Views/SwiftUI/View Controller Representables/MainNavigationView.swift +++ b/Views/SwiftUI/View Controller Representables/MainNavigationView.swift @@ -23,7 +23,7 @@ import PreviewViewModels struct MainNavigationView_Previews: PreviewProvider { static var previews: some View { - MainNavigationView { NavigationViewModel(identityContext: .preview) } + MainNavigationView { NavigationViewModel(identityContext: .preview, environment: .preview) } .environmentObject(RootViewModel.preview) } }