diff --git a/Localization/app.json b/Localization/app.json index ffa074ec3..c0f8560d7 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -519,6 +519,7 @@ }, "boringzone": { "title": "The Boring zone", + "account_settings": "Account settings", "terms": "Terms of Service", "privacy": "Privacy Policy" }, diff --git a/Mastodon/Diffiable/Item/SettingsItem.swift b/Mastodon/Diffiable/Item/SettingsItem.swift index 7320e9fc5..31c383b45 100644 --- a/Mastodon/Diffiable/Item/SettingsItem.swift +++ b/Mastodon/Diffiable/Item/SettingsItem.swift @@ -43,6 +43,7 @@ extension SettingsItem { } enum Link: CaseIterable { + case accountSettings case termsOfService case privacyPolicy case clearMediaCache @@ -50,6 +51,7 @@ extension SettingsItem { var title: String { switch self { + case .accountSettings: return "Account settings" case .termsOfService: return L10n.Scene.Settings.Section.Boringzone.terms case .privacyPolicy: return L10n.Scene.Settings.Section.Boringzone.privacy case .clearMediaCache: return L10n.Scene.Settings.Section.Spicyzone.clear @@ -59,6 +61,7 @@ extension SettingsItem { var textColor: UIColor { switch self { + case .accountSettings: return Asset.Colors.brandBlue.color case .termsOfService: return Asset.Colors.brandBlue.color case .privacyPolicy: return Asset.Colors.brandBlue.color case .clearMediaCache: return .systemRed diff --git a/Mastodon/Generated/Strings.swift b/Mastodon/Generated/Strings.swift index 5fa285e57..16e726d51 100644 --- a/Mastodon/Generated/Strings.swift +++ b/Mastodon/Generated/Strings.swift @@ -942,6 +942,8 @@ internal enum L10n { internal static let trueBlackDarkMode = L10n.tr("Localizable", "Scene.Settings.Section.AppearanceSettings.TrueBlackDarkMode") } internal enum Boringzone { + /// Account settings + internal static let accountSettings = L10n.tr("Localizable", "Scene.Settings.Section.Boringzone.AccountSettings") /// Privacy Policy internal static let privacy = L10n.tr("Localizable", "Scene.Settings.Section.Boringzone.Privacy") /// Terms of Service diff --git a/Mastodon/Protocol/StatusProvider/StatusProviderFacade.swift b/Mastodon/Protocol/StatusProvider/StatusProviderFacade.swift index 73952c8c3..0ae8a3ca8 100644 --- a/Mastodon/Protocol/StatusProvider/StatusProviderFacade.swift +++ b/Mastodon/Protocol/StatusProvider/StatusProviderFacade.swift @@ -145,8 +145,8 @@ extension StatusProviderFacade { provider.coordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil)) } case .hashtag(let text, _): - let hashtagTimelienViewModel = HashtagTimelineViewModel(context: provider.context, hashtag: text) - provider.coordinator.present(scene: .hashtagTimeline(viewModel: hashtagTimelienViewModel), from: provider, transition: .show) + let hashtagTimelineViewModel = HashtagTimelineViewModel(context: provider.context, hashtag: text) + provider.coordinator.present(scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel), from: provider, transition: .show) case .mention(let text, let userInfo): let href = userInfo?["href"] as? String coordinateToStatusMentionProfileScene(for: .primary, provider: provider, cell: cell, mention: text, href: href) diff --git a/Mastodon/Resources/ar.lproj/Localizable.strings b/Mastodon/Resources/ar.lproj/Localizable.strings index 63a389a9e..4d809429b 100644 --- a/Mastodon/Resources/ar.lproj/Localizable.strings +++ b/Mastodon/Resources/ar.lproj/Localizable.strings @@ -320,6 +320,7 @@ any server."; "Scene.Settings.Section.Appearance.Title" = "Appearance"; "Scene.Settings.Section.AppearanceSettings.DisableAvatarAnimation" = "Disable avatar animation"; "Scene.Settings.Section.AppearanceSettings.TrueBlackDarkMode" = "True black Dark Mode"; +"Scene.Settings.Section.Boringzone.AccountSettings" = "Account settings"; "Scene.Settings.Section.Boringzone.Privacy" = "Privacy Policy"; "Scene.Settings.Section.Boringzone.Terms" = "Terms of Service"; "Scene.Settings.Section.Boringzone.Title" = "The Boring zone"; diff --git a/Mastodon/Resources/en.lproj/Localizable.strings b/Mastodon/Resources/en.lproj/Localizable.strings index 63a389a9e..4d809429b 100644 --- a/Mastodon/Resources/en.lproj/Localizable.strings +++ b/Mastodon/Resources/en.lproj/Localizable.strings @@ -320,6 +320,7 @@ any server."; "Scene.Settings.Section.Appearance.Title" = "Appearance"; "Scene.Settings.Section.AppearanceSettings.DisableAvatarAnimation" = "Disable avatar animation"; "Scene.Settings.Section.AppearanceSettings.TrueBlackDarkMode" = "True black Dark Mode"; +"Scene.Settings.Section.Boringzone.AccountSettings" = "Account settings"; "Scene.Settings.Section.Boringzone.Privacy" = "Privacy Policy"; "Scene.Settings.Section.Boringzone.Terms" = "Terms of Service"; "Scene.Settings.Section.Boringzone.Title" = "The Boring zone"; diff --git a/Mastodon/Scene/Settings/SettingsViewController.swift b/Mastodon/Scene/Settings/SettingsViewController.swift index fce06caf3..5c573b161 100644 --- a/Mastodon/Scene/Settings/SettingsViewController.swift +++ b/Mastodon/Scene/Settings/SettingsViewController.swift @@ -12,7 +12,7 @@ import ActiveLabel import CoreData import CoreDataStack import MastodonSDK - +import AuthenticationServices class SettingsViewController: UIViewController, NeedsDependency { @@ -369,6 +369,10 @@ extension SettingsViewController: UITableViewDelegate { break case .boringZone(let link), .spicyZone(let link): switch link { + case .accountSettings: + guard let box = context.authenticationService.activeMastodonAuthenticationBox.value, + let url = URL(string: "https://\(box.domain)/auth/edit") else { return } + viewModel.openAuthenticationPage(authenticateURL: url, presentationContextProvider: self) case .termsOfService, .privacyPolicy: // same URL guard let url = viewModel.privacyURL else { break } @@ -382,10 +386,10 @@ extension SettingsViewController: UITableViewDelegate { .receive(on: RunLoop.main) .sink { [weak self] byteCount in guard let self = self else { return } - let byteCountformatted = AppContext.byteCountFormatter.string(fromByteCount: Int64(byteCount)) + let byteCountFormatted = AppContext.byteCountFormatter.string(fromByteCount: Int64(byteCount)) let alertController = UIAlertController( title: L10n.Common.Alerts.CleanCache.title, - message: L10n.Common.Alerts.CleanCache.message(byteCountformatted), + message: L10n.Common.Alerts.CleanCache.message(byteCountFormatted), preferredStyle: .alert ) let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil) @@ -537,6 +541,13 @@ extension SettingsViewController: ActiveLabelDelegate { } } +// MARK: - ASAuthorizationControllerPresentationContextProviding +extension SettingsViewController: ASWebAuthenticationPresentationContextProviding { + func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { + return view.window! + } +} + // MARK: - UIAdaptivePresentationControllerDelegate extension SettingsViewController: UIAdaptivePresentationControllerDelegate { func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { diff --git a/Mastodon/Scene/Settings/SettingsViewModel.swift b/Mastodon/Scene/Settings/SettingsViewModel.swift index 5d60f1669..d74b0ab51 100644 --- a/Mastodon/Scene/Settings/SettingsViewModel.swift +++ b/Mastodon/Scene/Settings/SettingsViewModel.swift @@ -12,13 +12,15 @@ import Foundation import MastodonSDK import UIKit import os.log +import AuthenticationServices class SettingsViewModel { var disposeBag = Set() let context: AppContext - + var mastodonAuthenticationController: MastodonAuthenticationController? + // input let setting: CurrentValueSubject var updateDisposeBag = Set() @@ -85,6 +87,20 @@ class SettingsViewModel { } extension SettingsViewModel { + + func openAuthenticationPage( + authenticateURL: URL, + presentationContextProvider: ASWebAuthenticationPresentationContextProviding + ) { + let authenticationController = MastodonAuthenticationController( + context: self.context, + authenticateURL: authenticateURL + ) + + self.mastodonAuthenticationController = authenticationController + authenticationController.authenticationSession?.presentationContextProvider = presentationContextProvider + authenticationController.authenticationSession?.start() + } // MARK: - Private methods private func processDataSource(_ setting: Setting) { @@ -117,6 +133,7 @@ extension SettingsViewModel { // boring zone let boringZoneSettingsItems: [SettingsItem] = { let links: [SettingsItem.Link] = [ + .accountSettings, .termsOfService, .privacyPolicy ]