Bladeren bron

Add a prominent Widgets entry point in launcher.

Surface a dedicated Widgets button in the launcher header with first-run highlighting, and open the widgets hub directly so users no longer need the per-app menu to discover widgets.

Made-with: Cursor
Hussain Afzal 3 maanden geleden
bovenliggende
commit
c57c69ebb5
1 gewijzigde bestanden met toevoegingen van 70 en 0 verwijderingen
  1. 70 0
      google_apps/LauncherRootView.swift

+ 70 - 0
google_apps/LauncherRootView.swift

@@ -28,6 +28,7 @@ struct LauncherRootView: View {
     @AppStorage("statusBarAppIDsData") private var statusBarAppIDsData = ""
     @AppStorage("widgetAppIDsData") private var widgetAppIDsData = ""
     @AppStorage("hiddenLauncherAppIDsData") private var hiddenLauncherAppIDsData = ""
+    @AppStorage("hasOpenedWidgetsHubFromLauncher") private var hasOpenedWidgetsHubFromLauncher = false
 
     private var apps: [LauncherApp] {
         let hiddenIDs = decodeUUIDSet(from: hiddenLauncherAppIDsData)
@@ -119,6 +120,10 @@ struct LauncherRootView: View {
                             InAppBrowserWindowManager.shared.open(url: url, title: "Google")
                         }
                     },
+                    onOpenWidgets: {
+                        openWidgetsHub()
+                    },
+                    shouldHighlightWidgets: !hasOpenedWidgetsHubFromLauncher,
                     onRestoreApp: { appID in
                         restoreHiddenApp(id: appID)
                     },
@@ -310,6 +315,7 @@ struct LauncherRootView: View {
     }
 
     private func openWidgetsPage(for app: LauncherApp) {
+        hasOpenedWidgetsHubFromLauncher = true
         var updated = decodeUUIDSetGlobal(from: widgetAppIDsData)
         updated.insert(app.id)
         widgetAppIDsData = encodeUUIDSetGlobal(updated)
@@ -320,6 +326,15 @@ struct LauncherRootView: View {
         )
     }
 
+    private func openWidgetsHub() {
+        hasOpenedWidgetsHubFromLauncher = true
+        let firstAppID = orderedApps.first(where: { !$0.isCreateNew })?.id
+        WidgetsWindowManager.shared.open(
+            apps: orderedApps.filter { !$0.isCreateNew },
+            selectedAppID: firstAppID
+        )
+    }
+
     private func addCustomApp(name: String, url: URL) {
         let newApp = LauncherApp(
             name: name,
@@ -524,8 +539,11 @@ private struct SearchHeader: View {
     let onToggleLayout: () -> Void
     let onOpenPremium: () -> Void
     let onOpenGoogle: () -> Void
+    let onOpenWidgets: () -> Void
+    let shouldHighlightWidgets: Bool
     let onRestoreApp: (UUID) -> Void
     let onRestoreAll: () -> Void
+    @State private var pulse = false
 
     var body: some View {
         HStack {
@@ -550,6 +568,52 @@ private struct SearchHeader: View {
             Spacer(minLength: 8)
 
             HStack(spacing: 12) {
+                Button(action: onOpenWidgets) {
+                    HStack(spacing: 6) {
+                        Image(systemName: "square.grid.2x2.fill")
+                        Text("Widgets")
+                            .font(.system(size: 12, weight: .bold))
+                        if shouldHighlightWidgets {
+                            Text("NEW")
+                                .font(.system(size: 9, weight: .black))
+                                .padding(.horizontal, 5)
+                                .padding(.vertical, 2)
+                                .background(
+                                    Capsule(style: .continuous)
+                                        .fill(Color.white.opacity(0.92))
+                                )
+                                .foregroundStyle(Color.blue.opacity(0.95))
+                        }
+                    }
+                    .foregroundStyle(.white.opacity(0.95))
+                    .padding(.horizontal, 10)
+                    .padding(.vertical, 6)
+                    .background(
+                        Capsule(style: .continuous)
+                            .fill(shouldHighlightWidgets ? Color.blue.opacity(0.82) : Color.white.opacity(0.12))
+                    )
+                    .overlay(
+                        Capsule(style: .continuous)
+                            .stroke(
+                                shouldHighlightWidgets
+                                ? Color.white.opacity(0.95)
+                                : Color.white.opacity(0.15),
+                                lineWidth: shouldHighlightWidgets ? 1.4 : 1
+                            )
+                    )
+                    .shadow(
+                        color: shouldHighlightWidgets
+                        ? Color.blue.opacity(0.55)
+                        : Color.clear,
+                        radius: pulse ? 18 : 9,
+                        x: 0,
+                        y: 5
+                    )
+                    .scaleEffect(shouldHighlightWidgets && pulse ? 1.03 : 1.0)
+                    .animation(.easeInOut(duration: 1.2).repeatForever(autoreverses: true), value: pulse)
+                }
+                .buttonStyle(.plain)
+
                 Button(action: onToggleLayout) {
                     Image(systemName: isPanelMode ? "square.grid.2x2" : "list.bullet")
                 }
@@ -588,6 +652,12 @@ private struct SearchHeader: View {
             .foregroundStyle(.white.opacity(0.82))
             .padding(.trailing, 4)
         }
+        .onAppear {
+            pulse = shouldHighlightWidgets
+        }
+        .onChange(of: shouldHighlightWidgets) { shouldHighlight in
+            pulse = shouldHighlight
+        }
     }
 }