From 368ddc37f12794d99a6231c0c46229187a42784f Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Thu, 17 Nov 2022 14:29:17 +0800 Subject: [PATCH 1/2] Create `StoreCreationSuccessView` and its hosting controller for store creation success screen. --- .../StoreCreationSuccessView.swift | 127 ++++++++++++++++++ .../WooCommerce.xcodeproj/project.pbxproj | 12 ++ 2 files changed, 139 insertions(+) create mode 100644 WooCommerce/Classes/Authentication/Store Creation/Installations/StoreCreationSuccessView.swift diff --git a/WooCommerce/Classes/Authentication/Store Creation/Installations/StoreCreationSuccessView.swift b/WooCommerce/Classes/Authentication/Store Creation/Installations/StoreCreationSuccessView.swift new file mode 100644 index 00000000000..bfab6d34835 --- /dev/null +++ b/WooCommerce/Classes/Authentication/Store Creation/Installations/StoreCreationSuccessView.swift @@ -0,0 +1,127 @@ +import SwiftUI + +/// Hosting controller that wraps the `StoreCreationSuccessView`. +final class StoreCreationSuccessHostingController: UIHostingController { + private let onContinue: () -> Void + + init(siteURL: URL, + onContinue: @escaping () -> Void) { + self.onContinue = onContinue + super.init(rootView: StoreCreationSuccessView(siteURL: siteURL)) + + rootView.onContinue = { [weak self] in + self?.onContinue() + } + } + + @available(*, unavailable) + required dynamic init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + configureNavigationBarAppearance() + } + + /// Shows a transparent navigation bar without a bottom border and with a close button to dismiss. + func configureNavigationBarAppearance() { + let appearance = UINavigationBarAppearance() + appearance.configureWithTransparentBackground() + appearance.backgroundColor = .systemBackground + + navigationItem.standardAppearance = appearance + navigationItem.scrollEdgeAppearance = appearance + navigationItem.compactAppearance = appearance + } +} + +struct StoreCreationSuccessView: View { + /// Set in the hosting controller. + var onContinue: () -> Void = {} + + /// URL of the newly created site. + let siteURL: URL + + // Tracks the scale of the view due to accessibility changes. + @ScaledMetric private var scale: CGFloat = 1.0 + + @State private var isPresentingWebview: Bool = false + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + ScrollView { + VStack(alignment: .center, spacing: 33) { + // Title label. + Text(Localization.title) + .fontWeight(.bold) + .titleStyle() + + // Readonly webview for the new site. + WebView(isPresented: .constant(true), url: siteURL) + .frame(height: 400 * scale) + .disabled(true) + .border(Color(.systemBackground), width: 8) + .cornerRadius(8) + .shadow(color: Color(.secondaryLabel), radius: 26) + .padding(.horizontal, insets: Layout.webviewHorizontalPadding) + } + .padding(Layout.contentPadding) + } + + VStack(spacing: 0) { + Divider() + .frame(height: 1) + .foregroundColor(Color(.separator)) + + VStack(spacing: 16) { + // Continue button. + Button(Localization.continueButtonTitle) { + onContinue() + } + .buttonStyle(PrimaryButtonStyle()) + + // Preview button. + Button(Localization.previewButtonTitle) { + isPresentingWebview = true + } + .buttonStyle(SecondaryButtonStyle()) + } + .padding(insets: Layout.buttonContainerPadding) + } + } + .safariSheet(isPresented: $isPresentingWebview, url: siteURL) + } +} + +private extension StoreCreationSuccessView { + enum Layout { + static let contentPadding: EdgeInsets = .init(top: 38, leading: 16, bottom: 16, trailing: 16) + static let buttonContainerPadding: EdgeInsets = .init(top: 16, leading: 16, bottom: 16, trailing: 16) + static let webviewHorizontalPadding: EdgeInsets = .init(top: 0, leading: 44, bottom: 0, trailing: 44) + } + + enum Localization { + static let title = NSLocalizedString( + "Your store has been created!", + comment: "Title of the store creation success screen." + ) + static let continueButtonTitle = NSLocalizedString( + "Manage My Store", + comment: "Title of the primary button on the store creation success screen to continue to the newly created store." + ) + static let previewButtonTitle = NSLocalizedString( + "Store Preview", + comment: "Title of the secondary button on the store creation success screen to preview the newly created store." + ) + } +} + +struct StoreCreationSuccessView_Previews: PreviewProvider { + static var previews: some View { + StoreCreationSuccessView(siteURL: URL(string: "https://woocommerce.com")!) + StoreCreationSuccessView(siteURL: URL(string: "https://woocommerce.com")!) + .preferredColorScheme(.dark) + } +} diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index 4a86f22bd4c..b93ba73c327 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 0202B6952387AD1B00F3EBE0 /* UITabBar+Order.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0202B6942387AD1B00F3EBE0 /* UITabBar+Order.swift */; }; 0205021E27C8B6C600FB1C6B /* InboxEligibilityUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0205021D27C8B6C600FB1C6B /* InboxEligibilityUseCase.swift */; }; 020624F027951113000D024C /* StoreStatsDataOrRedactedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020624EF27951113000D024C /* StoreStatsDataOrRedactedView.swift */; }; + 02063C8929260AA000130906 /* StoreCreationSuccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02063C8829260A9F00130906 /* StoreCreationSuccessView.swift */; }; 0206483A23FA4160008441BB /* OrdersRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0206483923FA4160008441BB /* OrdersRootViewController.swift */; }; 02077F72253816FF005A78EF /* ProductFormActionsFactory+ReadonlyProductTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02077F71253816FF005A78EF /* ProductFormActionsFactory+ReadonlyProductTests.swift */; }; 020886572499E643001D784E /* ProductExternalLinkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020886562499E642001D784E /* ProductExternalLinkViewController.swift */; }; @@ -1995,6 +1996,7 @@ 0202B6942387AD1B00F3EBE0 /* UITabBar+Order.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITabBar+Order.swift"; sourceTree = ""; }; 0205021D27C8B6C600FB1C6B /* InboxEligibilityUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxEligibilityUseCase.swift; sourceTree = ""; }; 020624EF27951113000D024C /* StoreStatsDataOrRedactedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreStatsDataOrRedactedView.swift; sourceTree = ""; }; + 02063C8829260A9F00130906 /* StoreCreationSuccessView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoreCreationSuccessView.swift; sourceTree = ""; }; 0206483923FA4160008441BB /* OrdersRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrdersRootViewController.swift; sourceTree = ""; }; 02077F71253816FF005A78EF /* ProductFormActionsFactory+ReadonlyProductTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProductFormActionsFactory+ReadonlyProductTests.swift"; sourceTree = ""; }; 020886562499E642001D784E /* ProductExternalLinkViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductExternalLinkViewController.swift; sourceTree = ""; }; @@ -3985,6 +3987,14 @@ path = TabBar; sourceTree = ""; }; + 02063C8729260A6500130906 /* Installations */ = { + isa = PBXGroup; + children = ( + 02063C8829260A9F00130906 /* StoreCreationSuccessView.swift */, + ); + path = Installations; + sourceTree = ""; + }; 02077F70253816B1005A78EF /* Actions Factory */ = { isa = PBXGroup; children = ( @@ -4553,6 +4563,7 @@ children = ( 020AF6642923C745007760E5 /* Store name */, 02EEA92929233F0F00D05F47 /* Plan */, + 02063C8729260A6500130906 /* Installations */, 02759B9028FFA09600918176 /* StoreCreationWebViewModel.swift */, 02E3B63029066858007E0F13 /* StoreCreationCoordinator.swift */, 02EAA4C7290F992B00918DAB /* LoggedOutStoreCreationCoordinator.swift */, @@ -9830,6 +9841,7 @@ 029700EC24FE38C900D242F8 /* ScrollWatcher.swift in Sources */, D8C11A4E22DD235F00D4A88D /* OrderDetailsResultsControllers.swift in Sources */, D8C251D9230D256F00F49782 /* NoticePresenter.swift in Sources */, + 02063C8929260AA000130906 /* StoreCreationSuccessView.swift in Sources */, 77E53EB8250E6A4E003D385F /* ProductDownloadListViewController.swift in Sources */, E1325EFB28FD544E00EC9B2A /* InAppPurchasesDebugView.swift in Sources */, 74460D4022289B7600D7316A /* Coordinator.swift in Sources */, From a696db64eb6fa76daa45fa652a68fad01b278cbb Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 18 Nov 2022 08:35:41 +0800 Subject: [PATCH 2/2] StoreCreationSuccessView: replace fixed bottom view below the scroll view by using `safeAreaInset` from CR suggestion. --- .../StoreCreationSuccessView.swift | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/WooCommerce/Classes/Authentication/Store Creation/Installations/StoreCreationSuccessView.swift b/WooCommerce/Classes/Authentication/Store Creation/Installations/StoreCreationSuccessView.swift index bfab6d34835..74d8d9dda78 100644 --- a/WooCommerce/Classes/Authentication/Store Creation/Installations/StoreCreationSuccessView.swift +++ b/WooCommerce/Classes/Authentication/Store Creation/Installations/StoreCreationSuccessView.swift @@ -50,26 +50,25 @@ struct StoreCreationSuccessView: View { @State private var isPresentingWebview: Bool = false var body: some View { - VStack(alignment: .leading, spacing: 0) { - ScrollView { - VStack(alignment: .center, spacing: 33) { - // Title label. - Text(Localization.title) - .fontWeight(.bold) - .titleStyle() - - // Readonly webview for the new site. - WebView(isPresented: .constant(true), url: siteURL) - .frame(height: 400 * scale) - .disabled(true) - .border(Color(.systemBackground), width: 8) - .cornerRadius(8) - .shadow(color: Color(.secondaryLabel), radius: 26) - .padding(.horizontal, insets: Layout.webviewHorizontalPadding) - } - .padding(Layout.contentPadding) + ScrollView { + VStack(alignment: .center, spacing: 33) { + // Title label. + Text(Localization.title) + .fontWeight(.bold) + .titleStyle() + + // Readonly webview for the new site. + WebView(isPresented: .constant(true), url: siteURL) + .frame(height: 400 * scale) + .disabled(true) + .border(Color(.systemBackground), width: 8) + .cornerRadius(8) + .shadow(color: Color(.secondaryLabel), radius: 26) + .padding(.horizontal, insets: Layout.webviewHorizontalPadding) } - + .padding(Layout.contentPadding) + } + .safeAreaInset(edge: .bottom) { VStack(spacing: 0) { Divider() .frame(height: 1) @@ -90,6 +89,7 @@ struct StoreCreationSuccessView: View { } .padding(insets: Layout.buttonContainerPadding) } + .background(Color(.systemBackground)) } .safariSheet(isPresented: $isPresentingWebview, url: siteURL) }