From 18c90acda54cb46815a081ecfc36ea8f2b9e93fd Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 29 Jun 2026 00:12:04 +0800
Subject: [PATCH] Fix custom hotkey settings UI for 8.2.1

---
 src/Apptag/PreferencesView.swift |  170 ++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 115 insertions(+), 55 deletions(-)

diff --git a/src/Apptag/PreferencesView.swift b/src/Apptag/PreferencesView.swift
index 41fec66..8838d3d 100644
--- a/src/Apptag/PreferencesView.swift
+++ b/src/Apptag/PreferencesView.swift
@@ -944,6 +944,7 @@
                 customizeTitle: proEntitlement.isUnlocked ? tr("hotkeys.customize") : tr("pro.card.badge"),
                 restoreTitle: tr("hotkeys.restoreDefault"),
                 isRecording: recordingHotkeyKind == .main,
+                isProLocked: !proEntitlement.isUnlocked,
                 canRestore: proEntitlement.isUnlocked && LauncherHotkeySettings.hasCustomHotkey(for: .main),
                 onCustomize: { startHotkeyRecording(for: .main) },
                 onRestore: { restoreDefaultHotkey(for: .main) }
@@ -966,6 +967,7 @@
                 customizeTitle: proEntitlement.isUnlocked ? tr("hotkeys.customize") : tr("pro.card.badge"),
                 restoreTitle: tr("hotkeys.restoreDefault"),
                 isRecording: recordingHotkeyKind == .quickSearch,
+                isProLocked: !proEntitlement.isUnlocked,
                 canRestore: proEntitlement.isUnlocked && LauncherHotkeySettings.hasCustomHotkey(for: .quickSearch),
                 onCustomize: { startHotkeyRecording(for: .quickSearch) },
                 onRestore: { restoreDefaultHotkey(for: .quickSearch) }
