| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import Foundation |
| import SwiftUI |
| import WidgetKit |
| |
| #if IOS_ENABLE_LOCKSCREEN_WIDGET |
| #if IOS_AVAILABLE_LOCKSCREEN_WIDGET |
| |
| enum LockscreenLauncherWidgetType { |
| case search, incognito, voiceSearch, dinoGame |
| |
| struct Configuration { |
| let displayName: LocalizedStringKey, description: LocalizedStringKey, imageName: String, |
| accessibilityLabel: LocalizedStringKey, |
| widgetURL: URL |
| |
| var supportedFamilies: [WidgetFamily] { |
| if #available(iOS 16, *) { |
| return [.accessoryCircular] |
| } |
| return [] |
| } |
| } |
| |
| var configuration: Configuration { |
| switch self { |
| case .search: |
| return Configuration( |
| displayName: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_SEARCH_DISPLAY_NAME", |
| description: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_SEARCH_DESCRIPTION", |
| imageName: "lockscreen_chrome_logo", |
| accessibilityLabel: |
| "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_SEARCH_A11Y_LABEL", |
| widgetURL: WidgetConstants.LockscreenLauncherWidget.searchUrl) |
| case .incognito: |
| return Configuration( |
| displayName: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_INCOGNITO_DISPLAY_NAME", |
| description: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_INCOGNITO_DESCRIPTION", |
| imageName: "lockscreen_incognito_logo", |
| accessibilityLabel: |
| "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_INCOGNITO_A11Y_LABEL", |
| widgetURL: WidgetConstants.LockscreenLauncherWidget.incognitoUrl) |
| case .voiceSearch: |
| return Configuration( |
| displayName: |
| "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_VOICESEARCH_DISPLAY_NAME", |
| description: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_VOICESEARCH_DESCRIPTION", |
| imageName: "lockscreen_voicesearch_logo", |
| accessibilityLabel: |
| "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_VOICESEARCH_A11Y_LABEL", |
| widgetURL: WidgetConstants.LockscreenLauncherWidget.voiceSearchUrl) |
| case .dinoGame: |
| return Configuration( |
| displayName: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_GAME_DISPLAY_NAME", |
| description: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_GAME_DESCRIPTION", |
| imageName: "lockscreen_game_logo", |
| accessibilityLabel: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_GAME_A11Y_LABEL", |
| widgetURL: WidgetConstants.LockscreenLauncherWidget.gameUrl) |
| } |
| } |
| } |
| |
| @MainActor |
| func lockScreenWidgetBackground() -> some View { |
| if #available(iOS 16.0, *) { |
| return AccessoryWidgetBackground() |
| } else { |
| // Widget only supports iOS16+ |
| return EmptyView() |
| } |
| } |
| |
| struct LockscreenLauncherWidgetEntryView: View { |
| let entry: Provider.Entry |
| let configuration: LockscreenLauncherWidgetType.Configuration |
| |
| var body: some View { |
| let configuration = self.configuration |
| ZStack { |
| Image(configuration.imageName) |
| .renderingMode(.template) |
| .foregroundColor(.white) |
| } |
| .widgetURL(configuration.widgetURL) |
| .accessibilityElement() |
| .accessibilityLabel(configuration.accessibilityLabel) |
| .crContainerBackground(lockScreenWidgetBackground()) |
| } |
| } |
| |
| @MainActor |
| func lockscreenLauncherWidgetConfiguration( |
| ofKind kind: String, forType type: LockscreenLauncherWidgetType |
| ) -> some WidgetConfiguration { |
| let configuration = type.configuration |
| return StaticConfiguration(kind: kind, provider: Provider()) { entry in |
| LockscreenLauncherWidgetEntryView(entry: entry, configuration: configuration) |
| } |
| .configurationDisplayName( |
| Text(configuration.displayName) |
| ) |
| .description(Text(configuration.description)) |
| .supportedFamilies(configuration.supportedFamilies) |
| .crDisfavoredLocations() |
| .crContainerBackgroundRemovable(false) |
| } |
| |
| struct LockscreenLauncherSearchWidget: Widget { |
| // Changing |kind| or deleting this widget will cause all installed instances of this widget |
| // to stop updating and show the placeholder state. |
| let kind: String = "LockscreenLauncherSearchWidget" |
| |
| var body: some WidgetConfiguration { |
| lockscreenLauncherWidgetConfiguration(ofKind: kind, forType: .search) |
| } |
| } |
| |
| struct LockscreenLauncherIncognitoWidget: Widget { |
| // Changing |kind| or deleting this widget will cause all installed instances of this widget |
| // to stop updating and show the placeholder state. |
| let kind: String = "LockscreenLauncherIncognitoWidget" |
| |
| var body: some WidgetConfiguration { |
| lockscreenLauncherWidgetConfiguration(ofKind: kind, forType: .incognito) |
| } |
| } |
| |
| struct LockscreenLauncherVoiceSearchWidget: Widget { |
| // Changing |kind| or deleting this widget will cause all installed instances of this widget |
| // to stop updating and show the placeholder state. |
| let kind: String = "LockscreenLauncherVoiceSearchWidget" |
| |
| var body: some WidgetConfiguration { |
| lockscreenLauncherWidgetConfiguration(ofKind: kind, forType: .voiceSearch) |
| } |
| } |
| |
| struct LockscreenLauncherGameWidget: Widget { |
| // Changing |kind| or deleting this widget will cause all installed instances of this widget |
| // to stop updating and show the placeholder state. |
| let kind: String = "LockscreenLauncherGameWidget" |
| |
| var body: some WidgetConfiguration { |
| lockscreenLauncherWidgetConfiguration(ofKind: kind, forType: .dinoGame) |
| } |
| } |
| |
| #endif // IOS_AVAILABLE_LOCKSCREEN_WIDGET |
| #endif // IOS_ENABLE_LOCKSCREEN_WIDGET |