Skip to content

Commit 3c57e6d

Browse files
authored
Merge pull request #7792 from woocommerce/hack/lockscreen-widgets-app-link
Lock Screen Widgets: Add app link widget
2 parents 023402a + 4298cb7 commit 3c57e6d

File tree

7 files changed

+119
-1
lines changed

7 files changed

+119
-1
lines changed

Experiments/Experiments/DefaultFeatureFlagService.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
3737
return true
3838
case .orderCreationSearchCustomers:
3939
return buildConfig == .localDeveloper || buildConfig == .alpha
40+
case .lockscreenWidgets:
41+
return buildConfig == .localDeveloper || buildConfig == .alpha
4042
case .replyToProductReviews:
4143
return buildConfig == .localDeveloper || buildConfig == .alpha
4244
default:

Experiments/Experiments/FeatureFlag.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ public enum FeatureFlag: Int {
7878
///
7979
case orderCreationSearchCustomers
8080

81+
/// Enables lock screen widgets
82+
///
83+
case lockscreenWidgets
84+
8185
/// Enables replying to product reviews
8286
///
8387
case replyToProductReviews

WooCommerce/Classes/System/WooConstants.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ enum WooConstants {
5353
/// Store Info Widget Identifier.
5454
///
5555
static let storeInfoWidgetKind = "StoreInfoWidget"
56+
57+
/// App link Widget Identifier.
58+
///
59+
static let appLinkWidgetKind = "AppLinkWidget"
5660
}
5761

5862
// MARK: URLs
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import WidgetKit
2+
import SwiftUI
3+
import Experiments
4+
5+
/// Static widget - app launch button
6+
///
7+
struct AppLinkWidget: Widget {
8+
private let enableLockscreenWidgets = DefaultFeatureFlagService().isFeatureFlagEnabled(.lockscreenWidgets)
9+
10+
private var supportedFamilies: [WidgetFamily] {
11+
if #available(iOSApplicationExtension 16.0, *), enableLockscreenWidgets {
12+
return [.accessoryCircular]
13+
} else {
14+
return []
15+
}
16+
}
17+
18+
var body: some WidgetConfiguration {
19+
StaticConfiguration(kind: WooConstants.appLinkWidgetKind, provider: AppLinkProvider()) { _ in
20+
AppButtonView()
21+
}
22+
.configurationDisplayName(Localization.title)
23+
.description(Localization.description)
24+
.supportedFamilies(supportedFamilies)
25+
}
26+
}
27+
28+
private struct AppLinkProvider: TimelineProvider {
29+
/// Type that represents the all the possible Widget states
30+
///
31+
enum AppLinkEntry: TimelineEntry {
32+
// Single possible state
33+
case appLink
34+
35+
// Current date, needed by the `TimelineEntry` protocol.
36+
var date: Date { Date() }
37+
}
38+
39+
func placeholder(in context: Context) -> AppLinkEntry {
40+
return .appLink
41+
}
42+
43+
func getSnapshot(in context: Context, completion: @escaping (AppLinkEntry) -> Void) {
44+
completion(.appLink)
45+
}
46+
47+
func getTimeline(in context: Context, completion: @escaping (Timeline<AppLinkEntry>) -> Void) {
48+
let timeline = Timeline<AppLinkEntry>(entries: [.appLink], policy: .never)
49+
completion(timeline)
50+
}
51+
}
52+
53+
private struct AppButtonView: View {
54+
var body: some View {
55+
ZStack {
56+
Circle()
57+
.fill(Color.black)
58+
Image(uiImage: .wooLogoWhite)
59+
.resizable()
60+
.scaledToFit()
61+
.padding(10)
62+
}
63+
}
64+
}
65+
66+
// MARK: Constants
67+
68+
/// Constants definition
69+
///
70+
private extension AppLinkWidget {
71+
enum Localization {
72+
static let title = AppLocalizedString(
73+
"appLinkWidget.displayName",
74+
value: "Icon",
75+
comment: "Widget title, displayed when selecting which widget to add"
76+
)
77+
static let description = AppLocalizedString(
78+
"appLinkWidget.description",
79+
value: "Quickly Launch WooCommerce",
80+
comment: "Widget description, displayed when selecting which widget to add"
81+
)
82+
}
83+
}
84+
85+
// MARK: Previews
86+
87+
@available(iOSApplicationExtension 16.0, *)
88+
struct AppLinkWidget_Previews: PreviewProvider {
89+
static var previews: some View {
90+
AppButtonView()
91+
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
92+
}
93+
}

WooCommerce/StoreWidgets/StoreInfoWidget.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import WidgetKit
22
import SwiftUI
33
import WooFoundation
4-
import Experiments
54

65
/// Main StoreInfo Widget type.
76
///
@@ -325,11 +324,14 @@ struct StoreWidgets_Previews: PreviewProvider {
325324
)
326325
.previewContext(WidgetPreviewContext(family: .systemMedium))
327326
.environment(\.sizeCategory, .extraExtraLarge)
327+
.previewDisplayName("XXL font")
328328

