diff --git a/Localization/app.json b/Localization/app.json index f2c2839a6..6ab65832f 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -11,6 +11,7 @@ }, "controls": { "actions": { + "back": "Back", "add": "Add", "remove": "Remove", "edit": "Edit", @@ -72,7 +73,9 @@ "prompt": "Your password needs at least:", "prompt_eight_characters": "Eight characters" } - } + }, + "success": "Success", + "check_email": "Regsiter request sent. Please check your email." }, "server_rules": { "title": "Some ground rules.", @@ -82,6 +85,25 @@ "confirm": "I Agree" } }, + "confirm_email": { + "title": "One last thing.", + "subtitle": "We just sent an email to %@,\ntap the link to confirm your account.", + "button": { + "open_email_app": "Open Email App", + "dont_receive_email": "I never got an email" + }, + "dont_receive_email": { + "title": "Check your email", + "description": "Check if your email address is correct as well as your junk folder if you haven’t.", + "resend_email": "Resend email" + }, + "open_email_app": { + "title": "Check your inbox.", + "description": "We just sent you an email. Check your junk folder if you haven’t.", + "mail": "Mail", + "open_email_client": "Open Email Client" + } + }, "home_timeline": { "title": "Home" }, diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 37a4a52af..51d067913 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -18,6 +18,8 @@ 2D32EAAC25CB96DC00C9ED86 /* TimelineMiddleLoaderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D32EAAB25CB96DC00C9ED86 /* TimelineMiddleLoaderTableViewCell.swift */; }; 2D32EABA25CB9B0500C9ED86 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D32EAB925CB9B0500C9ED86 /* UIView.swift */; }; 2D32EADA25CBCC3300C9ED86 /* PublicTimelineViewModel+LoadMiddleState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D32EAD925CBCC3300C9ED86 /* PublicTimelineViewModel+LoadMiddleState.swift */; }; + 2D364F7225E66D7500204FDC /* MastodonResendEmailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D364F7125E66D7500204FDC /* MastodonResendEmailViewController.swift */; }; + 2D364F7825E66D8300204FDC /* MastodonResendEmailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D364F7725E66D8300204FDC /* MastodonResendEmailViewModel.swift */; }; 2D38F1C625CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D38F1C525CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift */; }; 2D38F1D525CD465300561493 /* HomeTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D38F1D425CD465300561493 /* HomeTimelineViewController.swift */; }; 2D38F1DF25CD46A400561493 /* HomeTimelineViewController+StatusProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D38F1DE25CD46A400561493 /* HomeTimelineViewController+StatusProvider.swift */; }; @@ -36,6 +38,9 @@ 2D45E5BF25C9549700A6D639 /* PublicTimelineViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D45E5BE25C9549700A6D639 /* PublicTimelineViewModel+State.swift */; }; 2D46975E25C2A54100CF4AA9 /* NSLayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D46975D25C2A54100CF4AA9 /* NSLayoutConstraint.swift */; }; 2D46976425C2A71500CF4AA9 /* UIIamge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D46976325C2A71500CF4AA9 /* UIIamge.swift */; }; + 2D59819B25E4A581000FB903 /* MastodonConfirmEmailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D59819A25E4A581000FB903 /* MastodonConfirmEmailViewController.swift */; }; + 2D5981A125E4A593000FB903 /* MastodonConfirmEmailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5981A025E4A593000FB903 /* MastodonConfirmEmailViewModel.swift */; }; + 2D5981BA25E4D7F8000FB903 /* ThirdPartyMailer in Frameworks */ = {isa = PBXBuildFile; productRef = 2D5981B925E4D7F8000FB903 /* ThirdPartyMailer */; }; 2D5A3D0325CF8742002347D6 /* ControlContainableScrollViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5A3D0225CF8742002347D6 /* ControlContainableScrollViews.swift */; }; 2D5A3D2825CF8BC9002347D6 /* HomeTimelineViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5A3D2725CF8BC9002347D6 /* HomeTimelineViewModel+Diffable.swift */; }; 2D5A3D3825CF8D9F002347D6 /* ScrollViewContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5A3D3725CF8D9F002347D6 /* ScrollViewContainer.swift */; }; @@ -52,6 +57,8 @@ 2D76319F25C1521200929FB9 /* StatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76319E25C1521200929FB9 /* StatusSection.swift */; }; 2D7631A825C1535600929FB9 /* StatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631A725C1535600929FB9 /* StatusTableViewCell.swift */; }; 2D7631B325C159F700929FB9 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631B225C159F700929FB9 /* Item.swift */; }; + 2D82B9FF25E7863200E36F0F /* OnboardingViewControllerAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D82B9FE25E7863200E36F0F /* OnboardingViewControllerAppearance.swift */; }; + 2D82BA0525E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D82BA0425E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift */; }; 2D927F0225C7E4F2004F19B8 /* Mention.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0125C7E4F2004F19B8 /* Mention.swift */; }; 2D927F0825C7E9A8004F19B8 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0725C7E9A8004F19B8 /* Tag.swift */; }; 2D927F0E25C7E9C9004F19B8 /* History.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0D25C7E9C9004F19B8 /* History.swift */; }; @@ -210,6 +217,8 @@ 2D32EAAB25CB96DC00C9ED86 /* TimelineMiddleLoaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMiddleLoaderTableViewCell.swift; sourceTree = ""; }; 2D32EAB925CB9B0500C9ED86 /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; }; 2D32EAD925CBCC3300C9ED86 /* PublicTimelineViewModel+LoadMiddleState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PublicTimelineViewModel+LoadMiddleState.swift"; sourceTree = ""; }; + 2D364F7125E66D7500204FDC /* MastodonResendEmailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonResendEmailViewController.swift; sourceTree = ""; }; + 2D364F7725E66D8300204FDC /* MastodonResendEmailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonResendEmailViewModel.swift; sourceTree = ""; }; 2D38F1C525CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentOffsetAdjustableTimelineViewControllerDelegate.swift; sourceTree = ""; }; 2D38F1D425CD465300561493 /* HomeTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineViewController.swift; sourceTree = ""; }; 2D38F1DE25CD46A400561493 /* HomeTimelineViewController+StatusProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeTimelineViewController+StatusProvider.swift"; sourceTree = ""; }; @@ -227,6 +236,8 @@ 2D45E5BE25C9549700A6D639 /* PublicTimelineViewModel+State.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PublicTimelineViewModel+State.swift"; sourceTree = ""; }; 2D46975D25C2A54100CF4AA9 /* NSLayoutConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraint.swift; sourceTree = ""; }; 2D46976325C2A71500CF4AA9 /* UIIamge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIIamge.swift; sourceTree = ""; }; + 2D59819A25E4A581000FB903 /* MastodonConfirmEmailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonConfirmEmailViewController.swift; sourceTree = ""; }; + 2D5981A025E4A593000FB903 /* MastodonConfirmEmailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonConfirmEmailViewModel.swift; sourceTree = ""; }; 2D5A3D0225CF8742002347D6 /* ControlContainableScrollViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlContainableScrollViews.swift; sourceTree = ""; }; 2D5A3D2725CF8BC9002347D6 /* HomeTimelineViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeTimelineViewModel+Diffable.swift"; sourceTree = ""; }; 2D5A3D3725CF8D9F002347D6 /* ScrollViewContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewContainer.swift; sourceTree = ""; }; @@ -242,6 +253,8 @@ 2D76319E25C1521200929FB9 /* StatusSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusSection.swift; sourceTree = ""; }; 2D7631A725C1535600929FB9 /* StatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTableViewCell.swift; sourceTree = ""; }; 2D7631B225C159F700929FB9 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = ""; }; + 2D82B9FE25E7863200E36F0F /* OnboardingViewControllerAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewControllerAppearance.swift; sourceTree = ""; }; + 2D82BA0425E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonResendEmailViewModelNavigationDelegateShim.swift; sourceTree = ""; }; 2D927F0125C7E4F2004F19B8 /* Mention.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mention.swift; sourceTree = ""; }; 2D927F0725C7E9A8004F19B8 /* Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = ""; }; 2D927F0D25C7E9C9004F19B8 /* History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = History.swift; sourceTree = ""; }; @@ -364,6 +377,7 @@ DB5086B825CC0D6400C2C187 /* Kingfisher in Frameworks */, 2D61336925C18A4F00CAE157 /* AlamofireNetworkActivityIndicator in Frameworks */, DB3D0FF325BAA61700EAA174 /* AlamofireImage in Frameworks */, + 2D5981BA25E4D7F8000FB903 /* ThirdPartyMailer in Frameworks */, 45B49097460EDE530AD5AA72 /* Pods_Mastodon.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -440,6 +454,16 @@ path = Content; sourceTree = ""; }; + 2D364F7025E66D5B00204FDC /* ResendEmail */ = { + isa = PBXGroup; + children = ( + 2D364F7125E66D7500204FDC /* MastodonResendEmailViewController.swift */, + 2D364F7725E66D8300204FDC /* MastodonResendEmailViewModel.swift */, + 2D82BA0425E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift */, + ); + path = ResendEmail; + sourceTree = ""; + }; 2D38F1D325CD463600561493 /* HomeTimeline */ = { isa = PBXGroup; children = ( @@ -484,6 +508,15 @@ path = Button; sourceTree = ""; }; + 2D59819925E4A55C000FB903 /* ConfirmEmail */ = { + isa = PBXGroup; + children = ( + 2D59819A25E4A581000FB903 /* MastodonConfirmEmailViewController.swift */, + 2D5981A025E4A593000FB903 /* MastodonConfirmEmailViewModel.swift */, + ); + path = ConfirmEmail; + sourceTree = ""; + }; 2D5A3D0125CF8640002347D6 /* Vender */ = { isa = PBXGroup; children = ( @@ -520,6 +553,7 @@ 2D38F1C525CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift */, 2D38F20725CD491300561493 /* DisposeBagCollectable.swift */, 2D5A3D3725CF8D9F002347D6 /* ScrollViewContainer.swift */, + 2D82B9FE25E7863200E36F0F /* OnboardingViewControllerAppearance.swift */, ); path = Protocol; sourceTree = ""; @@ -616,6 +650,8 @@ DB01409B25C40BB600F9F3CF /* Authentication */ = { isa = PBXGroup; children = ( + 2D364F7025E66D5B00204FDC /* ResendEmail */, + 2D59819925E4A55C000FB903 /* ConfirmEmail */, DB0140A625C40C0900F9F3CF /* PinBased */, DBE0821A25CD382900FD6BBD /* Register */, DB72602125E36A2500235243 /* ServerRules */, @@ -1014,6 +1050,7 @@ 2D42FF6025C8177C004A627A /* ActiveLabel */, DB0140BC25C40D7500F9F3CF /* CommonOSLog */, DB5086B725CC0D6400C2C187 /* Kingfisher */, + 2D5981B925E4D7F8000FB903 /* ThirdPartyMailer */, ); productName = Mastodon; productReference = DB427DD225BAA00100D1B89D /* Mastodon.app */; @@ -1141,6 +1178,7 @@ 2D42FF5F25C8177C004A627A /* XCRemoteSwiftPackageReference "ActiveLabel" */, DB0140BB25C40D7500F9F3CF /* XCRemoteSwiftPackageReference "CommonOSLog" */, DB5086B625CC0D6400C2C187 /* XCRemoteSwiftPackageReference "Kingfisher" */, + 2D5981B825E4D7F8000FB903 /* XCRemoteSwiftPackageReference "ThirdPartyMailer" */, ); productRefGroup = DB427DD325BAA00100D1B89D /* Products */; projectDirPath = ""; @@ -1326,6 +1364,7 @@ files = ( DB98337125C9443200AD9700 /* APIService+Authentication.swift in Sources */, 0FAA0FDF25E0B57E0017CCDE /* WelcomeViewController.swift in Sources */, + 2D59819B25E4A581000FB903 /* MastodonConfirmEmailViewController.swift in Sources */, DB45FB1D25CA9D23005A8AC7 /* APIService+HomeTimeline.swift in Sources */, 2D7631B325C159F700929FB9 /* Item.swift in Sources */, 2D61335E25C1894B00CAE157 /* APIService.swift in Sources */, @@ -1334,6 +1373,7 @@ 0FAA101225E105390017CCDE /* PrimaryActionButton.swift in Sources */, DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */, DB72602725E36A6F00235243 /* MastodonServerRulesViewModel.swift in Sources */, + 2D364F7225E66D7500204FDC /* MastodonResendEmailViewController.swift in Sources */, 2D38F1F125CD477D00561493 /* HomeTimelineViewModel+LoadMiddleState.swift in Sources */, DB45FAD725CA6C76005A8AC7 /* UIBarButtonItem.swift in Sources */, 2D152A8C25C295CC009AA50C /* StatusView.swift in Sources */, @@ -1352,6 +1392,7 @@ 2DA7D04425CA52B200804E11 /* TimelineLoaderTableViewCell.swift in Sources */, DB8AF52F25C13561002E6C99 /* DocumentStore.swift in Sources */, DB9D6C2425E502C60051B173 /* MosaicImageViewModel.swift in Sources */, + 2D82BA0525E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift in Sources */, 2D38F1EB25CD477000561493 /* HomeTimelineViewModel+LoadLatestState.swift in Sources */, DBD9149025DF6D8D00903DFD /* APIService+Onboarding.swift in Sources */, DB98337F25C9452D00AD9700 /* APIService+APIError.swift in Sources */, @@ -1359,6 +1400,7 @@ DBE0822425CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift in Sources */, 2DF75B9B25D0E27500694EC8 /* StatusProviderFacade.swift in Sources */, DB5086A525CC0B7000C2C187 /* AvatarBarButtonItem.swift in Sources */, + 2D82B9FF25E7863200E36F0F /* OnboardingViewControllerAppearance.swift in Sources */, 2D38F1E525CD46C100561493 /* HomeTimelineViewModel.swift in Sources */, 2D76316B25C14D4C00929FB9 /* PublicTimelineViewModel.swift in Sources */, 2D38F1DF25CD46A400561493 /* HomeTimelineViewController+StatusProvider.swift in Sources */, @@ -1372,9 +1414,11 @@ 2DF75BA125D0E29D00694EC8 /* StatusProvider+TimelinePostTableViewCellDelegate.swift in Sources */, 2D42FF7E25C82218004A627A /* ActionToolBarContainer.swift in Sources */, DB0140A125C40C0600F9F3CF /* MastodonPinBasedAuthenticationViewController.swift in Sources */, + 2D5981A125E4A593000FB903 /* MastodonConfirmEmailViewModel.swift in Sources */, DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */, DB9D6BE925E4F5340051B173 /* SearchViewController.swift in Sources */, 2D38F1C625CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift in Sources */, + 2D364F7825E66D8300204FDC /* MastodonResendEmailViewModel.swift in Sources */, DB8AF54525C13647002E6C99 /* NeedsDependency.swift in Sources */, DB9D6BF825E4F5690051B173 /* NotificationViewController.swift in Sources */, DB45FADD25CA6F6B005A8AC7 /* APIService+CoreData+MastodonUser.swift in Sources */, @@ -1951,6 +1995,14 @@ minimumVersion = 4.0.0; }; }; + 2D5981B825E4D7F8000FB903 /* XCRemoteSwiftPackageReference "ThirdPartyMailer" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/vtourraine/ThirdPartyMailer.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.7.1; + }; + }; 2D61336725C18A4F00CAE157 /* XCRemoteSwiftPackageReference "AlamofireNetworkActivityIndicator" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Alamofire/AlamofireNetworkActivityIndicator"; @@ -1991,6 +2043,11 @@ package = 2D42FF5F25C8177C004A627A /* XCRemoteSwiftPackageReference "ActiveLabel" */; productName = ActiveLabel; }; + 2D5981B925E4D7F8000FB903 /* ThirdPartyMailer */ = { + isa = XCSwiftPackageProductDependency; + package = 2D5981B825E4D7F8000FB903 /* XCRemoteSwiftPackageReference "ThirdPartyMailer" */; + productName = ThirdPartyMailer; + }; 2D61336825C18A4F00CAE157 /* AlamofireNetworkActivityIndicator */ = { isa = XCSwiftPackageProductDependency; package = 2D61336725C18A4F00CAE157 /* XCRemoteSwiftPackageReference "AlamofireNetworkActivityIndicator" */; diff --git a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved index bbf66235a..456a6e967 100644 --- a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -81,6 +81,15 @@ "revision": "2b6054efa051565954e1d2b9da831680026cd768", "version": "5.0.0" } + }, + { + "package": "ThirdPartyMailer", + "repositoryURL": "https://github.com/vtourraine/ThirdPartyMailer.git", + "state": { + "branch": null, + "revision": "923c60ee7588da47db8cfc4e0f5b96e5e605ef84", + "version": "1.7.1" + } } ] }, diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index 409215b03..4ae96f9e5 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -43,6 +43,8 @@ extension SceneCoordinator { case mastodonPinBasedAuthentication(viewModel: MastodonPinBasedAuthenticationViewModel) case mastodonRegister(viewModel: MastodonRegisterViewModel) case mastodonServerRules(viewModel: MastodonServerRulesViewModel) + case mastodonConfirmEmail(viewModel: MastodonConfirmEmailViewModel) + case mastodonResendEmail(viewModel: MastodonResendEmailViewModel) case alertController(alertController: UIAlertController) @@ -156,6 +158,14 @@ private extension SceneCoordinator { let _viewController = MastodonServerRulesViewController() _viewController.viewModel = viewModel viewController = _viewController + case .mastodonConfirmEmail(let viewModel): + let _viewController = MastodonConfirmEmailViewController() + _viewController.viewModel = viewModel + viewController = _viewController + case .mastodonResendEmail(let viewModel): + let _viewController = MastodonResendEmailViewController() + _viewController.viewModel = viewModel + viewController = _viewController case .alertController(let alertController): if let popoverPresentationController = alertController.popoverPresentationController { assert( diff --git a/Mastodon/Generated/Strings.swift b/Mastodon/Generated/Strings.swift index 5c6f58bbf..c032874d9 100644 --- a/Mastodon/Generated/Strings.swift +++ b/Mastodon/Generated/Strings.swift @@ -26,6 +26,8 @@ internal enum L10n { internal enum Actions { /// Add internal static let add = L10n.tr("Localizable", "Common.Controls.Actions.Add") + /// Back + internal static let back = L10n.tr("Localizable", "Common.Controls.Actions.Back") /// Cancel internal static let cancel = L10n.tr("Localizable", "Common.Controls.Actions.Cancel") /// Confirm @@ -83,6 +85,38 @@ internal enum L10n { } internal enum Scene { + internal enum ConfirmEmail { + /// We just sent an email to %@,\ntap the link to confirm your account. + internal static func subtitle(_ p1: Any) -> String { + return L10n.tr("Localizable", "Scene.ConfirmEmail.Subtitle", String(describing: p1)) + } + /// One last thing. + internal static let title = L10n.tr("Localizable", "Scene.ConfirmEmail.Title") + internal enum Button { + /// I never got an email + internal static let dontReceiveEmail = L10n.tr("Localizable", "Scene.ConfirmEmail.Button.DontReceiveEmail") + /// Open Email App + internal static let openEmailApp = L10n.tr("Localizable", "Scene.ConfirmEmail.Button.OpenEmailApp") + } + internal enum DontReceiveEmail { + /// Check if your email address is correct as well as your junk folder if you haven’t. + internal static let description = L10n.tr("Localizable", "Scene.ConfirmEmail.DontReceiveEmail.Description") + /// Resend email + internal static let resendEmail = L10n.tr("Localizable", "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail") + /// Check your email + internal static let title = L10n.tr("Localizable", "Scene.ConfirmEmail.DontReceiveEmail.Title") + } + internal enum OpenEmailApp { + /// We just sent you an email. Check your junk folder if you haven’t. + internal static let description = L10n.tr("Localizable", "Scene.ConfirmEmail.OpenEmailApp.Description") + /// Mail + internal static let mail = L10n.tr("Localizable", "Scene.ConfirmEmail.OpenEmailApp.Mail") + /// Open Email Client + internal static let openEmailClient = L10n.tr("Localizable", "Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient") + /// Check your inbox. + internal static let title = L10n.tr("Localizable", "Scene.ConfirmEmail.OpenEmailApp.Title") + } + } internal enum HomeTimeline { /// Home internal static let title = L10n.tr("Localizable", "Scene.HomeTimeline.Title") @@ -92,6 +126,10 @@ internal enum L10n { internal static let title = L10n.tr("Localizable", "Scene.PublicTimeline.Title") } internal enum Register { + /// Regsiter request sent. Please check your email. + internal static let checkEmail = L10n.tr("Localizable", "Scene.Register.CheckEmail") + /// Success + internal static let success = L10n.tr("Localizable", "Scene.Register.Success") /// Tell us about you. internal static let title = L10n.tr("Localizable", "Scene.Register.Title") internal enum Input { diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index bc681a7d6..82ee713a3 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -64,5 +64,16 @@ UIViewControllerBasedStatusBarAppearance + LSApplicationQueriesSchemes + + sparrow + googlegmail + x-dispatch + readdle-spark + airmail + ms-outlook + ymail + fastmail + diff --git a/Mastodon/Protocol/OnboardingViewControllerAppearance.swift b/Mastodon/Protocol/OnboardingViewControllerAppearance.swift new file mode 100644 index 000000000..ea723e3cc --- /dev/null +++ b/Mastodon/Protocol/OnboardingViewControllerAppearance.swift @@ -0,0 +1,30 @@ +// +// OnboardingViewControllerAppearance.swift +// Mastodon +// +// Created by sxiaojian on 2021/2/25. +// + +import UIKit + +protocol OnboardingViewControllerAppearance: UIViewController { + func setupOnboardingAppearance() +} + +extension OnboardingViewControllerAppearance { + func setupOnboardingAppearance() { + overrideUserInterfaceStyle = .light + view.backgroundColor = Asset.Colors.Background.onboardingBackground.color + + // set navigationBar transparent + let barAppearance = UINavigationBarAppearance() + barAppearance.configureWithTransparentBackground() + navigationController?.navigationBar.standardAppearance = barAppearance + navigationController?.navigationBar.compactAppearance = barAppearance + navigationController?.navigationBar.scrollEdgeAppearance = barAppearance + + let backItem = UIBarButtonItem() + backItem.title = L10n.Common.Controls.Actions.back + navigationController?.navigationBar.topItem?.backBarButtonItem = backItem + } +} diff --git a/Mastodon/Resources/en.lproj/Localizable.strings b/Mastodon/Resources/en.lproj/Localizable.strings index 08a8d8293..de05b7ffb 100644 --- a/Mastodon/Resources/en.lproj/Localizable.strings +++ b/Mastodon/Resources/en.lproj/Localizable.strings @@ -1,6 +1,7 @@ "Common.Alerts.ServerError.Title" = "Server Error"; "Common.Alerts.SignUpFailure.Title" = "Sign Up Failure"; "Common.Controls.Actions.Add" = "Add"; +"Common.Controls.Actions.Back" = "Back"; "Common.Controls.Actions.Cancel" = "Cancel"; "Common.Controls.Actions.Confirm" = "Confirm"; "Common.Controls.Actions.Continue" = "Continue"; @@ -22,8 +23,21 @@ "Common.Controls.Timeline.LoadMore" = "Load More"; "Common.Countable.Photo.Multiple" = "photos"; "Common.Countable.Photo.Single" = "photo"; +"Scene.ConfirmEmail.Button.DontReceiveEmail" = "I never got an email"; +"Scene.ConfirmEmail.Button.OpenEmailApp" = "Open Email App"; +"Scene.ConfirmEmail.DontReceiveEmail.Description" = "Check if your email address is correct as well as your junk folder if you haven’t."; +"Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Resend email"; +"Scene.ConfirmEmail.DontReceiveEmail.Title" = "Check your email"; +"Scene.ConfirmEmail.OpenEmailApp.Description" = "We just sent you an email. Check your junk folder if you haven’t."; +"Scene.ConfirmEmail.OpenEmailApp.Mail" = "Mail"; +"Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "Open Email Client"; +"Scene.ConfirmEmail.OpenEmailApp.Title" = "Check your inbox."; +"Scene.ConfirmEmail.Subtitle" = "We just sent an email to %@, +tap the link to confirm your account."; +"Scene.ConfirmEmail.Title" = "One last thing."; "Scene.HomeTimeline.Title" = "Home"; "Scene.PublicTimeline.Title" = "Public"; +"Scene.Register.CheckEmail" = "Regsiter request sent. Please check your email."; "Scene.Register.Input.DisplayName.Placeholder" = "display name"; "Scene.Register.Input.Email.Placeholder" = "email"; "Scene.Register.Input.Password.Placeholder" = "password"; @@ -31,6 +45,7 @@ "Scene.Register.Input.Password.PromptEightCharacters" = "Eight characters"; "Scene.Register.Input.Username.DuplicatePrompt" = "This username is taken."; "Scene.Register.Input.Username.Placeholder" = "username"; +"Scene.Register.Success" = "Success"; "Scene.Register.Title" = "Tell us about you."; "Scene.ServerPicker.Input.Placeholder" = "Find a server or join your own..."; "Scene.ServerPicker.Title" = "Pick a Server, diff --git a/Mastodon/Scene/Authentication/AuthenticationViewController.swift b/Mastodon/Scene/Authentication/AuthenticationViewController.swift index a4a96dd59..090d84234 100644 --- a/Mastodon/Scene/Authentication/AuthenticationViewController.swift +++ b/Mastodon/Scene/Authentication/AuthenticationViewController.swift @@ -11,7 +11,7 @@ import Combine import MastodonSDK import UITextField_Shake -final class AuthenticationViewController: UIViewController, NeedsDependency { +final class AuthenticationViewController: UIViewController, NeedsDependency, OnboardingViewControllerAppearance{ var disposeBag = Set() @@ -77,9 +77,7 @@ extension AuthenticationViewController { override func viewDidLoad() { super.viewDidLoad() - overrideUserInterfaceStyle = .dark // FIXME: - title = "Authentication" - view.backgroundColor = Asset.Colors.Background.systemBackground.color + self.setupOnboardingAppearance() domainLabel.translatesAutoresizingMaskIntoConstraints = false view.addSubview(domainLabel) diff --git a/Mastodon/Scene/Authentication/ConfirmEmail/MastodonConfirmEmailViewController.swift b/Mastodon/Scene/Authentication/ConfirmEmail/MastodonConfirmEmailViewController.swift new file mode 100644 index 000000000..3bf7f78c4 --- /dev/null +++ b/Mastodon/Scene/Authentication/ConfirmEmail/MastodonConfirmEmailViewController.swift @@ -0,0 +1,174 @@ +// +// MastodonConfirmEmailViewController.swift +// Mastodon +// +// Created by sxiaojian on 2021/2/23. +// + +import Combine +import MastodonSDK +import os.log +import ThirdPartyMailer +import UIKit + +final class MastodonConfirmEmailViewController: UIViewController, NeedsDependency, OnboardingViewControllerAppearance { + var disposeBag = Set() + + weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } + weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } + + var viewModel: MastodonConfirmEmailViewModel! + + let largeTitleLabel: UILabel = { + let label = UILabel() + label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: UIFont.boldSystemFont(ofSize: 34)) + label.textColor = .label + label.text = L10n.Scene.ConfirmEmail.title + return label + }() + + private(set) lazy var subtitleLabel: UILabel = { + let label = UILabel() + label.font = UIFontMetrics(forTextStyle: .title1).scaledFont(for: UIFont.systemFont(ofSize: 20)) + label.textColor = .secondaryLabel + label.text = L10n.Scene.ConfirmEmail.subtitle(viewModel.email) + label.numberOfLines = 0 + return label + }() + + let openEmailButton: UIButton = { + let button = UIButton(type: .system) + button.titleLabel?.font = .preferredFont(forTextStyle: .headline) + button.setBackgroundImage(UIImage.placeholder(color: Asset.Colors.lightBrandBlue.color), for: .normal) + button.setTitleColor(.white, for: .normal) + button.setTitle(L10n.Scene.ConfirmEmail.Button.openEmailApp, for: .normal) + button.layer.masksToBounds = true + button.layer.cornerRadius = 8 + button.layer.cornerCurve = .continuous + button.addTarget(self, action: #selector(openEmailButtonPressed(_:)), for: UIControl.Event.touchUpInside) + return button + }() + + let dontReceiveButton: UIButton = { + let button = UIButton(type: .system) + button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: UIFont.boldSystemFont(ofSize: 15)) + button.setTitleColor(Asset.Colors.lightBrandBlue.color, for: .normal) + button.setTitle(L10n.Scene.ConfirmEmail.Button.dontReceiveEmail, for: .normal) + button.addTarget(self, action: #selector(dontReceiveButtonPressed(_:)), for: UIControl.Event.touchUpInside) + return button + }() +} + +extension MastodonConfirmEmailViewController { + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(false, animated: false) + } + + override func viewDidLoad() { + + self.setupOnboardingAppearance() + + // resizedView + let resizedView = UIView() + resizedView.translatesAutoresizingMaskIntoConstraints = false + resizedView.setContentHuggingPriority(.defaultLow, for: .vertical) + + // stackView + let stackView = UIStackView() + stackView.axis = .vertical + stackView.distribution = .fill + stackView.spacing = 10 + stackView.layoutMargins = UIEdgeInsets(top: 10, left: 0, bottom: 23, right: 0) + stackView.isLayoutMarginsRelativeArrangement = true + stackView.addArrangedSubview(self.largeTitleLabel) + stackView.addArrangedSubview(self.subtitleLabel) + stackView.addArrangedSubview(resizedView) + stackView.addArrangedSubview(self.openEmailButton) + stackView.addArrangedSubview(self.dontReceiveButton) + + view.addSubview(stackView) + stackView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + stackView.topAnchor.constraint(equalTo: view.readableContentGuide.topAnchor), + stackView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor), + stackView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor), + ]) + NSLayoutConstraint.activate([ + self.openEmailButton.heightAnchor.constraint(equalToConstant: 46), + ]) + + self.viewModel.timestampUpdatePublisher + .sink { [weak self] _ in + guard let self = self else { return } + AuthenticationViewModel.verifyAndSaveAuthentication(context: self.context, info: self.viewModel.authenticateInfo, userToken: self.viewModel.userToken) + .receive(on: DispatchQueue.main) + .sink { completion in + switch completion { + case .failure(let error): + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: swap user access token swap fail: %s", (#file as NSString).lastPathComponent, #line, #function, error.localizedDescription) + case .finished: + break + } + } receiveValue: { _ in + self.coordinator.setup() + } + .store(in: &self.disposeBag) + } + .store(in: &self.disposeBag) + } +} + +extension MastodonConfirmEmailViewController { + @objc private func openEmailButtonPressed(_ sender: UIButton) { + let alertController = UIAlertController(title: L10n.Scene.ConfirmEmail.OpenEmailApp.title, message: L10n.Scene.ConfirmEmail.OpenEmailApp.description, preferredStyle: .alert) + let openEmailAction = UIAlertAction(title: L10n.Scene.ConfirmEmail.Button.openEmailApp, style: .default) { [weak self] _ in + guard let self = self else { return } + self.showEmailAppAlert() + } + let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel, handler: nil) + alertController.addAction(openEmailAction) + alertController.addAction(cancelAction) + alertController.preferredAction = openEmailAction + self.coordinator.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil)) + } + + @objc private func dontReceiveButtonPressed(_ sender: UIButton) { + let alertController = UIAlertController(title: L10n.Scene.ConfirmEmail.DontReceiveEmail.title, message: L10n.Scene.ConfirmEmail.DontReceiveEmail.description, preferredStyle: .alert) + let resendAction = UIAlertAction(title: L10n.Scene.ConfirmEmail.DontReceiveEmail.resendEmail, style: .default) { _ in + let url = Mastodon.API.resendEmailURL(domain: self.viewModel.authenticateInfo.domain) + let viewModel = MastodonResendEmailViewModel(resendEmailURL: url, email: self.viewModel.email) + self.coordinator.present(scene: .mastodonResendEmail(viewModel: viewModel), from: self, transition: .modal(animated: true, completion: nil)) + } + let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default) { _ in + } + alertController.addAction(resendAction) + alertController.addAction(okAction) + self.coordinator.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil)) + } + + func showEmailAppAlert() { + let clients = ThirdPartyMailClient.clients() + let application = UIApplication.shared + let avaliableClients = clients.filter { client -> Bool in + ThirdPartyMailer.application(application, isMailClientAvailable: client) + } + let alertController = UIAlertController(title: L10n.Scene.ConfirmEmail.OpenEmailApp.openEmailClient, message: nil, preferredStyle: .alert) + + let alertAction = UIAlertAction(title: L10n.Scene.ConfirmEmail.OpenEmailApp.mail, style: .default) { _ in + UIApplication.shared.open(URL(string: "message://")!, options: [:], completionHandler: nil) + } + alertController.addAction(alertAction) + _ = avaliableClients.compactMap { client -> UIAlertAction in + let alertAction = UIAlertAction(title: client.name, style: .default) { _ in + _ = ThirdPartyMailer.application(application, openMailClient: client, recipient: nil, subject: nil, body: nil) + } + alertController.addAction(alertAction) + return alertAction + } + let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel, handler: nil) + alertController.addAction(cancelAction) + self.coordinator.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil)) + } +} diff --git a/Mastodon/Scene/Authentication/ConfirmEmail/MastodonConfirmEmailViewModel.swift b/Mastodon/Scene/Authentication/ConfirmEmail/MastodonConfirmEmailViewModel.swift new file mode 100644 index 000000000..aff254741 --- /dev/null +++ b/Mastodon/Scene/Authentication/ConfirmEmail/MastodonConfirmEmailViewModel.swift @@ -0,0 +1,31 @@ +// +// MastodonConfirmEmailViewModel.swift +// Mastodon +// +// Created by sxiaojian on 2021/2/23. +// + +import Combine +import Foundation +import MastodonSDK + +final class MastodonConfirmEmailViewModel { + var disposeBag = Set() + + let context: AppContext + var email: String + let authenticateInfo: AuthenticationViewModel.AuthenticateInfo + let userToken: Mastodon.Entity.Token + + let timestampUpdatePublisher = Timer.publish(every: 4.0, on: .main, in: .common) + .autoconnect() + .share() + .eraseToAnyPublisher() + + init(context: AppContext, email: String, authenticateInfo: AuthenticationViewModel.AuthenticateInfo, userToken: Mastodon.Entity.Token) { + self.context = context + self.email = email + self.authenticateInfo = authenticateInfo + self.userToken = userToken + } +} diff --git a/Mastodon/Scene/Authentication/Register/MastodonRegisterViewController.swift b/Mastodon/Scene/Authentication/Register/MastodonRegisterViewController.swift index 1ff30bf66..074d5c762 100644 --- a/Mastodon/Scene/Authentication/Register/MastodonRegisterViewController.swift +++ b/Mastodon/Scene/Authentication/Register/MastodonRegisterViewController.swift @@ -11,7 +11,7 @@ import os.log import UIKit import UITextField_Shake -final class MastodonRegisterViewController: UIViewController, NeedsDependency { +final class MastodonRegisterViewController: UIViewController, NeedsDependency, OnboardingViewControllerAppearance { var disposeBag = Set() weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } @@ -176,7 +176,7 @@ final class MastodonRegisterViewController: UIViewController, NeedsDependency { button.setBackgroundImage(UIImage.placeholder(color: Asset.Colors.lightBrandBlue.color), for: .normal) button.setBackgroundImage(UIImage.placeholder(color: Asset.Colors.lightDisabled.color), for: .disabled) button.isEnabled = false - button.setTitleColor(Asset.Colors.Label.primary.color, for: .normal) + button.setTitleColor(.white, for: .normal) button.setTitle(L10n.Common.Controls.Actions.continue, for: .normal) button.layer.masksToBounds = true button.layer.cornerRadius = 8 @@ -196,8 +196,8 @@ extension MastodonRegisterViewController { override func viewDidLoad() { super.viewDidLoad() - overrideUserInterfaceStyle = .light - view.backgroundColor = Asset.Colors.Background.onboardingBackground.color + self.setupOnboardingAppearance() + domainLabel.text = "@" + viewModel.domain + " " domainLabel.sizeToFit() passwordCheckLabel.attributedText = viewModel.attributeStringForPassword() @@ -451,7 +451,7 @@ extension MastodonRegisterViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - navigationController?.setNavigationBarHidden(true, animated: false) + navigationController?.setNavigationBarHidden(false, animated: false) } } @@ -567,17 +567,17 @@ extension MastodonRegisterViewController { } } receiveValue: { [weak self] response in guard let self = self else { return } - _ = response.value - // TODO: - let alertController = UIAlertController(title: "Success", message: "Regsiter request sent. Please check your email.\n(Auto sign in not implement yet.)", preferredStyle: .alert) + let userToken = response.value + + let alertController = UIAlertController(title: L10n.Scene.Register.success, message: L10n.Scene.Register.checkEmail, preferredStyle: .alert) let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default) { [weak self] _ in guard let self = self else { return } - self.navigationController?.popViewController(animated: true) + let viewModel = MastodonConfirmEmailViewModel(context: self.context, email: email, authenticateInfo: self.viewModel.authenticateInfo, userToken: userToken) + self.coordinator.present(scene: .mastodonConfirmEmail(viewModel: viewModel), from: self, transition: .show) } alertController.addAction(okAction) self.coordinator.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil)) } .store(in: &disposeBag) } - } diff --git a/Mastodon/Scene/Authentication/ResendEmail/MastodonResendEmailViewController.swift b/Mastodon/Scene/Authentication/ResendEmail/MastodonResendEmailViewController.swift new file mode 100644 index 000000000..a10755fe3 --- /dev/null +++ b/Mastodon/Scene/Authentication/ResendEmail/MastodonResendEmailViewController.swift @@ -0,0 +1,66 @@ +// +// MastodonResendEmailViewController.swift +// Mastodon +// +// Created by sxiaojian on 2021/2/24. +// + +import Combine +import os.log +import UIKit +import WebKit + +final class MastodonResendEmailViewController: UIViewController, NeedsDependency, WKNavigationDelegate { + weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } + weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } + + var disposeBag = Set() + var viewModel: MastodonResendEmailViewModel! + + let webView: WKWebView = { + let configuration = WKWebViewConfiguration() + configuration.processPool = WKProcessPool() + let webView = WKWebView(frame: .zero, configuration: configuration) + return webView + }() + + deinit { + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", (#file as NSString).lastPathComponent, #line, #function) + + // cleanup cookie + let httpCookieStore = webView.configuration.websiteDataStore.httpCookieStore + httpCookieStore.getAllCookies { cookies in + for cookie in cookies { + httpCookieStore.delete(cookie, completionHandler: nil) + } + } + } +} + +extension MastodonResendEmailViewController { + override func viewDidLoad() { + super.viewDidLoad() + + navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(MastodonResendEmailViewController.cancelBarButtonItemPressed(_:))) + + webView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(webView) + NSLayoutConstraint.activate([ + webView.topAnchor.constraint(equalTo: view.topAnchor), + webView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + webView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + webView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + + let request = URLRequest(url: viewModel.resendEmailURL) + webView.navigationDelegate = self.viewModel.navigationDelegate + webView.load(request) + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: resendEmail via: %s", (#file as NSString).lastPathComponent, #line, #function, viewModel.resendEmailURL.debugDescription) + } +} + +extension MastodonResendEmailViewController { + @objc private func cancelBarButtonItemPressed(_ sender: UIBarButtonItem) { + dismiss(animated: true, completion: nil) + } +} diff --git a/Mastodon/Scene/Authentication/ResendEmail/MastodonResendEmailViewModel.swift b/Mastodon/Scene/Authentication/ResendEmail/MastodonResendEmailViewModel.swift new file mode 100644 index 000000000..e8e16e6e5 --- /dev/null +++ b/Mastodon/Scene/Authentication/ResendEmail/MastodonResendEmailViewModel.swift @@ -0,0 +1,37 @@ +// +// MastodonResendEmailViewModel.swift +// Mastodon +// +// Created by sxiaojian on 2021/2/24. +// + +import Combine +import Foundation +import os.log +import WebKit + +final class MastodonResendEmailViewModel { + // input + let resendEmailURL: URL + let email: String + + private var navigationDelegateShim: MastodonResendEmailViewModelNavigationDelegateShim? + + init(resendEmailURL: URL, email: String) { + self.resendEmailURL = resendEmailURL + self.email = email + } + + deinit { + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", (#file as NSString).lastPathComponent, #line, #function) + } +} +extension MastodonResendEmailViewModel { + + var navigationDelegate: WKNavigationDelegate { + let navigationDelegateShim = MastodonResendEmailViewModelNavigationDelegateShim(viewModel: self) + self.navigationDelegateShim = navigationDelegateShim + return navigationDelegateShim + } + +} diff --git a/Mastodon/Scene/Authentication/ResendEmail/MastodonResendEmailViewModelNavigationDelegateShim.swift b/Mastodon/Scene/Authentication/ResendEmail/MastodonResendEmailViewModelNavigationDelegateShim.swift new file mode 100644 index 000000000..4a27de96d --- /dev/null +++ b/Mastodon/Scene/Authentication/ResendEmail/MastodonResendEmailViewModelNavigationDelegateShim.swift @@ -0,0 +1,37 @@ +// +// MastodonResendEmailViewModelNavigationDelegateShim.swift +// Mastodon +// +// Created by sxiaojian on 2021/2/25. +// + +import os.log +import Foundation +import WebKit + +final class MastodonResendEmailViewModelNavigationDelegateShim: NSObject { + + weak var viewModel: MastodonResendEmailViewModel? + + init(viewModel: MastodonResendEmailViewModel) { + self.viewModel = viewModel + } + + deinit { + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) + } +} + + +// MARK: - WKNavigationDelegate +extension MastodonResendEmailViewModelNavigationDelegateShim: WKNavigationDelegate { + + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { + guard let email = self.viewModel?.email else { + return + } + let scriptString = "document.getElementById('user_email').value = '\(email)';" + webView.evaluateJavaScript(scriptString) + } + +} diff --git a/Mastodon/Scene/Authentication/ServerRules/MastodonServerRulesViewController.swift b/Mastodon/Scene/Authentication/ServerRules/MastodonServerRulesViewController.swift index 826a8731a..4f23a6134 100644 --- a/Mastodon/Scene/Authentication/ServerRules/MastodonServerRulesViewController.swift +++ b/Mastodon/Scene/Authentication/ServerRules/MastodonServerRulesViewController.swift @@ -8,7 +8,7 @@ import os.log import UIKit -final class MastodonServerRulesViewController: UIViewController, NeedsDependency { +final class MastodonServerRulesViewController: UIViewController, NeedsDependency ,OnboardingViewControllerAppearance{ weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } @@ -78,8 +78,7 @@ extension MastodonServerRulesViewController { override func viewDidLoad() { super.viewDidLoad() - overrideUserInterfaceStyle = .light - view.backgroundColor = Asset.Colors.Background.onboardingBackground.color + self.setupOnboardingAppearance() bottonContainerView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(bottonContainerView) @@ -144,7 +143,7 @@ extension MastodonServerRulesViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - navigationController?.setNavigationBarHidden(true, animated: false) + navigationController?.setNavigationBarHidden(false, animated: false) } } diff --git a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift index 24b7ec3ad..92897090c 100644 --- a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift +++ b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift @@ -81,6 +81,10 @@ extension Mastodon.API { static let joinMastodonEndpointURL = URL(string: "https://api.joinmastodon.org/")! + public static func resendEmailURL(domain: String) -> URL { + return URL(string: "https://" + domain + "/auth/confirmation/new")! + } + } extension Mastodon.API {