Skip to content

Commit 80661f9

Browse files
authored
Merge pull request #8217 from woocommerce/issue/8075-ui-updates
Login: UI updates for the native Jetpack setup flow
2 parents 848f8a7 + 2b0db77 commit 80661f9

File tree

17 files changed

+256
-145
lines changed

17 files changed

+256
-145
lines changed

WooCommerce/Classes/Authentication/Jetpack Setup/Native Jetpack Setup/LoginJetpackSetupInterruptedView.swift

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ import SwiftUI
33
/// View to be displayed when the native Jetpack connection flow is dismissed.
44
///
55
struct LoginJetpackSetupInterruptedView: View {
6+
let siteURL: String
67
let onSupport: () -> Void
78
let onContinue: () -> Void
89
let onCancellation: () -> Void
910

11+
/// Scale of the view based on accessibility changes
12+
@ScaledMetric private var scale: CGFloat = 1.0
13+
1014
var body: some View {
1115
VStack {
1216
HStack {
@@ -27,11 +31,38 @@ struct LoginJetpackSetupInterruptedView: View {
2731
Spacer()
2832

2933
VStack(spacing: Constants.contentSpacing) {
34+
// Error image
3035
Image(uiImage: .jetpackSetupInterruptedImage)
36+
37+
// Site address info
38+
HStack(spacing: Constants.contentSpacing) {
39+
AsyncImage(url: URL(string: siteURL + Constants.favicoPath)) { image in
40+
image.resizable()
41+
} placeholder: {
42+
Image(systemName: "globe.americas.fill").resizable()
43+
}
44+
.frame(width: Constants.faviconSize * scale, height: Constants.faviconSize * scale)
45+
.scaledToFit()
46+
47+
Text(siteURL.trimHTTPScheme())
48+
.bodyStyle()
49+
.multilineTextAlignment(.leading)
50+
}
51+
.frame(maxWidth: .infinity)
52+
.foregroundColor(Color(uiColor: .text))
53+
.padding(Constants.contentSpacing)
54+
.overlay {
55+
RoundedRectangle(cornerRadius: 4)
56+
.stroke(Color(.separator), lineWidth: 0.5)
57+
}
58+
.padding(.bottom, Constants.contentSpacing)
59+
60+
// Error title
3161
Text(Localization.title)
3262
.fontWeight(.semibold)
63+
64+
// Error message
3365
Text(Localization.message)
34-
Text(Localization.suggestion)
3566
}
3667
.font(.title3)
3768
.foregroundColor(Color(uiColor: .text))
@@ -63,36 +94,34 @@ extension LoginJetpackSetupInterruptedView {
6394
enum Localization {
6495
static let help = NSLocalizedString("Help", comment: "Button to contact support on the Jetpack setup interrupted screen")
6596
static let title = NSLocalizedString(
66-
"You interrupted the connection.",
97+
"Jetpack is installed, but not connected.",
6798
comment: "Title of the Jetpack setup interrupted screen"
6899
)
69100
static let message = NSLocalizedString(
70-
"Jetpack is installed, but not connected.",
101+
"Try connecting again to access your store.",
71102
comment: "Message on the Jetpack setup interrupted screen"
72103
)
73-
static let suggestion = NSLocalizedString(
74-
"Please continue the connection process to access your store.",
75-
comment: "Suggestion on the Jetpack setup interrupted screen"
76-
)
77104
static let continueConnection = NSLocalizedString(
78-
"Continue Connection",
105+
"Connect Jetpack",
79106
comment: "Button on the Jetpack setup interrupted screen to continue the setup"
80107
)
81108
static let cancelInstallation = NSLocalizedString(
82-
"Cancel Installation",
109+
"Exit Without Connecting",
83110
comment: "Button to cancel installation on the Jetpack setup interrupted screen"
84111
)
85112
}
86113

87114
enum Constants {
88115
static let contentSpacing: CGFloat = 16
116+
static let faviconSize: CGFloat = 20
117+
static let favicoPath = "/favicon.ico"
89118
}
90119
}
91120

92121
struct LoginJetpackSetupInterruptedView_Previews: PreviewProvider {
93122
static var previews: some View {
94-
LoginJetpackSetupInterruptedView(onSupport: {}, onContinue: {}, onCancellation: {})
95-
LoginJetpackSetupInterruptedView(onSupport: {}, onContinue: {}, onCancellation: {})
123+
LoginJetpackSetupInterruptedView(siteURL: "this-is-a-really-really-long-long-long-store-address.com", onSupport: {}, onContinue: {}, onCancellation: {})
124+
LoginJetpackSetupInterruptedView(siteURL: "this-is-an-address.com", onSupport: {}, onContinue: {}, onCancellation: {})
96125
.previewInterfaceOrientation(.landscapeLeft)
97126
}
98127
}

WooCommerce/Classes/Authentication/Jetpack Setup/Native Jetpack Setup/LoginJetpackSetupView.swift

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ final class LoginJetpackSetupHostingController: UIHostingController<LoginJetpack
6060

6161
let webViewModel = JetpackConnectionWebViewModel(initialURL: connectionURL,
6262
siteURL: viewModel.siteURL,
63-
title: Localization.approveConnection,
6463
completion: { [weak self] in
6564
guard let self else { return }
6665
self.viewModel.shouldPresentWebView = false
@@ -89,7 +88,6 @@ final class LoginJetpackSetupHostingController: UIHostingController<LoginJetpack
8988
private extension LoginJetpackSetupHostingController {
9089
enum Localization {
9190
static let cancel = NSLocalizedString("Cancel", comment: "Button to dismiss the site credential login screen")
92-
static let approveConnection = NSLocalizedString("Approve connection", comment: "Title of the web view to approve Jetpack connection")
9391
}
9492
}
9593

@@ -139,7 +137,12 @@ struct LoginJetpackSetupView: View {
139137
// Setup steps and progress
140138
ForEach(viewModel.setupSteps) { step in
141139
HStack(spacing: Constants.stepItemHorizontalSpacing) {
142-
if viewModel.isSetupStepInProgress(step) {
140+
if viewModel.isSetupStepFailed(step) {
141+
Image(systemName: "exclamationmark.circle.fill")
142+
.resizable()
143+
.frame(width: Constants.stepImageSize * scale, height: Constants.stepImageSize * scale)
144+
.foregroundColor(Color(uiColor: .error))
145+
} else if viewModel.isSetupStepInProgress(step) {
143146
ActivityIndicator(isAnimating: .constant(true), style: .medium)
144147
} else if viewModel.isSetupStepPending(step) {
145148
Image(uiImage: .checkEmptyCircleImage)
@@ -152,24 +155,30 @@ struct LoginJetpackSetupView: View {
152155
}
153156

154157
VStack(alignment: .leading, spacing: 4) {
158+
// Title of the setup step
155159
Text(step == .connection ? Localization.authorizing : step.title)
156160
.font(.body)
157161
.if(viewModel.isSetupStepPending(step) == false) {
158162
$0.bold()
159163
}
160164
.foregroundColor(Color(.text))
161165
.opacity(viewModel.isSetupStepPending(step) == false ? 1 : 0.5)
162-
Label {
163-
Text(viewModel.currentConnectionStep.title)
166+
167+
// Status of the connection step
168+
viewModel.currentConnectionStep.map { step in
169+
Text(step.title)
164170
.font(.footnote)
165171
.fontWeight(.semibold)
166-
} icon: {
167-
viewModel.currentConnectionStep.imageName.map { name in
168-
Image(systemName: name)
169-
}
172+
.foregroundColor(Color(uiColor: step.tintColor))
170173
}
171-
.foregroundColor(Color(uiColor: viewModel.currentConnectionStep.tintColor))
172174
.renderedIf(step == .connection)
175+
176+
// Error label
177+
Text(Localization.error)
178+
.font(.footnote)
179+
.fontWeight(.semibold)
180+
.foregroundColor(Color(uiColor: .error))
181+
.renderedIf(viewModel.isSetupStepFailed(step))
173182
}
174183
}
175184
}
@@ -256,7 +265,7 @@ struct LoginJetpackSetupView: View {
256265
}
257266
}
258267
.fullScreenCover(isPresented: $viewModel.jetpackConnectionInterrupted) {
259-
LoginJetpackSetupInterruptedView(onSupport: supportHandler, onContinue: {
268+
LoginJetpackSetupInterruptedView(siteURL: viewModel.siteURL, onSupport: supportHandler, onContinue: {
260269
viewModel.jetpackConnectionInterrupted = false
261270
// delay for the dismissal of the interrupted screen to complete.
262271
DispatchQueue.main.asyncAfter(deadline: .now() + Constants.interruptedConnectionActionHandlerDelayTime) {
@@ -276,10 +285,11 @@ struct LoginJetpackSetupView: View {
276285
private extension LoginJetpackSetupView {
277286
enum Localization {
278287
static let goToStore = NSLocalizedString("Go to Store", comment: "Title for the button to navigate to the home screen after Jetpack setup completes")
279-
static let authorizing = NSLocalizedString("Authorizing connection", comment: "Name of the connection step on the Jetpack setup screen")
288+
static let authorizing = NSLocalizedString("Connect store to Jetpack", comment: "Name of the connection step on the Jetpack setup screen")
280289
static let errorCode = NSLocalizedString("Error code %1$d", comment: "Error code displayed when the Jetpack setup fails. %1$d is the code.")
281290
static let getSupport = NSLocalizedString("Get support", comment: "Button to contact support when Jetpack setup fails")
282291
static let cancelInstallation = NSLocalizedString("Cancel Installation", comment: "Action button to cancel Jetpack installation.")
292+
static let error = NSLocalizedString("Error", comment: "Title indicating a failed step in Jetpack installation.")
283293
}
284294

285295
enum Constants {

WooCommerce/Classes/Authentication/Jetpack Setup/Native Jetpack Setup/LoginJetpackSetupViewModel.swift

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ final class LoginJetpackSetupViewModel: ObservableObject {
4040
}
4141

4242
@Published private(set) var currentSetupStep: JetpackInstallStep?
43-
@Published private(set) var currentConnectionStep: ConnectionStep = .pending
43+
@Published private(set) var currentConnectionStep: ConnectionStep?
4444
@Published private(set) var jetpackConnectionURL: URL?
4545
@Published var shouldPresentWebView = false
4646
@Published var jetpackConnectionInterrupted = false
@@ -99,6 +99,13 @@ final class LoginJetpackSetupViewModel: ObservableObject {
9999
self.storeNavigationHandler = onStoreNavigation
100100
}
101101

102+
func isSetupStepFailed(_ step: JetpackInstallStep) -> Bool {
103+
guard let currentStep = currentSetupStep else {
104+
return false
105+
}
106+
return step == currentStep && setupFailed
107+
}
108+
102109
func isSetupStepInProgress(_ step: JetpackInstallStep) -> Bool {
103110
guard let currentStep = currentSetupStep else {
104111
return false
@@ -132,7 +139,7 @@ final class LoginJetpackSetupViewModel: ObservableObject {
132139
setupErrorDetail = nil
133140

134141
currentSetupStep = nil
135-
currentConnectionStep = .pending
142+
currentConnectionStep = nil
136143
startSetup()
137144
}
138145
}
@@ -301,34 +308,20 @@ extension LoginJetpackSetupViewModel {
301308
/// Steps for the Jetpack connection process.
302309
///
303310
enum ConnectionStep {
304-
case pending
305311
case inProgress
306312
case authorized
307313

308314
var title: String {
309315
switch self {
310-
case .pending:
311-
return LoginJetpackSetupViewModel.Localization.approvalRequired
312316
case .inProgress:
313317
return LoginJetpackSetupViewModel.Localization.validating
314318
case .authorized:
315319
return LoginJetpackSetupViewModel.Localization.connectionApproved
316320
}
317321
}
318322

319-
var imageName: String? {
320-
switch self {
321-
case .pending:
322-
return "info.circle.fill"
323-
case .inProgress, .authorized:
324-
return nil
325-
}
326-
}
327-
328323
var tintColor: UIColor {
329324
switch self {
330-
case .pending:
331-
return .wooOrange
332325
case .inProgress:
333326
return .secondaryLabel
334327
case .authorized:
@@ -350,16 +343,12 @@ extension LoginJetpackSetupViewModel {
350343
"Please wait while we connect your store %1$@ with Jetpack.",
351344
comment: "Message on the Jetpack setup screen. The %1$@ is the site address."
352345
)
353-
static let approvalRequired = NSLocalizedString(
354-
"Approval required",
355-
comment: "Message to be displayed when a Jetpack connection is pending approval"
356-
)
357346
static let validating = NSLocalizedString(
358347
"Validating",
359348
comment: "Message to be displayed when a Jetpack connection is being authorized"
360349
)
361350
static let connectionApproved = NSLocalizedString(
362-
"Connection approved",
351+
"Connected",
363352
comment: "Message to be displayed when a Jetpack connection has been authorized"
364353
)
365354
static let permissionErrorMessage = NSLocalizedString(

0 commit comments

Comments
 (0)