329329
NotLoggedInView()
330330
.previewContext(WidgetPreviewContext(family: .systemMedium))
331+
.previewDisplayName("Not logged in")
331332

332333
UnableToFetchView()
333334
.previewContext(WidgetPreviewContext(family: .systemMedium))
335+
.previewDisplayName("Unable to fetch data")
334336
}
335337
}

WooCommerce/StoreWidgets/StoreWidgets.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ struct StoreWidgetsBundle: WidgetBundle {
88
var body: some Widget {
99
// Add here any widget you want to be available
1010
StoreInfoWidget()
11+
AppLinkWidget()
1112
}
1213
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@
11531153
AEC95D432774D07B001571F5 /* CreateOrderAddressFormViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEC95D422774D07B001571F5 /* CreateOrderAddressFormViewModel.swift */; };
11541154
AECD57D226DFDF7500A3B580 /* EditOrderAddressForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = AECD57D126DFDF7500A3B580 /* EditOrderAddressForm.swift */; };
11551155
AED089F227C794BC0020AE10 /* View+CurrencySymbol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AED089F127C794BC0020AE10 /* View+CurrencySymbol.swift */; };
1156+
AED9012D28E5F517002B4572 /* AppLinkWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = AED9012C28E5F517002B4572 /* AppLinkWidget.swift */; };
11561157
AEDDDA0A25CA9C980077F9B2 /* AttributePickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEDDDA0925CA9C980077F9B2 /* AttributePickerViewController.swift */; };
11571158
AEDDDA1A25CAB2170077F9B2 /* AttributePickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AEDDDA1925CAB2170077F9B2 /* AttributePickerViewController.xib */; };
11581159
AEE085B52897C871007ACE20 /* LinkedProductsPromoCampaign.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE085B42897C871007ACE20 /* LinkedProductsPromoCampaign.swift */; };
@@ -3044,6 +3045,7 @@
30443045
AEC95D422774D07B001571F5 /* CreateOrderAddressFormViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateOrderAddressFormViewModel.swift; sourceTree = "<group>"; };
30453046
AECD57D126DFDF7500A3B580 /* EditOrderAddressForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditOrderAddressForm.swift; sourceTree = "<group>"; };
30463047
AED089F127C794BC0020AE10 /* View+CurrencySymbol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+CurrencySymbol.swift"; sourceTree = "<group>"; };
3048+
AED9012C28E5F517002B4572 /* AppLinkWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLinkWidget.swift; sourceTree = "<group>"; };
30473049
AEDDDA0925CA9C980077F9B2 /* AttributePickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributePickerViewController.swift; sourceTree = "<group>"; };
30483050
AEDDDA1925CAB2170077F9B2 /* AttributePickerViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AttributePickerViewController.xib; sourceTree = "<group>"; };
30493051
AEE085B42897C871007ACE20 /* LinkedProductsPromoCampaign.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkedProductsPromoCampaign.swift; sourceTree = "<group>"; };
@@ -5359,6 +5361,7 @@
53595361
children = (
53605362
3F50FE4028C8319A00C89201 /* Entitlements */,
53615363
26FFD32828C6A0E4002E5E5E /* Images */,
5364+
AED9012B28E5F27B002B4572 /* Lockscreen */,
53625365
3F1FA84528B60125009E246C /* StoreWidgets.swift */,
53635366
265C99E028B9BA43005E6117 /* StoreInfoWidget.swift */,
53645367
265C99E328B9C834005E6117 /* StoreInfoProvider.swift */,
@@ -6482,6 +6485,14 @@
64826485
path = "Address Edit";
64836486
sourceTree = "<group>";
64846487
};
6488+
AED9012B28E5F27B002B4572 /* Lockscreen */ = {
6489+
isa = PBXGroup;
6490+
children = (
6491+
AED9012C28E5F517002B4572 /* AppLinkWidget.swift */,
6492+
);
6493+
path = Lockscreen;
6494+
sourceTree = "<group>";
6495+
};
64856496
AEDDDA0825CA9C0A0077F9B2 /* Edit Attributes */ = {
64866497
isa = PBXGroup;
64876498
children = (
@@ -9347,6 +9358,7 @@
93479358
isa = PBXSourcesBuildPhase;
93489359
buildActionMask = 2147483647;
93499360
files = (
9361+
AED9012D28E5F517002B4572 /* AppLinkWidget.swift in Sources */,
93509362
2608C50728C941D600C9DFC0 /* UserDefaults+Woo.swift in Sources */,
93519363
265C99E628B9CB8E005E6117 /* StoreInfoViewModifiers.swift in Sources */,
93529364
2608C50628C93AB700C9DFC0 /* WooConstants.swift in Sources */,

0 commit comments

Comments
 (0)