Skip to content

Commit 47effb3

Browse files
committed
Jetpack banner view with SwiftUI.
1 parent a746159 commit 47effb3

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed

WooCommerce/Classes/Extensions/UIImage+Woo.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ extension UIImage {
1313
return UIImage.gridicon(.addOutline)
1414
}
1515

16+
/// Alarm Bell Ring Image
17+
///
18+
static var alarmBellRingImage: UIImage {
19+
return UIImage(named: "icon-alarm-bell-ring")!
20+
}
21+
1622
/// Arrow Up Icon
1723
///
1824
static var arrowUp: UIImage {
@@ -25,6 +31,12 @@ extension UIImage {
2531
return UIImage.gridicon(.alignJustify)
2632
}
2733

34+
/// Analytics Image
35+
///
36+
static var analyticsImage: UIImage {
37+
return UIImage(named: "icon-analytics")!
38+
}
39+
2840
/// Notice Icon
2941
///
3042
static var noticeImage: UIImage {
@@ -732,6 +744,12 @@ extension UIImage {
732744
return UIImage(imageLiteralResourceName: "megaphone").imageFlippedForRightToLeftLayoutDirection()
733745
}
734746

747+
/// Multiple Users Image
748+
///
749+
static var multipleUsersImage: UIImage {
750+
return UIImage(named: "icon-multiple-users")!
751+
}
752+
735753
/// Error image
736754
///
737755
static var errorImage: UIImage {

WooCommerce/Classes/Styles/ColorStudio.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ enum ColorStudioName: String, CustomStringConvertible {
33
// MARK: - Base colors
44
case blue
55
case celadon
6+
case jetpackGreen
67
case gray
78
case green
89
case orange
@@ -68,6 +69,7 @@ struct ColorStudio {
6869
static let red = ColorStudio(name: .red)
6970
static let gray = ColorStudio(name: .gray)
7071
static let blue = ColorStudio(name: .blue)
72+
static let jetpackGreen = ColorStudio(name: .jetpackGreen)
7173
static let green = ColorStudio(name: .green)
7274
static let yellow = ColorStudio(name: .yellow)
7375
static let orange = ColorStudio(name: .orange)

WooCommerce/Classes/Styles/UIColor+SemanticColors.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,19 @@ extension UIColor {
301301
static var softwareUpdateProgressFill: UIColor {
302302
return UIColor(red: 0.498, green: 0.329, blue: 0.702, alpha: 1)
303303
}
304+
305+
/// Jetpack benefits banner background color.
306+
///
307+
static var jetpackBenefitsBackground: UIColor {
308+
return UIColor(red: 11.0/255, green: 38.0/255, blue: 33.0/255, alpha: 1)
309+
}
310+
311+
/// Jetpack logo color.
312+
///
313+
static var jetpackGreen: UIColor {
314+
return UIColor(light: .withColorStudio(.jetpackGreen, shade: .shade30),
315+
dark: .withColorStudio(.jetpackGreen, shade: .shade30))
316+
}
304317
}
305318

306319
// MARK: - UI elements.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import SwiftUI
2+
3+
/// Hosting controller wrapper for `JetpackBenefitsBanner`
4+
///
5+
final class JetpackBenefitsBannerHostingController: UIHostingController<JetpackBenefitsBanner> {
6+
init() {
7+
super.init(rootView: JetpackBenefitsBanner())
8+
}
9+
10+
required dynamic init?(coder aDecoder: NSCoder) {
11+
fatalError("init(coder:) has not been implemented")
12+
}
13+
14+
/// Actions are set in a separate function because most of the time, they will require to access `self` to be able to present new view controllers.
15+
///
16+
func setActions(tapAction: @escaping () -> Void, dismissAction: @escaping () -> Void) {
17+
rootView.tapAction = tapAction
18+
rootView.dismissAction = dismissAction
19+
}
20+
}
21+
22+
/// A banner about Jetpack benefits that can be tapped to show more details or dismiss.
23+
struct JetpackBenefitsBanner: View {
24+
/// Closure invoked when the banner is tapped
25+
///
26+
var tapAction: () -> Void = {}
27+
28+
/// Closure invoked when the dismiss button is tapped
29+
///
30+
var dismissAction: () -> Void = {}
31+
32+
// Tracks the scale of the view due to accessibility changes
33+
@ScaledMetric private var scale: CGFloat = 1.0
34+
35+
var body: some View {
36+
Group {
37+
HStack(spacing: Layout.horizontalSpacing) {
38+
Image("icon-jetpack-gray")
39+
.resizable()
40+
.renderingMode(.template)
41+
.foregroundColor(Color(.jetpackGreen))
42+
.frame(width: Layout.iconDimension * scale, height: Layout.iconDimension * scale)
43+
VStack(alignment: .leading, spacing: Layout.verticalTextSpacing) {
44+
Text(Localization.title)
45+
.foregroundColor(.white)
46+
.bodyStyle()
47+
Text(Localization.subtitle)
48+
.foregroundColor(Color(.gray(.shade30)))
49+
.bodyStyle()
50+
}
51+
Spacer()
52+
Button(action: dismissAction) {
53+
Image(uiImage: .closeButton)
54+
.foregroundColor(Color(.gray(.shade30)))
55+
}
56+
}
57+
.padding(insets: Layout.padding)
58+
}
59+
.gesture(
60+
TapGesture()
61+
.onEnded { _ in
62+
self.tapAction()
63+
}
64+
)
65+
.background(Color(.jetpackBenefitsBackground))
66+
.fixedSize(horizontal: false, vertical: true)
67+
}
68+
}
69+
70+
private extension JetpackBenefitsBanner {
71+
enum Localization {
72+
static let title = NSLocalizedString("Get the full experience with Jetpack", comment: "Title of the Jetpack benefits banner.")
73+
static let subtitle = NSLocalizedString("See the benefits", comment: "Subtitle of the Jetpack benefits banner.")
74+
}
75+
76+
enum Layout {
77+
static let padding = EdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16)
78+
static let iconDimension = CGFloat(24)
79+
static let horizontalSpacing = CGFloat(10)
80+
static let verticalTextSpacing = CGFloat(5)
81+
}
82+
}
83+
84+
struct JetpackBenefitsBanner_Previews: PreviewProvider {
85+
static var previews: some View {
86+
JetpackBenefitsBanner()
87+
.preferredColorScheme(.dark)
88+
.environment(\.sizeCategory, .extraExtraLarge)
89+
JetpackBenefitsBanner()
90+
.preferredColorScheme(.light)
91+
.environment(\.sizeCategory, .extraExtraLarge)
92+
}
93+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@
371371
02F67FF525806E0100C3BAD2 /* ShippingLabelTrackingURLGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F67FF425806E0100C3BAD2 /* ShippingLabelTrackingURLGeneratorTests.swift */; };
372372
02F6800325807C9B00C3BAD2 /* ShippingLabelPaperSizeOptionListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F6800225807C9B00C3BAD2 /* ShippingLabelPaperSizeOptionListView.swift */; };
373373
02F6800925807CD300C3BAD2 /* GridStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F6800825807CD300C3BAD2 /* GridStackView.swift */; };
374+
02F843DA273646A30017FE12 /* JetpackBenefitsBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02F843D9273646A30017FE12 /* JetpackBenefitsBanner.swift */; };
374375
02FE89C7231FAA4100E85EF8 /* MainTabBarControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FE89C6231FAA4100E85EF8 /* MainTabBarControllerTests.swift */; };
375376
03AA165E2719B7EF005CCB7B /* ReceiptActionCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03AA165D2719B7EF005CCB7B /* ReceiptActionCoordinator.swift */; };
376377
03AA16602719B83D005CCB7B /* ReceiptActionCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03AA165F2719B83D005CCB7B /* ReceiptActionCoordinatorTests.swift */; };
@@ -1830,6 +1831,7 @@
18301831
02F67FF425806E0100C3BAD2 /* ShippingLabelTrackingURLGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelTrackingURLGeneratorTests.swift; sourceTree = "<group>"; };
18311832
02F6800225807C9B00C3BAD2 /* ShippingLabelPaperSizeOptionListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelPaperSizeOptionListView.swift; sourceTree = "<group>"; };
18321833
02F6800825807CD300C3BAD2 /* GridStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridStackView.swift; sourceTree = "<group>"; };
1834+
02F843D9273646A30017FE12 /* JetpackBenefitsBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackBenefitsBanner.swift; sourceTree = "<group>"; };
18331835
02FE89C6231FAA4100E85EF8 /* MainTabBarControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabBarControllerTests.swift; sourceTree = "<group>"; };
18341836
03AA165D2719B7EF005CCB7B /* ReceiptActionCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptActionCoordinator.swift; sourceTree = "<group>"; };
18351837
03AA165F2719B83D005CCB7B /* ReceiptActionCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptActionCoordinatorTests.swift; sourceTree = "<group>"; };
@@ -3855,6 +3857,14 @@
38553857
path = "Shipping Label";
38563858
sourceTree = "<group>";
38573859
};
3860+
02F843D8273646190017FE12 /* JetpackConnectionPackageSites */ = {
3861+
isa = PBXGroup;
3862+
children = (
3863+
02F843D9273646A30017FE12 /* JetpackBenefitsBanner.swift */,
3864+
);
3865+
path = JetpackConnectionPackageSites;
3866+
sourceTree = "<group>";
3867+
};
38583868
2611EE57243A46C500A74490 /* Categories */ = {
38593869
isa = PBXGroup;
38603870
children = (
@@ -6092,6 +6102,7 @@
60926102
CE85FD5120F677460080B73E /* Dashboard */ = {
60936103
isa = PBXGroup;
60946104
children = (
6105+
02F843D8273646190017FE12 /* JetpackConnectionPackageSites */,
60956106
028BAC4322F3AE3B008BB4AF /* Stats v4 */,
60966107
029D444B22F1417400DEFA8A /* Stats v3 */,
60976108
029D444722F13F5C00DEFA8A /* Factories */,
@@ -8102,6 +8113,7 @@
81028113
B5AA7B3D20ED5D15004DA14F /* SessionManager.swift in Sources */,
81038114
74C6FEA521C2F1FA009286B6 /* AboutViewController.swift in Sources */,
81048115
B53B3F37219C75AC00DF1EB6 /* OrderLoaderViewController.swift in Sources */,
8116+
02F843DA273646A30017FE12 /* JetpackBenefitsBanner.swift in Sources */,
81058117
027D4A8D2526FD1800108626 /* SettingsViewController.swift in Sources */,
81068118
02E262C9238D0AD300B79588 /* ProductStockStatusListSelectorCommand.swift in Sources */,
81078119
CE2A9FC823C3D2D4002BEC1C /* RefundedProductsDataSource.swift in Sources */,

0 commit comments

Comments
 (0)