Jelajahi Sumber

Remove Gmail medium (inbox preview) widget variant

- Keep gmail_small and gmail_large only; drop GmailWidgetMode.inboxPreview.
- Remove inbox preview UI and unused openComposeReply/openGmailSearch helpers.
- Map persisted gmail_medium widget instances to gmail_large.

Made-with: Cursor
huzaifahayat12 3 bulan lalu
induk
melakukan
70ef96eeb4

+ 1 - 146
google_apps/Widgets/GmailDesktopWidgetView.swift

@@ -4,7 +4,7 @@ import WebKit
 
 // MARK: - Public SwiftUI view
 
-/// Tiered Gmail desktop widget: compact unread + compose, inbox preview, or full embedded Gmail.
+/// Tiered Gmail desktop widget: compact unread + compose, or full embedded Gmail.
 struct GmailDesktopWidgetView: View {
     let app: LauncherApp
     let mode: GmailWidgetMode
@@ -18,8 +18,6 @@ struct GmailDesktopWidgetView: View {
             switch mode {
             case .compact:
                 compactBody
-            case .inboxPreview:
-                inboxPreviewBody
             case .interactive:
                 interactiveBody
             }
@@ -88,126 +86,6 @@ struct GmailDesktopWidgetView: View {
         .opacity(isPreview ? 0.85 : 1)
     }
 
-    // MARK: - Medium (inbox preview)
-
-    private struct PreviewRow: Identifiable {
-        let id: String
-        let sender: String
-        let subject: String
-        let time: String
-        let searchQuery: String
-    }
-
-    private static let previewRows: [PreviewRow] = [
-        PreviewRow(id: "1", sender: "Alex Chen", subject: "Q4 roadmap — draft review", time: "9:42a", searchQuery: "from:alex"),
-        PreviewRow(id: "2", sender: "Google Alerts", subject: "News: your weekly digest", time: "8:10a", searchQuery: "from:googlealerts"),
-        PreviewRow(id: "3", sender: "HR Benefits", subject: "Open enrollment ends Friday", time: "Yesterday", searchQuery: "from:hr"),
-    ]
-
-    private var inboxPreviewBody: some View {
-        ZStack(alignment: .topLeading) {
-            gmailGradientBackground
-                .frame(maxWidth: .infinity, maxHeight: .infinity)
-            ScrollView {
-                VStack(alignment: .leading, spacing: 10) {
-                    HStack(spacing: 8) {
-                        AppIconView(app: app, size: 32, showAppBackground: false, iconPaddingFactor: 0.08)
-                        Text("Inbox preview")
-                            .font(.system(size: 14, weight: .bold))
-                            .foregroundStyle(.white.opacity(0.95))
-                        Spacer(minLength: 0)
-                        Text("Sample")
-                            .font(.system(size: 10, weight: .bold))
-                            .foregroundStyle(.white.opacity(0.55))
-                            .padding(.horizontal, 8)
-                            .padding(.vertical, 4)
-                            .background(Capsule().fill(Color.white.opacity(0.12)))
-                    }
-
-                    compactButton(title: "Open Mail", systemImage: "envelope.open", emphasized: false) {
-                        openMailInBrowser()
-                    }
-
-                    Text("Recent messages")
-                        .font(.system(size: 11, weight: .semibold))
-                        .foregroundStyle(.white.opacity(0.62))
-
-                    VStack(spacing: 8) {
-                        ForEach(Self.previewRows) { row in
-                            previewRowView(row)
-                        }
-                    }
-                }
-                .frame(maxWidth: .infinity, alignment: .leading)
-                .padding(.bottom, 4)
-            }
-            .padding(14)
-            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
-        }
-        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
-        .disabled(isPreview)
-        .opacity(isPreview ? 0.85 : 1)
-    }
-
-    private func previewRowView(_ row: PreviewRow) -> some View {
-        VStack(alignment: .leading, spacing: 8) {
-            HStack(alignment: .top, spacing: 8) {
-                VStack(alignment: .leading, spacing: 3) {
-                    Text(row.sender)
-                        .font(.system(size: 12, weight: .bold))
-                        .foregroundStyle(.white.opacity(0.95))
-                        .lineLimit(1)
-                    Text(row.subject)
-                        .font(.system(size: 11, weight: .medium))
-                        .foregroundStyle(.white.opacity(0.78))
-                        .lineLimit(2)
-                }
-                Spacer(minLength: 0)
-                Text(row.time)
-                    .font(.system(size: 10, weight: .semibold))
-                    .foregroundStyle(.white.opacity(0.5))
-            }
-            HStack(spacing: 8) {
-                previewActionButton(title: "Reply", systemImage: "arrowshape.turn.up.left") {
-                    openComposeReply(subject: row.subject)
-                }
-                previewActionButton(title: "Archive", systemImage: "archivebox") {
-                    openGmailSearch(query: row.searchQuery)
-                }
-            }
-        }
-        .padding(10)
-        .background(
-            RoundedRectangle(cornerRadius: 12, style: .continuous)
-                .fill(Color.black.opacity(0.28))
-        )
-        .overlay(
-            RoundedRectangle(cornerRadius: 12, style: .continuous)
-                .stroke(Color.white.opacity(0.1), lineWidth: 1)
-        )
-    }
-
-    private func previewActionButton(title: String, systemImage: String, action: @escaping () -> Void) -> some View {
-        Button(action: {
-            NSApp.activate(ignoringOtherApps: true)
-            action()
-        }) {
-            HStack(spacing: 5) {
-                Image(systemName: systemImage)
-                    .font(.system(size: 10, weight: .semibold))
-                Text(title)
-                    .font(.system(size: 10, weight: .bold))
-            }
-            .foregroundStyle(.white.opacity(0.92))
-            .padding(.horizontal, 10)
-            .padding(.vertical, 6)
-            .background(Capsule().fill(Color.white.opacity(0.14)))
-        }
-        .buttonStyle(.plain)
-        .disabled(isPreview)
-        .allowsHitTesting(!isPreview)
-    }
-
     // MARK: - Large (interactive)
 
     @State private var searchText = ""
@@ -465,29 +343,6 @@ struct GmailDesktopWidgetView: View {
         InAppBrowserWindowManager.shared.open(url: url, title: app.name)
     }
 
-    private func openComposeReply(subject: String) {
-        guard !isPreview else { return }
-        var c = URLComponents()
-        c.scheme = "https"
-        c.host = "mail.google.com"
-        c.path = "/mail/u/\(gmailAccountSlot)/"
-        c.queryItems = [
-            URLQueryItem(name: "view", value: "cm"),
-            URLQueryItem(name: "fs", value: "1"),
-            URLQueryItem(name: "su", value: "Re: \(subject)"),
-        ]
-        guard let url = c.url else { return }
-        InAppBrowserWindowManager.shared.open(url: url, title: app.name)
-    }
-
-    private func openGmailSearch(query: String) {
-        guard !isPreview else { return }
-        let encoded = query.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlFragmentAllowed) ?? query
-        let path = "/mail/u/{{u}}/#search/\(encoded)"
-        let url = WidgetDeepLinkURL.resolved(base: baseURL, actionPath: path, accountSlot: gmailAccountSlot)
-        InAppBrowserWindowManager.shared.open(url: url, title: app.name)
-    }
-
     private func navigateToMailPath(_ path: String) {
         let url = WidgetDeepLinkURL.resolved(base: baseURL, actionPath: path, accountSlot: gmailAccountSlot)
         DispatchQueue.main.async {

+ 4 - 6
google_apps/Widgets/WidgetTemplates.swift

@@ -19,8 +19,6 @@ struct WidgetAction: Identifiable, Hashable {
 enum GmailWidgetMode: Hashable, Sendable {
     /// Unread count (local placeholder) and quick compose.
     case compact
-    /// Sample inbox rows with reply / archive-style shortcuts.
-    case inboxPreview
     /// Embedded Gmail (`WKWebView`) with search, category chips, and folder shortcuts.
     case interactive
 }
@@ -142,7 +140,7 @@ enum WidgetLayoutMode: Hashable {
     case actionsGrid(columns: Int)
     /// Embedded Google Maps (`WKWebView`) with search, traffic, and navigation shortcuts.
     case interactiveMap
-    /// Tiered Gmail: compact preview, inbox list, or full embedded inbox.
+    /// Tiered Gmail: compact preview or full embedded inbox.
     case gmail(GmailWidgetMode)
     /// Tiered Google Drive: recent files, starred preview, or large shortcut hub.
     case drive(DriveWidgetMode)
@@ -219,7 +217,6 @@ enum WidgetTemplates {
         case .gmail:
             return [
                 v("gmail_small", "Unread & compose", .small, false, .gmail(.compact), []),
-                v("gmail_medium", "Inbox preview", .medium, false, .gmail(.inboxPreview), []),
                 v("gmail_large", "Full inbox", .large, false, .gmail(.interactive), []),
             ]
         case .drive:
@@ -510,6 +507,9 @@ enum WidgetTemplates {
             if WidgetAppProfile.from(app: app) == .contacts {
                 if id == "contacts_small" || id == "contacts_large" { return "contacts_medium" }
             }
+            if WidgetAppProfile.from(app: app) == .gmail, id == "gmail_medium" {
+                return "gmail_large"
+            }
             return id
         }()
         if let normalizedID, let match = variants.first(where: { $0.id == normalizedID }) {
@@ -598,7 +598,6 @@ extension WidgetLayoutMode {
         case .gmail(let mode):
             switch mode {
             case .compact: return CGSize(width: 220, height: 220)
-            case .inboxPreview: return CGSize(width: 420, height: 480)
             case .interactive: return CGSize(width: 540, height: 580)
             }
         case .drive(let mode):
@@ -668,7 +667,6 @@ extension WidgetLayoutMode {
         case .gmail(let mode):
             switch mode {
             case .compact: return CGSize(width: 200, height: 200)
-            case .inboxPreview: return CGSize(width: 380, height: 420)
             case .interactive: return CGSize(width: 480, height: 440)
             }
         case .drive(let mode):