@@ -1728,32 +1730,27 @@
     let statusTone: HotkeyStatusTone
 
     var body: some View {
-        VStack(alignment: .leading, spacing: 12) {
-            HStack(alignment: .top, spacing: 12) {
-                VStack(alignment: .leading, spacing: 3) {
-                    Text(title)
-                        .font(.system(size: 13, weight: .semibold))
-                    Text(description)
-                        .font(.caption)
-                        .foregroundStyle(.secondary)
-                        .fixedSize(horizontal: false, vertical: true)
-                }
-                .frame(maxWidth: .infinity, alignment: .leading)
-
-                VStack(alignment: .leading, spacing: 4) {
-                    Text(displayText)
-                        .font(.system(size: 15, weight: .semibold))
-                        .lineLimit(1)
-                        .minimumScaleFactor(0.85)
-                    Text(statusText)
-                        .font(.system(size: 11, weight: .semibold))
-                        .foregroundStyle(statusTone.foreground)
-                        .padding(.horizontal, 8)
-                        .padding(.vertical, 3)
-                        .background(Capsule().fill(statusTone.background))
-                }
-                .frame(width: 180, alignment: .leading)
+        HStack(alignment: .center, spacing: 18) {
+            VStack(alignment: .leading, spacing: 3) {
+                Text(title)
+                    .font(.system(size: 13, weight: .semibold))
+                Text(description)
+                    .font(.caption)
+                    .foregroundStyle(.secondary)
+                    .fixedSize(horizontal: false, vertical: true)
             }
+            .frame(maxWidth: .infinity, alignment: .leading)
+
+            HStack(alignment: .center, spacing: 12) {
+                Text(displayText)
+                    .font(.system(size: 15, weight: .semibold))
+                    .lineLimit(1)
+                    .minimumScaleFactor(0.85)
+                    .frame(width: 156, alignment: .leading)
+
+                HotkeyStatusPill(text: statusText, tone: statusTone)
+            }
+            .frame(width: 310, alignment: .leading)
         }
         .padding(12)
         .background(
@@ -1776,36 +1773,32 @@
     let customizeTitle: String
     let restoreTitle: String
     let isRecording: Bool
+    let isProLocked: Bool
     let canRestore: Bool
     let onCustomize: () -> Void
     let onRestore: () -> Void
 
     var body: some View {
-        VStack(alignment: .leading, spacing: 12) {
-            HStack(alignment: .top, spacing: 12) {
-                VStack(alignment: .leading, spacing: 3) {
-                    Text(title)
-                        .font(.system(size: 13, weight: .semibold))
-                    Text(description)
-                        .font(.caption)
-                        .foregroundStyle(.secondary)
-                        .fixedSize(horizontal: false, vertical: true)
-                }
-                .frame(maxWidth: .infinity, alignment: .leading)
+        HStack(alignment: .center, spacing: 18) {
+            VStack(alignment: .leading, spacing: 3) {
+                Text(title)
+                    .font(.system(size: 13, weight: .semibold))
+                Text(description)
+                    .font(.caption)
+                    .foregroundStyle(.secondary)
+                    .fixedSize(horizontal: false, vertical: true)
+            }
+            .frame(maxWidth: .infinity, alignment: .leading)
 
-                VStack(alignment: .leading, spacing: 7) {
+            HStack(alignment: .center, spacing: 12) {
+                VStack(alignment: .leading, spacing: 6) {
                     Text(isRecording ? "…" : displayText)
                         .font(.system(size: 15, weight: .semibold))
                         .lineLimit(1)
                         .minimumScaleFactor(0.85)
 
                     HStack(spacing: 6) {
-                        Text(statusText)
-                            .font(.system(size: 11, weight: .semibold))
-                            .foregroundStyle(statusTone.foreground)
-                            .padding(.horizontal, 8)
-                            .padding(.vertical, 3)
-                            .background(Capsule().fill(statusTone.background))
+                        HotkeyStatusPill(text: statusText, tone: statusTone)
 
                         if isRecording {
                             Text(tr("hotkeys.recordingInline"))
@@ -1813,20 +1806,23 @@
                                 .foregroundStyle(.blue)
                         }
                     }
-
-                    HStack(spacing: 8) {
-                        Button(customizeTitle, action: onCustomize)
-                            .buttonStyle(.borderedProminent)
-                            .controlSize(.small)
-
-                        Button(restoreTitle, action: onRestore)
-                            .buttonStyle(.bordered)
-                            .controlSize(.small)
-                            .disabled(!canRestore)
-                    }
                 }
-                .frame(width: 230, alignment: .leading)
+                .frame(width: 156, alignment: .leading)
+
+                HotkeyPrimaryActionButton(
+                    title: customizeTitle,
+                    isProLocked: isProLocked,
+                    action: onCustomize
+                )
+
+                if canRestore {
+                    HotkeySecondaryActionButton(
+                        title: restoreTitle,
+                        action: onRestore
+                    )
+                }
             }
+            .frame(width: 310, alignment: .leading)
         }
         .padding(12)
         .background(
@@ -1840,6 +1836,70 @@
     }
 }
 
+private struct HotkeyStatusPill: View {
+    let text: String
+    let tone: HotkeyStatusTone
+
+    var body: some View {
+        Text(text)
+            .font(.system(size: 11, weight: .semibold))
+            .foregroundStyle(tone.foreground)
+            .lineLimit(1)
+            .padding(.horizontal, 8)
+            .padding(.vertical, 3)
+            .background(Capsule().fill(tone.background))
+    }
+}
+
+private struct HotkeyPrimaryActionButton: View {
+    let title: String
+    let isProLocked: Bool
+    let action: () -> Void
+
+    var body: some View {
+        Button(action: action) {
+            if isProLocked {
+                ProStatusPill(text: title, style: .locked, compact: true)
+            } else {
+                Text(title)
+                    .font(.system(size: 11, weight: .semibold))
+                    .foregroundStyle(Color.white)
+                    .lineLimit(1)
+                    .padding(.horizontal, 12)
+                    .padding(.vertical, 6)
+                    .background(
+                        Capsule(style: .continuous)
+                            .fill(Color.accentColor)
+                    )
+            }
+        }
+        .buttonStyle(.plain)
+        .contentShape(Capsule(style: .continuous))
+    }
+}
+
+private struct HotkeySecondaryActionButton: View {
+    let title: String
+    let action: () -> Void
+
+    var body: some View {
+        Button(action: action) {
+            Text(title)
+                .font(.system(size: 11, weight: .semibold))
+                .foregroundStyle(.secondary)
+                .lineLimit(1)
+                .padding(.horizontal, 12)
+                .padding(.vertical, 6)
+                .background(
+                    Capsule(style: .continuous)
+                        .fill(Color.secondary.opacity(0.12))
+                )
+        }
+        .buttonStyle(.plain)
+        .contentShape(Capsule(style: .continuous))
+    }
+}
+
 private struct SettingsConfirmationView: View {
     let title: String
     let message: String

--
Gitblit v1.9.3