checkpoint: archive current 7.5.1 before performance optimization
42 files modified
13 files added
| | |
| | | # Apptag Project Rules |
| | | |
| | | 本项目 Hermes 必须严格遵守的规则 |
| | | Authoritative workflow standard: |
| | | |
| | | ## 版本管理 & 需求记录铁律(每次任务都必须执行) |
| | | - `Docs/ProjectManagement/Apptag_Development_Workflow_Standard_v1.0.md` |
| | | |
| | | 1. 任何修改文件前,必须先执行 checkpoint: |
| | | git add -A && git commit -m "checkpoint: [本次任务简要描述]" |
| | | 2. 任务完成后,**必须**更新 DECISIONS.md: |
| | | - 在文件最顶部追加一节新内容(使用当前日期) |
| | | - 格式必须严格遵守下面的模板 |
| | | 3. 最后执行正式 commit: |
| | | git add DECISIONS.md .hermes.md && git commit -m "docs: 更新 DECISIONS.md [任务描述]" |
| | | 4. 如果是重大功能,自动推送 GitHub PR(可选) |
| | | Hermes and any coder working in this repository must follow that document as the single workflow authority. |
| | | |
| | | ## 上下文管理规则 |
| | | |
| | | - 每完成 5 个任务后,自动执行一次上下文压缩 |
| | | - 压缩完成后,在 DECISIONS.md 里新增一节 “压缩摘要” |
| | | |
| | | ## |
| | | |
| | | If a task request conflicts with the workflow standard, the coder must pause, cite the exact violated clause, and resolve the conflict before proceeding. |
| | |
| | | |
| | | enum AppDefaults { |
| | | static let schemaVersionKey = "initialDefaultsSchemaVersion" |
| | | static let currentSchemaVersion = 2 |
| | | static let currentSchemaVersion = 3 |
| | | |
| | | static let tagFontSize: Double = 22 |
| | | static let iconSize: Double = 80 |
| | |
| | | "hideAppNames": hideAppNames, |
| | | "showDockIcon": showDockIcon, |
| | | "launchAtLogin": launchAtLogin, |
| | | "showUncommonAppBubbles": showUncommonAppBubbles |
| | | "showUncommonAppBubbles": showUncommonAppBubbles, |
| | | LauncherHotkeyRegistrationStore.mainStateKey: LauncherHotkeyRegistrationState.active.rawValue, |
| | | LauncherHotkeyRegistrationStore.quickSearchStateKey: LauncherHotkeyRegistrationState.active.rawValue |
| | | ]) |
| | | migrateShortcutDefaultsIfNeeded() |
| | | removeShortcutCustomizationDefaults() |
| | | } |
| | | |
| | | static func hasStoredValue(for key: String) -> Bool { |
| | |
| | | return UserDefaults.standard.persistentDomain(forName: domain)?[key] != nil |
| | | } |
| | | |
| | | private static func migrateShortcutDefaultsIfNeeded() { |
| | | private static func removeShortcutCustomizationDefaults() { |
| | | let defaults = UserDefaults.standard |
| | | guard defaults.integer(forKey: schemaVersionKey) < currentSchemaVersion else { return } |
| | | |
| | | defaults.set(LauncherHotkey.defaultMain.serialized, forKey: LauncherHotkeyKind.main.storageKey) |
| | | defaults.removeObject(forKey: LauncherHotkeyKind.main.pendingStorageKey) |
| | | defaults.removeObject(forKey: LauncherHotkeyKind.main.statusKey) |
| | | defaults.removeObject(forKey: LauncherHotkeyKind.main.conflictMessageKey) |
| | | |
| | | let quickSearchKey = LauncherHotkeyKind.quickSearch.storageKey |
| | | let storedQuickSearch = defaults.string(forKey: quickSearchKey) ?? "" |
| | | if storedQuickSearch.isEmpty { |
| | | defaults.set(LauncherHotkey.defaultQuickSearch.serialized, forKey: quickSearchKey) |
| | | defaults.removeObject(forKey: LauncherHotkeyKind.quickSearch.pendingStorageKey) |
| | | defaults.removeObject(forKey: LauncherHotkeyKind.quickSearch.statusKey) |
| | | defaults.removeObject(forKey: LauncherHotkeyKind.quickSearch.conflictMessageKey) |
| | | } |
| | | |
| | | [ |
| | | "mainHotkey", |
| | | "quickSearchHotkey", |
| | | "mainHotkeyPending", |
| | | "quickSearchHotkeyPending", |
| | | "mainHotkeyStatus", |
| | | "quickSearchHotkeyStatus", |
| | | "mainHotkeyConflictMessage", |
| | | "quickSearchHotkeyConflictMessage" |
| | | ].forEach { defaults.removeObject(forKey: $0) } |
| | | defaults.set(currentSchemaVersion, forKey: schemaVersionKey) |
| | | } |
| | | } |
| | |
| | | private var statusItem: NSStatusItem? |
| | | private var overlayWindow: NSWindow? |
| | | private var overlayKeyMonitor: Any? |
| | | private var quickSearchExternalMouseMonitor: Any? |
| | | private var settingsWindow: NSWindow? // Track Settings window to keep it above overlay |
| | | private var mainHotkeyRef: EventHotKeyRef? |
| | | private var quickSearchHotkeyRef: EventHotKeyRef? |
| | | private var hotkeyEventHandlerInstalled = false |
| | | private var isQuickSearchOpen = false |
| | | private var isModalInteractionActive = false |
| | | private var areHotkeysPausedForCapture = false |
| | | private var isInEditMode = false // Suppress auto-dismiss during editing |
| | | private var isEditingAppNote = false |
| | | private var isConfiguringApplicationMenu = false |
| | |
| | | migrateDefaultGroupName() |
| | | TagDatabase.seedDefaultTags() |
| | | syncChromeSettings(force: true) |
| | | observeHotkeyStatusChanges() |
| | | registerConfiguredHotkeys() |
| | | observeOtherWindows() |
| | | observeSettingsClose() |
| | |
| | | |
| | | func applicationWillTerminate(_ notification: Notification) { |
| | | TagDatabase.flushPendingCategorySchemeBackupBatch() |
| | | removeQuickSearchExternalMouseMonitor() |
| | | } |
| | | |
| | | /// Ensure defaultGroupName is always the language-neutral key "Other". |
| | |
| | | } |
| | | |
| | | private var showAppListMenuTitle: String { |
| | | if let hotkey = LauncherHotkeyStore.hotkey(for: .main) { |
| | | return "\(tr("menu.showAppList")) \(hotkey.displayString)" |
| | | if LauncherHotkeyRegistrationStore.state(for: .main) == .failed { |
| | | return tr("menu.showShortcutUnavailable") |
| | | } |
| | | return tr("menu.showAppList") |
| | | return "\(tr("menu.showAppList")) \(LauncherHotkey.main.displayString)" |
| | | } |
| | | |
| | | private func observeApplicationMenuChanges() { |
| | |
| | | } |
| | | overlayWindow?.orderOut(nil) |
| | | removeOverlayKeyMonitor() |
| | | removeQuickSearchExternalMouseMonitor() |
| | | NotificationCenter.default.post(name: .tagLauncherOverlayDidHide, object: nil) |
| | | if force { |
| | | overlayWindow = nil |
| | |
| | | |
| | | private func registerConfiguredHotkeys() { |
| | | installHotkeyEventHandlerIfNeeded() |
| | | registerStoredHotkey(.main) |
| | | registerStoredHotkey(.quickSearch) |
| | | registerFixedHotkey(.main) |
| | | registerFixedHotkey(.quickSearch) |
| | | } |
| | | |
| | | @discardableResult |
| | | func applyHotkey(_ hotkey: LauncherHotkey?, for kind: LauncherHotkeyKind) -> Bool { |
| | | installHotkeyEventHandlerIfNeeded() |
| | | |
| | | if hotkey == nil { |
| | | unregisterHotkey(for: kind) |
| | | LauncherHotkeyStore.save(nil, for: kind) |
| | | LauncherHotkeyStore.setStatus(.disabled, message: nil, for: kind) |
| | | return true |
| | | } |
| | | |
| | | guard let hotkey else { return false } |
| | | let previousRef = hotkeyRef(for: kind) |
| | | if previousRef != nil, LauncherHotkeyStore.hotkey(for: kind) == hotkey { |
| | | LauncherHotkeyStore.setStatus(.active, message: nil, for: kind) |
| | | return true |
| | | } |
| | | setHotkeyRef(nil, for: kind) |
| | | private func registerFixedHotkey(_ kind: LauncherHotkeyKind) { |
| | | unregisterHotkey(for: kind) |
| | | let hotkey = kind.hotkey |
| | | |
| | | var hotkeyID = EventHotKeyID() |
| | | hotkeyID.signature = OSType(0x41505447) // 'APTG' |
| | |
| | | ) |
| | | |
| | | if status == noErr, let newRef { |
| | | if let previousRef { UnregisterEventHotKey(previousRef) } |
| | | setHotkeyRef(newRef, for: kind) |
| | | LauncherHotkeyStore.save(hotkey, for: kind) |
| | | LauncherHotkeyStore.setStatus(.active, message: nil, for: kind) |
| | | return true |
| | | LauncherHotkeyRegistrationStore.setActive(for: kind) |
| | | } else { |
| | | setHotkeyRef(nil, for: kind) |
| | | LauncherHotkeyRegistrationStore.setFailed(status, for: kind) |
| | | print("[TagLauncher] Fixed hotkey registration failed for \(kind.rawValue): \(status)") |
| | | } |
| | | |
| | | setHotkeyRef(previousRef, for: kind) |
| | | let message = LauncherHotkeyStore.knownConflictMessage(for: hotkey, status: status) |
| | | ?? tr("quickSearch.hotkeyConflict.generic") |
| | | LauncherHotkeyStore.savePending(hotkey, for: kind) |
| | | LauncherHotkeyStore.setStatus(.conflict, message: message, for: kind) |
| | | print("[TagLauncher] Hotkey registration failed for \(kind.rawValue): \(status)") |
| | | return false |
| | | } |
| | | |
| | | func retryHotkeyRegistration(for kind: LauncherHotkeyKind) { |
| | | _ = applyHotkey( |
| | | LauncherHotkeyStore.pendingHotkey(for: kind) ?? LauncherHotkeyStore.hotkey(for: kind), |
| | | for: kind |
| | | ) |
| | | } |
| | | |
| | | private func registerStoredHotkey(_ kind: LauncherHotkeyKind) { |
| | | _ = applyHotkey(LauncherHotkeyStore.hotkey(for: kind), for: kind) |
| | | private func observeHotkeyStatusChanges() { |
| | | NotificationCenter.default.addObserver( |
| | | forName: .tagLauncherHotkeyRegistrationChanged, |
| | | object: nil, |
| | | queue: .main |
| | | ) { [weak self] _ in |
| | | self?.setupMenuBar() |
| | | self?.configureApplicationMenuWhenAvailable(retries: 2) |
| | | } |
| | | } |
| | | |
| | | private func installHotkeyEventHandlerIfNeeded() { |
| | |
| | | object: nil, |
| | | queue: .main |
| | | ) { [weak self] notification in |
| | | self?.isQuickSearchOpen = (notification.userInfo?["active"] as? Bool) ?? false |
| | | guard let self else { return } |
| | | self.isQuickSearchOpen = (notification.userInfo?["active"] as? Bool) ?? false |
| | | if self.isQuickSearchOpen { |
| | | self.installQuickSearchExternalMouseMonitor() |
| | | } else { |
| | | self.removeQuickSearchExternalMouseMonitor() |
| | | } |
| | | } |
| | | |
| | | NotificationCenter.default.addObserver( |
| | |
| | | object: nil, |
| | | queue: .main |
| | | ) { [weak self] notification in |
| | | guard let self else { return } |
| | | let active = (notification.userInfo?["active"] as? Bool) ?? false |
| | | self.isModalInteractionActive = active |
| | | if (notification.userInfo?["source"] as? String) == "hotkeyRecording" { |
| | | self.setHotkeysPausedForCapture(active) |
| | | } |
| | | self?.isModalInteractionActive = (notification.userInfo?["active"] as? Bool) ?? false |
| | | } |
| | | |
| | | NotificationCenter.default.addObserver( |
| | | forName: .tagLauncherHotkeysChanged, |
| | | object: nil, |
| | | forName: NSApplication.didResignActiveNotification, |
| | | object: NSApp, |
| | | queue: .main |
| | | ) { [weak self] _ in |
| | | self?.setupMenuBar() |
| | | self?.configureApplicationMenuWhenAvailable(retries: 2) |
| | | guard self?.isQuickSearchOpen == true else { return } |
| | | NotificationCenter.default.post(name: .tagLauncherQuickSearchDismissRequested, object: nil) |
| | | } |
| | | } |
| | | |
| | | private func installQuickSearchExternalMouseMonitor() { |
| | | guard quickSearchExternalMouseMonitor == nil else { return } |
| | | quickSearchExternalMouseMonitor = NSEvent.addGlobalMonitorForEvents( |
| | | matching: [.leftMouseDown, .rightMouseDown, .otherMouseDown] |
| | | ) { [weak self] _ in |
| | | DispatchQueue.main.async { |
| | | guard self?.isQuickSearchOpen == true else { return } |
| | | NotificationCenter.default.post(name: .tagLauncherQuickSearchDismissRequested, object: nil) |
| | | } |
| | | } |
| | | } |
| | | |
| | | private func removeQuickSearchExternalMouseMonitor() { |
| | | if let quickSearchExternalMouseMonitor { |
| | | NSEvent.removeMonitor(quickSearchExternalMouseMonitor) |
| | | self.quickSearchExternalMouseMonitor = nil |
| | | } |
| | | } |
| | | |
| | |
| | | overlayWindow.level = isEditingAppNote ? Self.overlayTextInputLevel : Self.overlayDefaultLevel |
| | | if let settingsWindow, settingsWindow.parent == overlayWindow { |
| | | settingsWindow.level = overlayWindow.level |
| | | } |
| | | } |
| | | |
| | | private func setHotkeysPausedForCapture(_ paused: Bool) { |
| | | guard areHotkeysPausedForCapture != paused else { return } |
| | | areHotkeysPausedForCapture = paused |
| | | if paused { |
| | | unregisterHotkey(for: .main) |
| | | unregisterHotkey(for: .quickSearch) |
| | | } else { |
| | | registerConfiguredHotkeys() |
| | | } |
| | | } |
| | | |
| | |
| | | private var quickSearchOverlay: some View { |
| | | GeometryReader { proxy in |
| | | if quickSearchVisible { |
| | | QuickSearchBackdropClickView { |
| | | closeQuickSearch() |
| | | } |
| | | Color.black.opacity(0.001) |
| | | .frame(width: proxy.size.width, height: proxy.size.height) |
| | | .ignoresSafeArea() |
| | | .contentShape(Rectangle()) |
| | | .onTapGesture { |
| | | closeQuickSearch() |
| | | } |
| | | .zIndex(899) |
| | | |
| | | QuickSearchOverlayView( |
| | |
| | | <key>CFBundleShortVersionString</key> |
| | | <string>7.5.1</string> |
| | | <key>CFBundleVersion</key> |
| | | <string>751</string> |
| | | <string>20260520.1228</string> |
| | | <key>LSMinimumSystemVersion</key> |
| | | <string>15.0</string> |
| | | <key>NSHighResolutionCapable</key> |
| | |
| | | { |
| | | "menu.show": "ورّ TagLauncher", |
| | | "menu.showAppList": "ورّ قائمة التطبيقات", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "التفضيلات…", |
| | | "menu.quit": "خروج", |
| | | "menu.language": "اللغة", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "إظهار TagLauncher", |
| | | "menu.showAppList": "إظهار قائمة التطبيقات", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "التفضيلات…", |
| | | "menu.quit": "إنهاء", |
| | | "menu.language": "اللغة", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Zobrazit TagLauncher", |
| | | "menu.showAppList": "Zobrazit seznam aplikací", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Předvolby…", |
| | | "menu.quit": "Ukončit", |
| | | "menu.language": "Jazyk", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Vis TagLauncher", |
| | | "menu.showAppList": "Vis appliste", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Indstillinger…", |
| | | "menu.quit": "Slut", |
| | | "menu.language": "Sprog", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "TagLauncher anzeigen", |
| | | "menu.showAppList": "App-Liste anzeigen", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Einstellungen…", |
| | | "menu.quit": "Beenden", |
| | | "menu.language": "Sprache", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Show TagLauncher", |
| | | "menu.showAppList": "Show App List", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Preferences…", |
| | | "menu.quit": "Quit", |
| | | "menu.language": "Language", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Mostrar TagLauncher", |
| | | "menu.showAppList": "Mostrar lista de apps", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Preferencias…", |
| | | "menu.quit": "Salir", |
| | | "menu.language": "Idioma", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Afficher TagLauncher", |
| | | "menu.showAppList": "Afficher la liste des apps", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Préférences…", |
| | | "menu.quit": "Quitter", |
| | | "menu.language": "Langue", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Tampilkan TagLauncher", |
| | | "menu.showAppList": "Tampilkan daftar app", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Preferensi…", |
| | | "menu.quit": "Keluar", |
| | | "menu.language": "Bahasa", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Mostra TagLauncher", |
| | | "menu.showAppList": "Mostra elenco app", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Preferenze…", |
| | | "menu.quit": "Esci", |
| | | "menu.language": "Lingua", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "TagLauncherを表示", |
| | | "menu.showAppList": "アプリ一覧を表示", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "設定…", |
| | | "menu.quit": "終了", |
| | | "menu.language": "言語", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "TagLauncher 보기", |
| | | "menu.showAppList": "앱 목록 보기", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "환경설정…", |
| | | "menu.quit": "종료", |
| | | "menu.language": "언어", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Tunjukkan TagLauncher", |
| | | "menu.showAppList": "Tunjukkan senarai app", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Keutamaan…", |
| | | "menu.quit": "Keluar", |
| | | "menu.language": "Bahasa", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Vis TagLauncher", |
| | | "menu.showAppList": "Vis appliste", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Innstillinger…", |
| | | "menu.quit": "Avslutt", |
| | | "menu.language": "Språk", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Toon TagLauncher", |
| | | "menu.showAppList": "Toon applijst", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Voorkeuren…", |
| | | "menu.quit": "Stop", |
| | | "menu.language": "Taal", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Vis TagLauncher", |
| | | "menu.showAppList": "Vis appliste", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Innstillingar…", |
| | | "menu.quit": "Avslutt", |
| | | "menu.language": "Språk", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Vis TagLauncher", |
| | | "menu.showAppList": "Vis appliste", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Innstillinger…", |
| | | "menu.quit": "Avslutt", |
| | | "menu.language": "Språk", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Pokaż TagLauncher", |
| | | "menu.showAppList": "Pokaż listę aplikacji", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Preferencje…", |
| | | "menu.quit": "Zakończ", |
| | | "menu.language": "Język", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Mostrar TagLauncher", |
| | | "menu.showAppList": "Mostrar lista de apps", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Preferências…", |
| | | "menu.quit": "Sair", |
| | | "menu.language": "Idioma", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Afișează TagLauncher", |
| | | "menu.showAppList": "Afișează lista aplicațiilor", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Preferințe…", |
| | | "menu.quit": "Ieșire", |
| | | "menu.language": "Limbă", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Показать TagLauncher", |
| | | "menu.showAppList": "Показать список приложений", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Настройки…", |
| | | "menu.quit": "Выйти", |
| | | "menu.language": "Язык", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Прикажи TagLauncher", |
| | | "menu.showAppList": "Прикажи листу апликација", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Подешавања…", |
| | | "menu.quit": "Изађи", |
| | | "menu.language": "Језик", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Visa TagLauncher", |
| | | "menu.showAppList": "Visa applista", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Inställningar…", |
| | | "menu.quit": "Avsluta", |
| | | "menu.language": "Språk", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "แสดง TagLauncher", |
| | | "menu.showAppList": "แสดงรายการแอป", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "การตั้งค่า…", |
| | | "menu.quit": "ออก", |
| | | "menu.language": "ภาษา", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "TagLauncher’ı Göster", |
| | | "menu.showAppList": "Uygulama listesini göster", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Tercihler…", |
| | | "menu.quit": "Çık", |
| | | "menu.language": "Dil", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Показати TagLauncher", |
| | | "menu.showAppList": "Показати список програм", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Параметри…", |
| | | "menu.quit": "Вийти", |
| | | "menu.language": "Мова", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "Hiển thị TagLauncher", |
| | | "menu.showAppList": "Hiển thị danh sách ứng dụng", |
| | | "menu.shortcutUnavailable": "shortcut unavailable", |
| | | "menu.showShortcutUnavailable": "Show TagLauncher (shortcut unavailable)", |
| | | "menu.preferences": "Tùy chọn…", |
| | | "menu.quit": "Thoát", |
| | | "menu.language": "Ngôn ngữ", |
| | |
| | | "quickSearch.hotkeys": "Keyboard shortcuts", |
| | | "quickSearch.mainHotkey": "App list", |
| | | "quickSearch.mainHotkeyDesc": "Opens the TagLauncher app list.", |
| | | "quickSearch.directHotkey": "Quick Search (global)", |
| | | "quickSearch.directHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.record": "Change", |
| | | "quickSearch.recording": "Recording", |
| | | "quickSearch.clear": "Clear", |
| | | "quickSearch.restoreDefault": "Restore default", |
| | | "quickSearch.retry": "Retry registration", |
| | | "quickSearch.recordingHint": "Press the new global shortcut. Press Esc to cancel.", |
| | | "quickSearch.disabled": "Disabled", |
| | | "quickSearch.blocked": "Blocked", |
| | | "quickSearch.previousStillActive": "Previous shortcut remains active:", |
| | | "quickSearch.status.Active": "Active", |
| | | "quickSearch.status.Conflict": "Conflict", |
| | | "quickSearch.status.Disabled": "Disabled", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space is used by Spotlight. Change Spotlight in macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space is used by the Finder search window. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space is used to switch to the previous input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space is used to switch to the next input source. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space is used for Emoji & Symbols. Change macOS Keyboard Shortcuts, or choose another shortcut.", |
| | | "quickSearch.hotkeyConflict.generic": "This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and retry.", |
| | | "quickSearch.status.registrationFailed": "Registration failed", |
| | | "quickSearch.status.unavailable": "Shortcut unavailable", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. The app-list shortcut is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% cannot be registered right now. It may be used by macOS, an input method, or another app. Global Quick Search is temporarily unavailable. Check keyboard shortcuts or shortcut conflicts, then restart TagLauncher. Error code: %status%.", |
| | | "quickSearch.loading": "Preparing search index…", |
| | | "quickSearch.openKeyboardSettings": "Open macOS Keyboard Shortcuts settings", |
| | | "quickSearch.internalHotkey": "Quick Search (inside TagLauncher)", |
| | | "quickSearch.internalHotkeyDesc": "Works only while the TagLauncher app list is open.", |
| | | "quickSearch.internalHotkeyStatus": "App list only", |
| | | "quickSearch.globalHotkey": "Quick Search (global)", |
| | | "quickSearch.globalHotkeyDesc": "Open Quick Search globally when the TagLauncher app list is not visible.", |
| | | "quickSearch.spaceDisplay": "Space", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space may already be used by macOS input source or Globe/Fn shortcuts. Open macOS Keyboard Shortcuts to change that system shortcut, or choose another shortcut here." |
| | | "quickSearch.spaceDisplay": "Space" |
| | | } |
| | |
| | | { |
| | | "menu.show": "显示 TagLauncher", |
| | | "menu.showAppList": "显示应用列表", |
| | | "menu.shortcutUnavailable": "快捷键不可用", |
| | | "menu.showShortcutUnavailable": "显示 TagLauncher(快捷键不可用)", |
| | | "menu.preferences": "偏好设置…", |
| | | "menu.quit": "退出", |
| | | "menu.language": "语言", |
| | |
| | | "quickSearch.hotkeys": "快捷键", |
| | | "quickSearch.mainHotkey": "主界面", |
| | | "quickSearch.mainHotkeyDesc": "打开 TagLauncher 应用列表。", |
| | | "quickSearch.directHotkey": "快捷搜索(全局)", |
| | | "quickSearch.directHotkeyDesc": "不在 TagLauncher 主界面时,直接打开快捷搜索。全局有效。", |
| | | "quickSearch.record": "修改", |
| | | "quickSearch.recording": "录制中", |
| | | "quickSearch.clear": "清除", |
| | | "quickSearch.restoreDefault": "恢复默认", |
| | | "quickSearch.retry": "重试注册", |
| | | "quickSearch.recordingHint": "按下新的全局快捷键。按 Esc 取消。", |
| | | "quickSearch.disabled": "已关闭", |
| | | "quickSearch.blocked": "被阻塞", |
| | | "quickSearch.previousStillActive": "之前可用的快捷键仍保持可用:", |
| | | "quickSearch.status.Active": "已启用", |
| | | "quickSearch.status.Conflict": "冲突", |
| | | "quickSearch.status.Disabled": "已关闭", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space 已被 Spotlight 使用。请在 macOS 键盘快捷键中修改 Spotlight,或选择其他快捷键。", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space 已被 Finder 搜索窗口使用。请在 macOS 键盘快捷键中修改,或选择其他快捷键。", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space 已被“上一个输入法”使用。请在 macOS 键盘快捷键中修改,或选择其他快捷键。", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space 已被“下一个输入法”使用。请在 macOS 键盘快捷键中修改,或选择其他快捷键。", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space 已被“表情与符号”使用。请在 macOS 键盘快捷键中修改,或选择其他快捷键。", |
| | | "quickSearch.hotkeyConflict.generic": "这个快捷键已被 macOS 或其他 App 使用。请选择其他快捷键,或先修改其他 App 中的快捷键后再重试。", |
| | | "quickSearch.status.registrationFailed": "注册失败", |
| | | "quickSearch.status.unavailable": "快捷键不可用", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% 当前无法注册,可能被系统、输入法或其他软件占用。主界面快捷键暂不可用。请检查 macOS 键盘快捷键、输入法快捷键或其他常驻软件的快捷键占用,然后重启 TagLauncher。错误码:%status%。", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% 当前无法注册,可能被系统、输入法或其他软件占用。快捷搜索全局唤起暂不可用。请检查 macOS 键盘快捷键、输入法快捷键或其他常驻软件的快捷键占用,然后重启 TagLauncher。错误码:%status%。", |
| | | "quickSearch.loading": "正在准备搜索索引…", |
| | | "quickSearch.openKeyboardSettings": "打开 macOS 键盘快捷键设置", |
| | | "quickSearch.internalHotkey": "快捷搜索(TagLauncher 内部)", |
| | | "quickSearch.internalHotkeyDesc": "仅在 TagLauncher 主界面有效。", |
| | | "quickSearch.internalHotkeyStatus": "仅主界面有效", |
| | | "quickSearch.globalHotkey": "快捷搜索(全局)", |
| | | "quickSearch.globalHotkeyDesc": "不在 TagLauncher 主界面时,直接打开快捷搜索。全局有效。", |
| | | "quickSearch.spaceDisplay": "Space(空格键)", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space 可能已被 macOS 的输入法或地球键快捷键占用。请打开 macOS 键盘快捷键设置关闭或改掉对应系统快捷键,或在这里选择其他组合。" |
| | | "quickSearch.spaceDisplay": "Space(空格键)" |
| | | } |
| | |
| | | { |
| | | "menu.show": "顯示 TagLauncher", |
| | | "menu.showAppList": "顯示應用列表", |
| | | "menu.shortcutUnavailable": "快捷鍵不可用", |
| | | "menu.showShortcutUnavailable": "顯示 TagLauncher(快捷鍵不可用)", |
| | | "menu.preferences": "偏好設定…", |
| | | "menu.quit": "退出", |
| | | "menu.language": "語言", |
| | |
| | | "quickSearch.hotkeys": "快捷鍵", |
| | | "quickSearch.mainHotkey": "主介面", |
| | | "quickSearch.mainHotkeyDesc": "打開 TagLauncher 應用列表。", |
| | | "quickSearch.directHotkey": "快捷搜尋(全域)", |
| | | "quickSearch.directHotkeyDesc": "不在 TagLauncher 主介面時,直接打開快捷搜尋。全域有效。", |
| | | "quickSearch.record": "修改", |
| | | "quickSearch.recording": "錄製中", |
| | | "quickSearch.clear": "清除", |
| | | "quickSearch.restoreDefault": "恢復預設", |
| | | "quickSearch.retry": "重試註冊", |
| | | "quickSearch.recordingHint": "按下新的全域快捷鍵。按 Esc 取消。", |
| | | "quickSearch.disabled": "已關閉", |
| | | "quickSearch.blocked": "被阻塞", |
| | | "quickSearch.previousStillActive": "之前可用的快捷鍵仍保持可用:", |
| | | "quickSearch.status.Active": "已啟用", |
| | | "quickSearch.status.Conflict": "衝突", |
| | | "quickSearch.status.Disabled": "已關閉", |
| | | "quickSearch.hotkeyConflict.spotlight": "Command + Space 已被 Spotlight 使用。請在 macOS 鍵盤快捷鍵中修改 Spotlight,或選擇其他快捷鍵。", |
| | | "quickSearch.hotkeyConflict.finderSearch": "Option + Command + Space 已被 Finder 搜尋視窗使用。請在 macOS 鍵盤快捷鍵中修改,或選擇其他快捷鍵。", |
| | | "quickSearch.hotkeyConflict.previousInput": "Control + Space 已被「上一個輸入法」使用。請在 macOS 鍵盤快捷鍵中修改,或選擇其他快捷鍵。", |
| | | "quickSearch.hotkeyConflict.nextInput": "Control + Option + Space 已被「下一個輸入法」使用。請在 macOS 鍵盤快捷鍵中修改,或選擇其他快捷鍵。", |
| | | "quickSearch.hotkeyConflict.emoji": "Control + Command + Space 已被「表情與符號」使用。請在 macOS 鍵盤快捷鍵中修改,或選擇其他快捷鍵。", |
| | | "quickSearch.hotkeyConflict.generic": "這個快捷鍵已被 macOS 或其他 App 使用。請選擇其他快捷鍵,或先修改其他 App 中的快捷鍵後再重試。", |
| | | "quickSearch.status.registrationFailed": "註冊失敗", |
| | | "quickSearch.status.unavailable": "快捷鍵不可用", |
| | | "quickSearch.mainHotkeyUnavailableMessage": "%shortcut% 目前無法註冊,可能被系統、輸入法或其他軟體佔用。主介面快捷鍵暫時不可用。請檢查 macOS 鍵盤快捷鍵、輸入法快捷鍵或其他常駐軟體的快捷鍵佔用,然後重新啟動 TagLauncher。錯誤碼:%status%。", |
| | | "quickSearch.globalHotkeyUnavailableMessage": "%shortcut% 目前無法註冊,可能被系統、輸入法或其他軟體佔用。快捷搜尋全域喚起暫時不可用。請檢查 macOS 鍵盤快捷鍵、輸入法快捷鍵或其他常駐軟體的快捷鍵佔用,然後重新啟動 TagLauncher。錯誤碼:%status%。", |
| | | "quickSearch.loading": "正在準備搜尋索引…", |
| | | "quickSearch.openKeyboardSettings": "打開 macOS 鍵盤快捷鍵設定", |
| | | "quickSearch.internalHotkey": "快捷搜尋(TagLauncher 內部)", |
| | | "quickSearch.internalHotkeyDesc": "僅在 TagLauncher 主介面有效。", |
| | | "quickSearch.internalHotkeyStatus": "僅主介面有效", |
| | | "quickSearch.globalHotkey": "快捷搜尋(全域)", |
| | | "quickSearch.globalHotkeyDesc": "不在 TagLauncher 主介面時,直接打開快捷搜尋。全域有效。", |
| | | "quickSearch.spaceDisplay": "Space(空格鍵)", |
| | | "quickSearch.hotkeyConflict.fnSpace": "Fn + Space 可能已被 macOS 的輸入法或地球鍵快捷鍵佔用。請打開 macOS 鍵盤快捷鍵設定關閉或改掉對應系統快捷鍵,或在這裡選擇其他組合。" |
| | | "quickSearch.spaceDisplay": "Space(空格鍵)" |
| | | } |
| | |
| | | import SwiftUI |
| | | import AppKit |
| | | import Carbon |
| | | |
| | | // MARK: - Preferences View |
| | | |
| | |
| | | @AppStorage("showDockIcon") private var showDockIcon = AppDefaults.showDockIcon |
| | | @AppStorage("launchAtLogin") private var launchAtLogin = AppDefaults.launchAtLogin |
| | | @AppStorage("showUncommonAppBubbles") private var showUncommonAppBubbles = AppDefaults.showUncommonAppBubbles |
| | | @AppStorage("mainHotkeyRegistrationState") private var mainHotkeyRegistrationState = LauncherHotkeyRegistrationState.active.rawValue |
| | | @AppStorage("quickSearchHotkeyRegistrationState") private var quickSearchHotkeyRegistrationState = LauncherHotkeyRegistrationState.active.rawValue |
| | | @State private var selectedLanguage = L10n.currentCode |
| | | @State private var isRefreshingLanguage = false |
| | | @State private var allApps: [AppInfo] = [] |
| | |
| | | @State private var categoryScheme = TagDatabase.CategorySchemeState() |
| | | @State private var isApplyingSystemScheme = false |
| | | @State private var showApplySystemSchemeConfirmation = false |
| | | @State private var recordingHotkeyKind: LauncherHotkeyKind? = nil |
| | | @State private var hotkeyCaptureMonitor: Any? = nil |
| | | @State private var hotkeyRefreshToken = 0 |
| | | @State private var hotkeyStatusToast: String? = nil |
| | | @State private var hotkeyStatusToastToken: UUID? = nil |
| | | |
| | | private func scanApps() { |
| | | DispatchQueue.global(qos: .userInitiated).async { |
| | |
| | | alert.beginSheetModal(for: window) |
| | | } else { |
| | | alert.runModal() |
| | | } |
| | | } |
| | | |
| | | private var mainHotkeyState: LauncherHotkeyRegistrationState { |
| | | LauncherHotkeyRegistrationState(rawValue: mainHotkeyRegistrationState) ?? .active |
| | | } |
| | | |
| | | private var quickSearchHotkeyState: LauncherHotkeyRegistrationState { |
| | | LauncherHotkeyRegistrationState(rawValue: quickSearchHotkeyRegistrationState) ?? .active |
| | | } |
| | | |
| | | private func hotkeyStatusText(for kind: LauncherHotkeyKind) -> String { |
| | | switch kind { |
| | | case .main: |
| | | return mainHotkeyState == .failed |
| | | ? tr("quickSearch.status.registrationFailed") |
| | | : tr("quickSearch.status.Active") |
| | | case .quickSearch: |
| | | return quickSearchHotkeyState == .failed |
| | | ? tr("quickSearch.status.unavailable") |
| | | : tr("quickSearch.status.Active") |
| | | } |
| | | } |
| | | |
| | | private func hotkeyStatusTone(for kind: LauncherHotkeyKind) -> HotkeyStatusTone { |
| | | switch kind { |
| | | case .main: |
| | | return mainHotkeyState == .failed ? .warning : .active |
| | | case .quickSearch: |
| | | return quickSearchHotkeyState == .failed ? .warning : .active |
| | | } |
| | | } |
| | | |
| | | private func showPendingHotkeyWarningIfNeeded() { |
| | | var messages: [String] = [] |
| | | if LauncherHotkeyRegistrationStore.consumeNeedsAttention(for: .main), |
| | | LauncherHotkeyRegistrationStore.state(for: .main) == .failed { |
| | | messages.append(hotkeyFailureMessage(for: .main)) |
| | | } |
| | | if LauncherHotkeyRegistrationStore.consumeNeedsAttention(for: .quickSearch), |
| | | LauncherHotkeyRegistrationStore.state(for: .quickSearch) == .failed { |
| | | messages.append(hotkeyFailureMessage(for: .quickSearch)) |
| | | } |
| | | guard !messages.isEmpty else { return } |
| | | showHotkeyStatusToast(messages.joined(separator: "\n\n")) |
| | | } |
| | | |
| | | private func hotkeyFailureMessage(for kind: LauncherHotkeyKind) -> String { |
| | | let key = kind == .main |
| | | ? "quickSearch.mainHotkeyUnavailableMessage" |
| | | : "quickSearch.globalHotkeyUnavailableMessage" |
| | | let status = LauncherHotkeyRegistrationStore.failureCode(for: kind) |
| | | .map(String.init) ?? "-" |
| | | return tr(key) |
| | | .replacingOccurrences(of: "%shortcut%", with: kind.hotkey.displayString) |
| | | .replacingOccurrences(of: "%status%", with: status) |
| | | } |
| | | |
| | | private func showHotkeyStatusToast(_ message: String) { |
| | | let token = UUID() |
| | | hotkeyStatusToastToken = token |
| | | withAnimation(.easeOut(duration: 0.16)) { |
| | | hotkeyStatusToast = message |
| | | } |
| | | DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { |
| | | guard hotkeyStatusToastToken == token else { return } |
| | | withAnimation(.easeOut(duration: 0.18)) { |
| | | hotkeyStatusToast = nil |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | .contentShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) |
| | | } |
| | | |
| | | private func applyHotkey(_ hotkey: LauncherHotkey?, for kind: LauncherHotkeyKind) { |
| | | (NSApp.delegate as? AppDelegate)?.applyHotkey(hotkey, for: kind) |
| | | hotkeyRefreshToken &+= 1 |
| | | } |
| | | |
| | | private func retryHotkey(_ kind: LauncherHotkeyKind) { |
| | | (NSApp.delegate as? AppDelegate)?.retryHotkeyRegistration(for: kind) |
| | | hotkeyRefreshToken &+= 1 |
| | | } |
| | | |
| | | private func openKeyboardShortcutsSettings() { |
| | | let urls = [ |
| | | URL(string: "x-apple.systempreferences:com.apple.Keyboard-Settings.extension?Shortcuts"), |
| | | URL(string: "x-apple.systempreferences:com.apple.preference.keyboard?shortcuts") |
| | | ].compactMap { $0 } |
| | | guard let url = urls.first else { return } |
| | | NSWorkspace.shared.open(url) |
| | | } |
| | | |
| | | private func hotkeySettingsPanel() -> some View { |
| | | VStack(alignment: .leading, spacing: 12) { |
| | | HStack { |
| | | Text(tr("quickSearch.hotkeys")) |
| | | .font(.system(size: 13, weight: .semibold)) |
| | | .foregroundStyle(.secondary) |
| | | Spacer() |
| | | Button(action: openKeyboardShortcutsSettings) { |
| | | Label(tr("quickSearch.openKeyboardSettings"), systemImage: "keyboard") |
| | | .font(.system(size: 13, weight: .semibold)) |
| | | .lineLimit(1) |
| | | } |
| | | .buttonStyle(.bordered) |
| | | .help(tr("quickSearch.openKeyboardSettings")) |
| | | .accessibilityLabel(tr("quickSearch.openKeyboardSettings")) |
| | | } |
| | | Text(tr("quickSearch.hotkeys")) |
| | | .font(.system(size: 13, weight: .semibold)) |
| | | .foregroundStyle(.secondary) |
| | | |
| | | HotkeySettingRow( |
| | | StaticHotkeyInfoRow( |
| | | title: tr("quickSearch.mainHotkey"), |
| | | description: tr("quickSearch.mainHotkeyDesc"), |
| | | kind: .main, |
| | | isRecording: recordingHotkeyKind == .main, |
| | | allowsEditing: false, |
| | | refreshToken: hotkeyRefreshToken, |
| | | onBeginRecording: { }, |
| | | onRestoreDefault: nil, |
| | | onRetry: { }, |
| | | onCancelRecording: cancelHotkeyRecording |
| | | displayText: LauncherHotkey.main.displayString, |
| | | statusText: hotkeyStatusText(for: .main), |
| | | statusTone: hotkeyStatusTone(for: .main) |
| | | ) |
| | | |
| | | StaticHotkeyInfoRow( |
| | | title: tr("quickSearch.internalHotkey"), |
| | | description: tr("quickSearch.internalHotkeyDesc"), |
| | | displayText: tr("quickSearch.spaceDisplay"), |
| | | statusText: tr("quickSearch.internalHotkeyStatus") |
| | | statusText: tr("quickSearch.internalHotkeyStatus"), |
| | | statusTone: .neutral |
| | | ) |
| | | |
| | | HotkeySettingRow( |
| | | StaticHotkeyInfoRow( |
| | | title: tr("quickSearch.globalHotkey"), |
| | | description: tr("quickSearch.globalHotkeyDesc"), |
| | | kind: .quickSearch, |
| | | isRecording: recordingHotkeyKind == .quickSearch, |
| | | allowsEditing: true, |
| | | refreshToken: hotkeyRefreshToken, |
| | | onBeginRecording: { beginHotkeyRecording(.quickSearch) }, |
| | | onRestoreDefault: { applyHotkey(.defaultQuickSearch, for: .quickSearch) }, |
| | | onRetry: { retryHotkey(.quickSearch) }, |
| | | onCancelRecording: cancelHotkeyRecording |
| | | displayText: LauncherHotkey.quickSearch.displayString, |
| | | statusText: hotkeyStatusText(for: .quickSearch), |
| | | statusTone: hotkeyStatusTone(for: .quickSearch) |
| | | ) |
| | | } |
| | | .id(hotkeyRefreshToken) |
| | | } |
| | | |
| | | private func beginHotkeyRecording(_ kind: LauncherHotkeyKind) { |
| | | removeHotkeyCaptureMonitor() |
| | | recordingHotkeyKind = kind |
| | | postHotkeyRecordingState(active: true) |
| | | hotkeyCaptureMonitor = NSEvent.addLocalMonitorForEvents(matching: .keyDown) { event in |
| | | handleCapturedHotkeyEvent(event, for: kind) |
| | | } |
| | | } |
| | | |
| | | private func handleCapturedHotkeyEvent(_ event: NSEvent, for kind: LauncherHotkeyKind) -> NSEvent? { |
| | | if event.keyCode == UInt16(kVK_Escape) { |
| | | cancelHotkeyRecording() |
| | | return nil |
| | | } |
| | | guard let hotkey = LauncherHotkey.from(event: event) else { |
| | | NSSound.beep() |
| | | return nil |
| | | } |
| | | finishHotkeyRecording() |
| | | applyHotkey(hotkey, for: kind) |
| | | return nil |
| | | } |
| | | |
| | | private func cancelHotkeyRecording() { |
| | | finishHotkeyRecording() |
| | | } |
| | | |
| | | private func finishHotkeyRecording() { |
| | | guard recordingHotkeyKind != nil || hotkeyCaptureMonitor != nil else { return } |
| | | recordingHotkeyKind = nil |
| | | removeHotkeyCaptureMonitor() |
| | | postHotkeyRecordingState(active: false) |
| | | } |
| | | |
| | | private func removeHotkeyCaptureMonitor() { |
| | | if let hotkeyCaptureMonitor { |
| | | NSEvent.removeMonitor(hotkeyCaptureMonitor) |
| | | self.hotkeyCaptureMonitor = nil |
| | | } |
| | | } |
| | | |
| | | private func postHotkeyRecordingState(active: Bool) { |
| | | NotificationCenter.default.post( |
| | | name: .tagLauncherModalInteractionChanged, |
| | | object: nil, |
| | | userInfo: [ |
| | | "active": active, |
| | | "source": "hotkeyRecording" |
| | | ] |
| | | ) |
| | | } |
| | | |
| | | var body: some View { |
| | |
| | | .onReceive(NotificationCenter.default.publisher(for: .tagLauncherDataDidChange)) { _ in |
| | | refreshDataState() |
| | | } |
| | | .onReceive(NotificationCenter.default.publisher(for: .tagLauncherHotkeysChanged)) { _ in |
| | | hotkeyRefreshToken &+= 1 |
| | | } |
| | | |
| | | if isRefreshingLanguage { |
| | | ZStack { |
| | |
| | | .zIndex(3) |
| | | .transition(.opacity) |
| | | } |
| | | |
| | | if let hotkeyStatusToast { |
| | | VStack { |
| | | Spacer() |
| | | Text(hotkeyStatusToast) |
| | | .font(.system(size: 13, weight: .semibold)) |
| | | .foregroundStyle(.white) |
| | | .multilineTextAlignment(.center) |
| | | .lineSpacing(2) |
| | | .padding(.horizontal, 18) |
| | | .padding(.vertical, 12) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 8, style: .continuous) |
| | | .fill(Color.black.opacity(0.92)) |
| | | ) |
| | | .shadow(color: .black.opacity(0.28), radius: 18, y: 10) |
| | | .frame(maxWidth: 620) |
| | | .padding(.bottom, 22) |
| | | } |
| | | .zIndex(4) |
| | | .transition(.opacity.combined(with: .move(edge: .bottom))) |
| | | } |
| | | } |
| | | .frame(width: settingsWindowWidth, height: 460) |
| | | .onAppear { |
| | | syncSelectedLanguage() |
| | | showPendingHotkeyWarningIfNeeded() |
| | | } |
| | | .onDisappear { |
| | | finishHotkeyRecording() |
| | | .onReceive(NotificationCenter.default.publisher(for: .tagLauncherHotkeyRegistrationChanged)) { _ in |
| | | showPendingHotkeyWarningIfNeeded() |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | private enum HotkeyStatusTone { |
| | | case active |
| | | case warning |
| | | case neutral |
| | | |
| | | var foreground: Color { |
| | | switch self { |
| | | case .active: return Color.green |
| | | case .warning: return Color.orange |
| | | case .neutral: return Color.secondary |
| | | } |
| | | } |
| | | |
| | | var background: Color { |
| | | foreground.opacity(0.13) |
| | | } |
| | | } |
| | | |
| | | private struct StaticHotkeyInfoRow: View { |
| | | let title: String |
| | | let description: String |
| | | let displayText: String |
| | | let statusText: String |
| | | let statusTone: HotkeyStatusTone |
| | | |
| | | var body: some View { |
| | | VStack(alignment: .leading, spacing: 12) { |
| | |
| | | .minimumScaleFactor(0.85) |
| | | Text(statusText) |
| | | .font(.system(size: 11, weight: .semibold)) |
| | | .foregroundStyle(Color.secondary) |
| | | .foregroundStyle(statusTone.foreground) |
| | | .padding(.horizontal, 8) |
| | | .padding(.vertical, 3) |
| | | .background(Capsule().fill(Color.secondary.opacity(0.13))) |
| | | .background(Capsule().fill(statusTone.background)) |
| | | } |
| | | .frame(width: 180, alignment: .leading) |
| | | } |
| | |
| | | RoundedRectangle(cornerRadius: 8, style: .continuous) |
| | | .stroke(Color.secondary.opacity(0.14), lineWidth: 1) |
| | | ) |
| | | } |
| | | } |
| | | |
| | | private struct HotkeySettingRow: View { |
| | | let title: String |
| | | let description: String |
| | | let kind: LauncherHotkeyKind |
| | | let isRecording: Bool |
| | | let allowsEditing: Bool |
| | | let refreshToken: Int |
| | | let onBeginRecording: () -> Void |
| | | let onRestoreDefault: (() -> Void)? |
| | | let onRetry: () -> Void |
| | | let onCancelRecording: () -> Void |
| | | |
| | | private var activeHotkey: LauncherHotkey? { |
| | | _ = refreshToken |
| | | return LauncherHotkeyStore.hotkey(for: kind) |
| | | } |
| | | |
| | | private var pendingHotkey: LauncherHotkey? { |
| | | _ = refreshToken |
| | | return LauncherHotkeyStore.pendingHotkey(for: kind) |
| | | } |
| | | |
| | | private var status: LauncherHotkeyStatus { |
| | | _ = refreshToken |
| | | return LauncherHotkeyStore.status(for: kind) |
| | | } |
| | | |
| | | private var conflictMessage: String { |
| | | _ = refreshToken |
| | | return LauncherHotkeyStore.conflictMessage(for: kind) |
| | | } |
| | | |
| | | 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) |
| | | statusLabel |
| | | } |
| | | .frame(width: 180, alignment: .leading) |
| | | } |
| | | |
| | | if allowsEditing { |
| | | HStack(spacing: 8) { |
| | | hotkeyButton( |
| | | isRecording ? tr("quickSearch.recording") : tr("quickSearch.record"), |
| | | systemImage: isRecording ? "keyboard.badge.ellipsis" : "keyboard", |
| | | prominent: true, |
| | | action: onBeginRecording |
| | | ) |
| | | if let onRestoreDefault { |
| | | hotkeyButton( |
| | | tr("quickSearch.restoreDefault"), |
| | | systemImage: "arrow.counterclockwise", |
| | | prominent: false, |
| | | action: onRestoreDefault |
| | | ) |
| | | } |
| | | if status == .conflict { |
| | | hotkeyButton( |
| | | tr("quickSearch.retry"), |
| | | systemImage: "arrow.clockwise", |
| | | prominent: false, |
| | | action: onRetry |
| | | ) |
| | | } |
| | | Spacer(minLength: 0) |
| | | } |
| | | } |
| | | |
| | | if allowsEditing && isRecording { |
| | | HStack(spacing: 8) { |
| | | Image(systemName: "keyboard") |
| | | Text(tr("quickSearch.recordingHint")) |
| | | Spacer(minLength: 0) |
| | | Button(tr("settings.cancel"), action: onCancelRecording) |
| | | .buttonStyle(.borderless) |
| | | } |
| | | .font(.system(size: 13, weight: .semibold)) |
| | | .foregroundStyle(Color.accentColor) |
| | | .padding(.horizontal, 10) |
| | | .padding(.vertical, 10) |
| | | .background(RoundedRectangle(cornerRadius: 7).fill(Color.accentColor.opacity(0.10))) |
| | | } |
| | | |
| | | if status == .conflict && !conflictMessage.isEmpty { |
| | | HotkeyConflictNotice(text: conflictDetailText) |
| | | } |
| | | } |
| | | .padding(12) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 8, style: .continuous) |
| | | .fill(Color(nsColor: .controlBackgroundColor)) |
| | | ) |
| | | .overlay( |
| | | RoundedRectangle(cornerRadius: 8, style: .continuous) |
| | | .stroke(Color.secondary.opacity(0.14), lineWidth: 1) |
| | | ) |
| | | } |
| | | |
| | | private var displayText: String { |
| | | if status == .conflict, let pendingHotkey { |
| | | return "\(pendingHotkey.displayString) · \(tr("quickSearch.blocked"))" |
| | | } |
| | | return activeHotkey?.displayString ?? tr("quickSearch.disabled") |
| | | } |
| | | |
| | | private var conflictDetailText: String { |
| | | if let activeHotkey { |
| | | return "\(conflictMessage) \(tr("quickSearch.previousStillActive")) \(activeHotkey.displayString)" |
| | | } |
| | | return conflictMessage |
| | | } |
| | | |
| | | private var statusLabel: some View { |
| | | Text(tr("quickSearch.status.\(status.rawValue)")) |
| | | .font(.system(size: 11, weight: .semibold)) |
| | | .foregroundStyle(statusColor) |
| | | .padding(.horizontal, 8) |
| | | .padding(.vertical, 3) |
| | | .background(Capsule().fill(statusColor.opacity(0.13))) |
| | | } |
| | | |
| | | private var statusColor: Color { |
| | | switch status { |
| | | case .active: return .green |
| | | case .conflict: return .orange |
| | | case .disabled: return .secondary |
| | | } |
| | | } |
| | | |
| | | private func hotkeyButton( |
| | | _ title: String, |
| | | systemImage: String, |
| | | prominent: Bool, |
| | | action: @escaping () -> Void |
| | | ) -> some View { |
| | | Button(action: action) { |
| | | Label(title, systemImage: systemImage) |
| | | .font(.system(size: 13, weight: .semibold)) |
| | | .lineLimit(1) |
| | | .minimumScaleFactor(0.88) |
| | | .foregroundStyle(prominent ? Color.white : Color.primary) |
| | | .padding(.horizontal, 10) |
| | | .frame(height: 30) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 7, style: .continuous) |
| | | .fill(prominent ? Color.accentColor : Color(nsColor: .controlBackgroundColor)) |
| | | ) |
| | | .overlay( |
| | | RoundedRectangle(cornerRadius: 7, style: .continuous) |
| | | .stroke(prominent ? Color.accentColor.opacity(0.24) : Color.secondary.opacity(0.22), lineWidth: 1) |
| | | ) |
| | | } |
| | | .buttonStyle(.plain) |
| | | .help(title) |
| | | .accessibilityLabel(title) |
| | | } |
| | | } |
| | | |
| | | private struct HotkeyConflictNotice: View { |
| | | let text: String |
| | | |
| | | var body: some View { |
| | | HStack(alignment: .top, spacing: 8) { |
| | | Image(systemName: "exclamationmark.triangle.fill") |
| | | .font(.system(size: 13, weight: .semibold)) |
| | | .foregroundStyle(Color.white.opacity(0.94)) |
| | | .padding(.top, 1) |
| | | Text(text) |
| | | .font(.system(size: 12, weight: .medium)) |
| | | .foregroundStyle(Color.white) |
| | | .fixedSize(horizontal: false, vertical: true) |
| | | Spacer(minLength: 0) |
| | | } |
| | | .padding(.horizontal, 10) |
| | | .padding(.vertical, 9) |
| | | .background( |
| | | RoundedRectangle(cornerRadius: 8, style: .continuous) |
| | | .fill(Color.black.opacity(0.92)) |
| | | ) |
| | | .shadow(color: .black.opacity(0.24), radius: 16, y: 8) |
| | | } |
| | | } |
| | | |
| | |
| | | static let tagLauncherQuickSearchRequested = Notification.Name("TagLauncherQuickSearchRequested") |
| | | static let tagLauncherQuickSearchDismissRequested = Notification.Name("TagLauncherQuickSearchDismissRequested") |
| | | static let tagLauncherQuickSearchVisibilityChanged = Notification.Name("TagLauncherQuickSearchVisibilityChanged") |
| | | static let tagLauncherHotkeysChanged = Notification.Name("TagLauncherHotkeysChanged") |
| | | static let tagLauncherHotkeyRegistrationChanged = Notification.Name("TagLauncherHotkeyRegistrationChanged") |
| | | } |
| | | |
| | | enum QuickSearchOpenSource { |
| | |
| | | struct LauncherHotkey: Equatable { |
| | | let keyCode: UInt32 |
| | | let modifiers: UInt32 |
| | | |
| | | var serialized: String { |
| | | "\(keyCode):\(modifiers)" |
| | | } |
| | | |
| | | var displayString: String { |
| | | let ordered: [(UInt32, String)] = [ |
| | |
| | | return modifierGlyphs + LauncherHotkey.keyDisplayName(for: keyCode) |
| | | } |
| | | |
| | | static var defaultMain: LauncherHotkey { |
| | | static var main: LauncherHotkey { |
| | | LauncherHotkey(keyCode: UInt32(kVK_Space), modifiers: UInt32(shiftKey | optionKey)) |
| | | } |
| | | |
| | | static var defaultQuickSearch: LauncherHotkey { |
| | | static var quickSearch: LauncherHotkey { |
| | | LauncherHotkey(keyCode: UInt32(kVK_Space), modifiers: UInt32(kEventKeyModifierFnMask)) |
| | | } |
| | | |
| | | static func deserialize(_ value: String?) -> LauncherHotkey? { |
| | | guard let value, !value.isEmpty else { return nil } |
| | | let parts = value.split(separator: ":") |
| | | guard parts.count == 2, |
| | | let keyCode = UInt32(parts[0]), |
| | | let modifiers = UInt32(parts[1]) |
| | | else { return nil } |
| | | return LauncherHotkey(keyCode: keyCode, modifiers: modifiers) |
| | | } |
| | | |
| | | static func from(event: NSEvent) -> LauncherHotkey? { |
| | | let ignoredKeyCodes: Set<UInt16> = [54, 55, 56, 57, 58, 59, 60, 61, 62, 63] |
| | | guard !ignoredKeyCodes.contains(event.keyCode) else { return nil } |
| | | |
| | | var carbonModifiers: UInt32 = 0 |
| | | if event.modifierFlags.contains(.shift) { carbonModifiers |= UInt32(shiftKey) } |
| | | if event.modifierFlags.contains(.option) { carbonModifiers |= UInt32(optionKey) } |
| | | if event.modifierFlags.contains(.control) { carbonModifiers |= UInt32(controlKey) } |
| | | if event.modifierFlags.contains(.command) { carbonModifiers |= UInt32(cmdKey) } |
| | | if event.modifierFlags.contains(.function) { carbonModifiers |= UInt32(kEventKeyModifierFnMask) } |
| | | guard carbonModifiers != 0 else { return nil } |
| | | |
| | | return LauncherHotkey(keyCode: UInt32(event.keyCode), modifiers: carbonModifiers) |
| | | } |
| | | |
| | | static func keyDisplayName(for keyCode: UInt32) -> String { |
| | |
| | | case main |
| | | case quickSearch |
| | | |
| | | var storageKey: String { |
| | | var stateKey: String { |
| | | switch self { |
| | | case .main: return "mainHotkey" |
| | | case .quickSearch: return "quickSearchHotkey" |
| | | case .main: return LauncherHotkeyRegistrationStore.mainStateKey |
| | | case .quickSearch: return LauncherHotkeyRegistrationStore.quickSearchStateKey |
| | | } |
| | | } |
| | | |
| | | var statusKey: String { |
| | | var failureCodeKey: String { |
| | | switch self { |
| | | case .main: return "mainHotkeyStatus" |
| | | case .quickSearch: return "quickSearchHotkeyStatus" |
| | | case .main: return LauncherHotkeyRegistrationStore.mainFailureCodeKey |
| | | case .quickSearch: return LauncherHotkeyRegistrationStore.quickSearchFailureCodeKey |
| | | } |
| | | } |
| | | |
| | | var conflictMessageKey: String { |
| | | var attentionKey: String { |
| | | switch self { |
| | | case .main: return "mainHotkeyConflictMessage" |
| | | case .quickSearch: return "quickSearchHotkeyConflictMessage" |
| | | case .main: return LauncherHotkeyRegistrationStore.mainNeedsAttentionKey |
| | | case .quickSearch: return LauncherHotkeyRegistrationStore.quickSearchNeedsAttentionKey |
| | | } |
| | | } |
| | | |
| | | var pendingStorageKey: String { |
| | | var hotkey: LauncherHotkey { |
| | | switch self { |
| | | case .main: return "mainHotkeyPending" |
| | | case .quickSearch: return "quickSearchHotkeyPending" |
| | | case .main: return .main |
| | | case .quickSearch: return .quickSearch |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | enum LauncherHotkeyStatus: String { |
| | | case active = "Active" |
| | | case conflict = "Conflict" |
| | | case disabled = "Disabled" |
| | | enum LauncherHotkeyRegistrationState: String { |
| | | case active |
| | | case failed |
| | | } |
| | | |
| | | enum LauncherHotkeyStore { |
| | | static func hotkey(for kind: LauncherHotkeyKind) -> LauncherHotkey? { |
| | | if kind == .main { |
| | | return .defaultMain |
| | | } |
| | | if kind == .quickSearch && !AppDefaults.hasStoredValue(for: kind.storageKey) { |
| | | return .defaultQuickSearch |
| | | } |
| | | return LauncherHotkey.deserialize(UserDefaults.standard.string(forKey: kind.storageKey)) |
| | | enum LauncherHotkeyRegistrationStore { |
| | | static let mainStateKey = "mainHotkeyRegistrationState" |
| | | static let quickSearchStateKey = "quickSearchHotkeyRegistrationState" |
| | | static let mainFailureCodeKey = "mainHotkeyRegistrationFailureCode" |
| | | static let quickSearchFailureCodeKey = "quickSearchHotkeyRegistrationFailureCode" |
| | | static let mainNeedsAttentionKey = "mainHotkeyRegistrationNeedsAttention" |
| | | static let quickSearchNeedsAttentionKey = "quickSearchHotkeyRegistrationNeedsAttention" |
| | | |
| | | static func state(for kind: LauncherHotkeyKind) -> LauncherHotkeyRegistrationState { |
| | | let rawValue = UserDefaults.standard.string(forKey: kind.stateKey) |
| | | return LauncherHotkeyRegistrationState(rawValue: rawValue ?? "") ?? .active |
| | | } |
| | | |
| | | static func save(_ hotkey: LauncherHotkey?, for kind: LauncherHotkeyKind) { |
| | | UserDefaults.standard.set(hotkey?.serialized ?? "", forKey: kind.storageKey) |
| | | UserDefaults.standard.removeObject(forKey: kind.pendingStorageKey) |
| | | static func failureCode(for kind: LauncherHotkeyKind) -> Int? { |
| | | let defaults = UserDefaults.standard |
| | | guard defaults.object(forKey: kind.failureCodeKey) != nil else { return nil } |
| | | return defaults.integer(forKey: kind.failureCodeKey) |
| | | } |
| | | |
| | | static func savePending(_ hotkey: LauncherHotkey, for kind: LauncherHotkeyKind) { |
| | | UserDefaults.standard.set(hotkey.serialized, forKey: kind.pendingStorageKey) |
| | | static func setActive(for kind: LauncherHotkeyKind) { |
| | | setState(.active, failureCode: nil, for: kind) |
| | | } |
| | | |
| | | static func pendingHotkey(for kind: LauncherHotkeyKind) -> LauncherHotkey? { |
| | | LauncherHotkey.deserialize(UserDefaults.standard.string(forKey: kind.pendingStorageKey)) |
| | | static func setFailed(_ failureCode: OSStatus, for kind: LauncherHotkeyKind) { |
| | | setState(.failed, failureCode: Int(failureCode), for: kind) |
| | | } |
| | | |
| | | static func status(for kind: LauncherHotkeyKind) -> LauncherHotkeyStatus { |
| | | let raw = UserDefaults.standard.string(forKey: kind.statusKey) |
| | | return LauncherHotkeyStatus(rawValue: raw ?? "") ?? (hotkey(for: kind) == nil ? .disabled : .active) |
| | | static func consumeNeedsAttention(for kind: LauncherHotkeyKind) -> Bool { |
| | | let defaults = UserDefaults.standard |
| | | let needsAttention = defaults.bool(forKey: kind.attentionKey) |
| | | defaults.set(false, forKey: kind.attentionKey) |
| | | return needsAttention |
| | | } |
| | | |
| | | static func setStatus(_ status: LauncherHotkeyStatus, message: String?, for kind: LauncherHotkeyKind) { |
| | | UserDefaults.standard.set(status.rawValue, forKey: kind.statusKey) |
| | | if let message, !message.isEmpty { |
| | | UserDefaults.standard.set(message, forKey: kind.conflictMessageKey) |
| | | private static func setState( |
| | | _ state: LauncherHotkeyRegistrationState, |
| | | failureCode: Int?, |
| | | for kind: LauncherHotkeyKind |
| | | ) { |
| | | let defaults = UserDefaults.standard |
| | | let previousState = defaults.string(forKey: kind.stateKey) |
| | | let previousFailureCode = defaults.object(forKey: kind.failureCodeKey) == nil |
| | | ? nil |
| | | : defaults.integer(forKey: kind.failureCodeKey) |
| | | let stateChanged = previousState != state.rawValue || previousFailureCode != failureCode |
| | | |
| | | defaults.set(state.rawValue, forKey: kind.stateKey) |
| | | if let failureCode { |
| | | defaults.set(failureCode, forKey: kind.failureCodeKey) |
| | | } else { |
| | | UserDefaults.standard.removeObject(forKey: kind.conflictMessageKey) |
| | | defaults.removeObject(forKey: kind.failureCodeKey) |
| | | } |
| | | NotificationCenter.default.post(name: .tagLauncherHotkeysChanged, object: nil) |
| | | } |
| | | |
| | | static func conflictMessage(for kind: LauncherHotkeyKind) -> String { |
| | | UserDefaults.standard.string(forKey: kind.conflictMessageKey) ?? "" |
| | | } |
| | | |
| | | static func knownConflictMessage(for hotkey: LauncherHotkey, status: OSStatus) -> String? { |
| | | guard status != noErr else { return nil } |
| | | switch (hotkey.keyCode, hotkey.modifiers) { |
| | | case (UInt32(kVK_Space), UInt32(cmdKey)): |
| | | return tr("quickSearch.hotkeyConflict.spotlight") |
| | | case (UInt32(kVK_Space), UInt32(optionKey | cmdKey)): |
| | | return tr("quickSearch.hotkeyConflict.finderSearch") |
| | | case (UInt32(kVK_Space), UInt32(controlKey)): |
| | | return tr("quickSearch.hotkeyConflict.previousInput") |
| | | case (UInt32(kVK_Space), UInt32(controlKey | optionKey)): |
| | | return tr("quickSearch.hotkeyConflict.nextInput") |
| | | case (UInt32(kVK_Space), UInt32(controlKey | cmdKey)): |
| | | return tr("quickSearch.hotkeyConflict.emoji") |
| | | case (UInt32(kVK_Space), UInt32(kEventKeyModifierFnMask)): |
| | | return tr("quickSearch.hotkeyConflict.fnSpace") |
| | | default: |
| | | return nil |
| | | if state == .active { |
| | | defaults.set(false, forKey: kind.attentionKey) |
| | | } else if stateChanged { |
| | | defaults.set(true, forKey: kind.attentionKey) |
| | | } |
| | | |
| | | NotificationCenter.default.post( |
| | | name: .tagLauncherHotkeyRegistrationChanged, |
| | | object: nil, |
| | | userInfo: ["kind": kind.rawValue] |
| | | ) |
| | | } |
| | | } |
| | | |
| | |
| | | candidates.append((.acronym, 0)) |
| | | } |
| | | for pinyin in field.pinyinCandidates { |
| | | if let pinyinCandidate = matchPinyinCandidate(token: token, normalized: pinyin) { |
| | | if let pinyinCandidate = matchPinyinCandidate( |
| | | token: token, |
| | | normalized: pinyin, |
| | | allowSubstring: field.kind == .note |
| | | ) { |
| | | candidates.append(pinyinCandidate) |
| | | } |
| | | } |
| | |
| | | case .tag: |
| | | return MatchOptions(allowSubstring: true, allowFuzzySubsequence: true) |
| | | case .note: |
| | | return MatchOptions(allowSubstring: true, allowFuzzySubsequence: false) |
| | | return MatchOptions(allowSubstring: true, allowFuzzySubsequence: true) |
| | | case .bundleIdentifier, .internalBundleName: |
| | | return MatchOptions(allowSubstring: false, allowFuzzySubsequence: false) |
| | | } |
| | |
| | | return nil |
| | | } |
| | | |
| | | private static func matchPinyinCandidate(token: String, normalized: String) -> (MatchKind, Int)? { |
| | | private static func matchPinyinCandidate( |
| | | token: String, |
| | | normalized: String, |
| | | allowSubstring: Bool = false |
| | | ) -> (MatchKind, Int)? { |
| | | guard !normalized.isEmpty else { return nil } |
| | | if normalized == token { |
| | | return (.exact, 0) |
| | | } |
| | | if normalized.hasPrefix(token) { |
| | | return (.prefix, 0) |
| | | } |
| | | if allowSubstring, let range = normalized.range(of: token) { |
| | | return (.substring, normalized.distance(from: normalized.startIndex, to: range.lowerBound)) |
| | | } |
| | | return nil |
| | | } |
| | |
| | | onCommand?(.dismiss) |
| | | default: |
| | | super.keyDown(with: event) |
| | | } |
| | | } |
| | | } |
| | | |
| | | struct QuickSearchBackdropClickView: NSViewRepresentable { |
| | | let onClick: () -> Void |
| | | |
| | | func makeNSView(context: Context) -> QuickSearchBackdropNSView { |
| | | let view = QuickSearchBackdropNSView() |
| | | view.onClick = onClick |
| | | return view |
| | | } |
| | | |
| | | func updateNSView(_ view: QuickSearchBackdropNSView, context: Context) { |
| | | view.onClick = onClick |
| | | } |
| | | } |
| | | |
| | | final class QuickSearchBackdropNSView: NSView { |
| | | var onClick: (() -> Void)? |
| | | |
| | | override func hitTest(_ point: NSPoint) -> NSView? { |
| | | bounds.contains(point) ? self : nil |
| | | } |
| | | |
| | | override func mouseDown(with event: NSEvent) { |
| | | onClick?() |
| | | } |
| | | } |
| | | |
| | | // MARK: - Hotkey Capture UI |
| | | |
| | | struct HotkeyCaptureView: NSViewRepresentable { |
| | | let isActive: Bool |
| | | let onCapture: (LauncherHotkey) -> Void |
| | | let onCancel: () -> Void |
| | | |
| | | func makeNSView(context: Context) -> HotkeyCaptureNSView { |
| | | let view = HotkeyCaptureNSView() |
| | | view.onCapture = onCapture |
| | | view.onCancel = onCancel |
| | | return view |
| | | } |
| | | |
| | | func updateNSView(_ view: HotkeyCaptureNSView, context: Context) { |
| | | view.onCapture = onCapture |
| | | view.onCancel = onCancel |
| | | view.setActive(isActive) |
| | | } |
| | | } |
| | | |
| | | final class HotkeyCaptureNSView: NSView { |
| | | var onCapture: ((LauncherHotkey) -> Void)? |
| | | var onCancel: (() -> Void)? |
| | | private var keyMonitor: Any? |
| | | |
| | | override var acceptsFirstResponder: Bool { true } |
| | | |
| | | deinit { |
| | | removeKeyMonitor() |
| | | } |
| | | |
| | | func setActive(_ active: Bool) { |
| | | if active { |
| | | installKeyMonitorIfNeeded() |
| | | DispatchQueue.main.async { [weak self] in |
| | | guard let self else { return } |
| | | self.window?.makeFirstResponder(self) |
| | | } |
| | | } else { |
| | | removeKeyMonitor() |
| | | } |
| | | } |
| | | |
| | | override func keyDown(with event: NSEvent) { |
| | | handle(event) |
| | | } |
| | | |
| | | private func installKeyMonitorIfNeeded() { |
| | | guard keyMonitor == nil else { return } |
| | | keyMonitor = NSEvent.addLocalMonitorForEvents(matching: .keyDown) { [weak self] event in |
| | | guard let self else { return event } |
| | | self.handle(event) |
| | | return nil |
| | | } |
| | | } |
| | | |
| | | private func removeKeyMonitor() { |
| | | if let keyMonitor { |
| | | NSEvent.removeMonitor(keyMonitor) |
| | | self.keyMonitor = nil |
| | | } |
| | | } |
| | | |
| | | private func handle(_ event: NSEvent) { |
| | | if event.keyCode == UInt16(kVK_Escape) { |
| | | onCancel?() |
| | | return |
| | | } |
| | | if let hotkey = LauncherHotkey.from(event: event) { |
| | | onCapture?(hotkey) |
| | | } else { |
| | | NSSound.beep() |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | - 设置页新增独立「快捷键」页签,将主界面快捷键与 Quick Search 直接快捷键管理从「通用」页拆出 |
| | | - 移除设置页中与当前快捷键设置重复的静态按键帽提示,避免「关于」等页面继续展示旧快捷键视觉元素 |
| | | - 按 C 版规则收窄「快捷搜索」匹配:短查询不再放大无关结果,备注恢复拼音前缀匹配,Tag 支持原文非连续字符匹配,Bundle ID 与内部 Bundle 名仅支持精确/前缀命中 |
| | | - 版本号更新为 `7.5.1`,Build 更新为 `751` |
| | | - 按 C 版规则收窄「快捷搜索」匹配:短查询不再放大无关结果,备注支持中文词拼音连续片段命中,Tag 支持原文非连续字符匹配,Bundle ID 与内部 Bundle 名仅支持精确/前缀命中 |
| | | - 移除快捷键自定义能力,快捷键页面只展示固定快捷键信息;构建号格式改为 `yyyyMMdd.HHmm` 并在打包时自动刷新 |
| | | - 修复全局快捷搜索失焦不关闭的问题:点击搜索框外部、点击其他 App 或 App 失去焦点时,会像 Spotlight 一样自动收起 |
| | | - 清理 Smart Start 默认目录备注中的开头标点,移除高置信别名重复项,并禁止用 App 名称加分类标签拼凑伪备注 |
| | | - 重新打包最新 Smart Start 终极默认分类目录,确保 App bundle 内置资源同步到最新 CSV/JSON |
| | | - 快捷键页面和菜单改为显示真实快捷键注册状态;固定快捷键注册失败时显示「快捷键不可用」,并只在状态变化后打开设置页时给出黑底白字提示 |
| | | - 修复构建流程:Build 号只写入 App bundle 内的 `Info.plist`,打包脚本会验证源码 `Apptag/Info.plist` 未被构建过程改动 |
| | | - 版本号更新为 `7.5.1`,Build 更新为 `20260520.1228` |
| | | |
| | | ## [7.5.0] — 2026-05-19 |
| | | |
| | |
| | | - Quick Search 使用 macOS Spotlight 风格玻璃面板,支持外部点击关闭、Esc 两级退出、结果滚动和稳定顶部定位 |
| | | - 启动历史增加最近成功启动时间,用于 Quick Search 空查询建议排序;启动失败不更新历史 |
| | | - 所有 Quick Search 用户可见文案接入本地化资源 |
| | | - 版本号更新为 `7.5.0`,Build 更新为 `750` |
| | | - 版本号更新为 `7.5.0`,Build 更新为 `20260519.0750` |
| | | |
| | | ## [7.3.5] — 2026-05-18 |
| | | |
| | |
| | | - 修复快速滑过 App 图标时旧用途气泡可能冻结在上一 App 上的问题,让新 hover 目标主动接管气泡状态 |
| | | - Smart Start 初始化目录切换为使用最新整理的 `tager` 字段生成运行时 JSON,覆盖 `5231` 个 App,并将 `4431` 条中文默认备注扩展为 29 种语言运行时备注 |
| | | - 统一 Smart Start 默认系统标签颜色分组,让网络/文件流、工作知识、开发 AI、内容媒体、系统能力等语义更接近的标签使用更一致的默认颜色 |
| | | - 版本号更新为 `7.3.5`,Build 更新为 `744` |
| | | - 版本号更新为 `7.3.5`,Build 更新为 `20260518.0744` |
| | | |
| | | ## [7.3.4] — 2026-05-18 |
| | | |
| | | - 优化应用列表打开速度:覆盖层窗口不再每次显示都销毁重建,减少重复初始化 |
| | | - App 扫描增加会话缓存,避免短时间内反复加载全部应用图标导致每次打开都长时间等待 |
| | | - 避免应用激活通知和首次显示同时触发重复全量刷新;刷新进行中时只保留必要的强制刷新请求 |
| | | - 版本号更新为 `7.3.4`,Build 更新为 `743` |
| | | - 版本号更新为 `7.3.4`,Build 更新为 `20260518.0743` |
| | | |
| | | ## [7.3.3] — 2026-05-18 |
| | | |
| | | - 拖拽 App 时会立即关闭并禁用 App 用途气泡,避免拖向目标容器时旧气泡继续遮挡视线 |
| | | - 「归类为未分类」确认浮层出现前会清理 App 气泡,确认决策期间不再显示背景 App 的说明气泡 |
| | | - 版本号更新为 `7.3.3`,Build 更新为 `742` |
| | | - 版本号更新为 `7.3.3`,Build 更新为 `20260518.0742` |
| | | |
| | | ## [7.3.2] — 2026-05-18 |
| | | |
| | | - 优化设置页「标签」界面布局,将标签列表内容区整体居中,避免左侧拥挤、右侧大面积留白 |
| | | - 标签名称区域改为自适应占用剩余空间,长标签名使用中间截断并保留悬停提示,兼顾不同语言长度 |
| | | - 版本号更新为 `7.3.2`,Build 更新为 `741` |
| | | - 版本号更新为 `7.3.2`,Build 更新为 `20260518.0741` |
| | | |
| | | ## [7.3.1] — 2026-05-18 |
| | | |
| | | - 将拖动 App 到「未分类」时的确认提示从系统弹窗改为应用列表内部浮层,视觉样式与现有确认反馈保持一致 |
| | | - 未分类确认浮层现在只覆盖 TagLauncher 应用列表窗口,提供「取消 / 确认」两个明确操作,并支持右上角关闭与 Esc 取消 |
| | | - 版本号更新为 `7.3.1`,Build 更新为 `740` |
| | | - 版本号更新为 `7.3.1`,Build 更新为 `20260518.0740` |
| | | |
| | | ## [7.3.0] — 2026-05-18 |
| | | |
| | |
| | | - 气泡提示设置改为「全部应用 / 仅不常用应用」二选一,并补齐多语言文案 |
| | | - 统一 App 图标 hover 焦点状态,降低快速滑过、视图复用或同一 App 出现在多个分组时出现小名字残影的概率 |
| | | - 当气泡提示范围选择「全部应用」时,hover 不再额外显示 App 图标下方的小名字,避免和大气泡重复 |
| | | - 版本号更新为 `7.3.0`,Build 更新为 `739` |
| | | - 版本号更新为 `7.3.0`,Build 更新为 `20260518.0739` |
| | | |
| | | ## [7.2.0] — 2026-05-18 |
| | | |
| | |
| | | - App 气泡提示改为稳定淡入,不再使用缩放弹跳动画 |
| | | - App 气泡定位改为使用 overlay 内部同一坐标系,修复纵向滑动时气泡和光标/App 距离越来越远的问题 |
| | | - App 气泡增加 macOS popover 风格尖角,明确指向触发它的 App |
| | | - 版本号更新为 `7.2.0`,Build 更新为 `738` |
| | | - 版本号更新为 `7.2.0`,Build 更新为 `20260518.0738` |
| | | |
| | | ## [7.1.0] — 2026-05-18 |
| | | |
| | |
| | | - App 图标切换为最终确认的轻量版 `icns`,打包时直接使用 `Research/logo/TagLauncherIcon_v2_light.icns` |
| | | - 菜单栏图标改为加载最终确认的 `SVG` 矢量资源,保留模板图标特性以适配系统明暗菜单栏 |
| | | - 放大菜单栏图标的矢量主体并将显示尺寸调整为 `19pt`,改善菜单栏中图标过小、不清晰的问题 |
| | | - 修正 build 731 引入的 hover 手感问题:App 图标 hover 放大改为极短交互动画,避免鼠标划过时出现慢动作拖尾 |
| | | - 修正 build 20260518.0731 引入的 hover 手感问题:App 图标 hover 放大改为极短交互动画,避免鼠标划过时出现慢动作拖尾 |
| | | - 修正容器 hover 凸起像慢镜头的问题:容器 lift 从 `0.25s` spring 改为极短 `easeOut`,保留反馈但去掉拖尾 |
| | | - 新增分类方案自动快照:用户主动改变标签归属、标签顺序、标签颜色、标签创建/删除/重命名时,会自动保存变动前方案到本地备份 |
| | | - 自动快照采用批次合并策略:同一轮连续编辑只生成一个“上一个分类方案”,当前分类方案时间戳随最新变动更新 |
| | | - 自动方案备份保留 30 天,旧记录会在后续变动、打开设置、导出或退出 App 时自动清理 |
| | | - 新安装 App 被扫描到但用户没有编辑时,不触发分类方案自动快照 |
| | | - 打包脚本在签名前清理 App bundle 扩展属性,避免资源文件元数据导致本地签名失败 |
| | | - 版本号更新为 `7.1.0`,Build 更新为 `737` |
| | | - 版本号更新为 `7.1.0`,Build 更新为 `20260518.0737` |
| | | |
| | | ## [7.0.19] — 2026-05-17 |
| | | |
| | | - 为 Apple 自带/Apple 官方 App 增加系统默认用途备注,每个 App 获得一句精简说明,作为首次使用时的小惊喜 |
| | | - 默认备注只写入现有 App 备注字段,不另建用户数据存储;用户右键编辑后会继续走同一套备注逻辑 |
| | | - 将 Safari、Mail、照片等高熟悉度 Apple App 排除在默认“不常用”之外,其余 Apple 自带/官方 App 默认标记为“不常用” |
| | | - 版本号更新为 `7.0.19`,Build 更新为 `719` |
| | | - 版本号更新为 `7.0.19`,Build 更新为 `20260517.0719` |
| | | |
| | | ## [7.0.18] — 2026-05-17 |
| | | |
| | | - 导出文件名与设置页中的方案名称改为按当前界面语言实时重算前缀,不再沿用旧语言下保存的英文前缀 |
| | | - 补全日语下的方案相关文案与按钮文本,日语界面导出时会显示日文文件名前缀 |
| | | - 版本号更新为 `7.0.18`,Build 更新为 `718` |
| | | - 版本号更新为 `7.0.18`,Build 更新为 `20260517.0718` |
| | | |
| | | ## [7.0.17] — 2026-05-17 |
| | | |
| | | - 设置页「数据」里的 `Apply` / `Restore` 按钮改为自绘的稳定样式,不再依赖系统 `borderedProminent` 渲染 |
| | | - 按钮在禁用、重绘或语言切换时仍会稳定显示文字,避免出现只剩空白按钮壳的情况 |
| | | - 版本号更新为 `7.0.17`,Build 更新为 `717` |
| | | - 版本号更新为 `7.0.17`,Build 更新为 `20260517.0717` |
| | | |
| | | ## [7.0.16] — 2026-05-17 |
| | | |
| | | - 新安装用户首次启动时,“不常用 App 气泡提示”默认改为不勾选 |
| | | - 已有用户的已保存设置保持不变,不会被这次默认值调整覆盖 |
| | | - 版本号更新为 `7.0.16`,Build 更新为 `716` |
| | | - 版本号更新为 `7.0.16`,Build 更新为 `20260517.0716` |
| | | |
| | | ## [7.0.15] — 2026-05-17 |
| | | |
| | | - 修复设置页语言列表选中状态可能停留在 English 的问题:设置窗口显示时会强制同步当前实际语言 |
| | | - 语言变化通知缺少 code 时也会回读当前语言,避免 UI 文案与语言选择状态不一致 |
| | | - 版本号更新为 `7.0.15`,Build 更新为 `715` |
| | | - 版本号更新为 `7.0.15`,Build 更新为 `20260517.0715` |
| | | |
| | | ## [7.0.14] — 2026-05-17 |
| | | |
| | | - 导入分类与布局 JSON 时补充方案时间容错:优先读取文件名中的规范时间 `yyyy.MMdd.HHmm` |
| | | - 如果导入文件名不含规范时间,则使用该 JSON 文件属性中的创建时间作为方案时间;创建时间不可用时回退到修改时间 |
| | | - 导入后的当前方案名称统一规范为带时间戳的本地分类方案,避免用户自定义文件名导致方案名称缺少时间信息 |
| | | - 版本号更新为 `7.0.14`,Build 更新为 `714` |
| | | - 版本号更新为 `7.0.14`,Build 更新为 `20260517.0714` |
| | | |
| | | ## [7.0.13] — 2026-05-17 |
| | | |
| | | - 设置页「数据」的分类方案面板改为固定右侧操作列,避免“应用”按钮在长方案名或布局刷新时被挤出/裁掉 |
| | | - “应用”和“恢复”按钮保持同列对齐,方案名称优先截断,操作按钮优先保留 |
| | | - 版本号更新为 `7.0.13`,Build 更新为 `713` |
| | | - 版本号更新为 `7.0.13`,Build 更新为 `20260517.0713` |
| | | |
| | | ## [7.0.12] — 2026-05-17 |
| | | |
| | | - 右键菜单中的“编辑用途备忘”对所有 App 开放,不再要求 App 已经属于“不常用” |
| | | - 用户保存非空用途备忘时,系统会自动把该 App 标记为“不常用”,无需用户再手动归类 |
| | | - hover 大号名称与用途备忘严格服从设置:开启“仅对不常用显示”时只显示不常用 App,关闭时所有 App 都可显示 |
| | | - 版本号更新为 `7.0.12`,Build 更新为 `712` |
| | | - 版本号更新为 `7.0.12`,Build 更新为 `20260517.0712` |
| | | |
| | | ## [7.0.11] — 2026-05-17 |
| | | |
| | | - 设置页「数据」去掉“分类方案数据管理”重复标题,减少顶部视觉干扰 |
| | | - 去掉底部快捷键提示,把页面重心保留给分类方案管理和不常用 App 气泡提示 |
| | | - 将“系统智能化初始分类 / 上一个分类方案 / 当前分类方案”收紧为同一组信息,“上一个分类方案”上移到系统方案下方 |
| | | - 版本号更新为 `7.0.11`,Build 更新为 `711` |
| | | - 版本号更新为 `7.0.11`,Build 更新为 `20260517.0711` |
| | | |
| | | ## [7.0.10] — 2026-05-17 |
| | | |
| | | - 进一步优化设置页「数据」布局:分类方案数据管理面板加宽,标题居中,方案行采用固定标签列对齐 |
| | | - 去掉面板内“备份与恢复”小标题,将导出/导入按钮及说明文案居中显示在面板底部 |
| | | - 版本号更新为 `7.0.10`,Build 更新为 `710` |
| | | - 版本号更新为 `7.0.10`,Build 更新为 `20260517.0710` |
| | | |
| | | ## [7.0.9] — 2026-05-17 |
| | | |
| | | - 设置页「数据」布局优化:将“备份与恢复”的导出/导入操作整合进“分类方案数据管理”面板,统一归入分类方案数据管理范围 |
| | | - 版本号更新为 `7.0.9`,Build 更新为 `709` |
| | | - 版本号更新为 `7.0.9`,Build 更新为 `20260517.0709` |
| | | |
| | | ## [7.0.8] — 2026-05-17 |
| | | |
| | | - 分类方案名称中的生成时间改为语言无关的纯数字格式 `yyyy.MMdd.HHmm`,例如 `2026.0517.1804` |
| | | - 已存在的旧式本地化日期方案名会在读取时自动规范化,导出文件名也同步使用新的数字时间格式 |
| | | - 版本号更新为 `7.0.8`,Build 更新为 `708` |
| | | - 版本号更新为 `7.0.8`,Build 更新为 `20260517.0708` |
| | | |
| | | ## [7.0.7] — 2026-05-17 |
| | | |
| | | - 参考编辑按钮的稳定事件路径,将设置按钮改为发送 App 内通知,由 AppDelegate 固定监听后打开设置窗口,减少静态代理调用链路导致的点击无响应 |
| | | - 版本号更新为 `7.0.7`,Build 更新为 `707` |
| | | - 版本号更新为 `7.0.7`,Build 更新为 `20260517.0707` |
| | | |
| | | ## [7.0.6] — 2026-05-17 |
| | | |
| | | - 设置页「数据」中“分类方案”标题改为“分类方案数据管理” |
| | | - 调整系统智能化初始分类行布局,右侧固定显示「应用」按钮,避免长方案名挤占按钮空间 |
| | | - 版本号更新为 `7.0.6`,Build 更新为 `706` |
| | | - 版本号更新为 `7.0.6`,Build 更新为 `20260517.0706` |
| | | |
| | | ## [7.0.5] — 2026-05-17 |
| | | |
| | | - 修复浮层右上角设置图标点击仍可能无响应的问题:按钮命中判断改为按鼠标真实坐标查找被点击的原生图标控件,避免 SwiftUI 包裹层误判左右按钮 |
| | | - 版本号更新为 `7.0.5`,Build 更新为 `705` |
| | | - 版本号更新为 `7.0.5`,Build 更新为 `20260517.0705` |
| | | |
| | | ## [7.0.4] — 2026-05-17 |
| | | |
| | |
| | | - 当前方案和上一个方案会自动补齐带生成日期时间的系统方案名,不再显示泛化的“当前本地方案” |
| | | - 导出分类与布局时,默认 JSON 文件名改为使用当前分类方案名,而不是导出当下的时间 |
| | | - 应用、导入、恢复分类方案后会通知应用列表刷新,减少设置页和主浮层显示不同步 |
| | | - 版本号更新为 `7.0.4`,Build 更新为 `704` |
| | | - 版本号更新为 `7.0.4`,Build 更新为 `20260517.0704` |
| | | |
| | | ## [7.0.3] — 2026-05-17 |
| | | |
| | | - 将应用列表浮层里的编辑/设置圆形图标改为原生 AppKit 点击控件,避免 SwiftUI 全屏浮层事件分发导致设置图标点击无响应 |
| | | - 从设置图标打开设置页时主动激活 App,提升 non-activating 浮层场景下设置窗口显示的稳定性 |
| | | - 版本号更新为 `7.0.3`,Build 更新为 `703` |
| | | - 版本号更新为 `7.0.3`,Build 更新为 `20260517.0703` |
| | | |
| | | ## [7.0.2] — 2026-05-17 |
| | | |
| | | - 修复给 App 写备注时中文/日文等输入法候选词窗口被全屏浮层遮住,导致无法选字的问题 |
| | | - 备注编辑期间会临时降低应用列表浮层层级,让输入法候选框显示在上方;退出备注编辑后恢复原最高层级 |
| | | - 版本号更新为 `7.0.2`,Build 更新为 `702` |
| | | - 版本号更新为 `7.0.2`,Build 更新为 `20260517.0702` |
| | | |
| | | ## [7.0.1] — 2026-05-17 |
| | | |
| | |
| | | - 设置窗口改为由 AppDelegate 统一创建和置顶管理,保证从菜单、快捷键或设置图标打开时都能显示在应用列表视图上层 |
| | | - 修复浮层点击分发逻辑过度转发 `NSControl`,导致设置图标点击可能无法打开设置窗口的问题 |
| | | - 打包脚本在构建开始时读取并校验 `Info.plist` 中的版本号和 Build 号,构建日志会明确显示当前打包版本 |
| | | - 版本号更新为 `7.0.1`,Build 更新为 `701` |
| | | - 版本号更新为 `7.0.1`,Build 更新为 `20260517.0701` |
| | | |
| | | ## [7.0.0] — 2026-05-17 |
| | | |
| | |
| | | - 将 Smart Start 提示从顶部横幅改为居中确认面板,放大标题、正文和按钮,避免用户错过“应用 / 暂不应用”的关键决策 |
| | | - 设置页「数据」页签显示当前分类方案和上一个分类方案名称,方案名称包含日期时间;导出分类与布局的默认文件名也追加日期时间 |
| | | - 应用列表右上角新增与编辑按钮风格一致的设置图标,方便用户直接进入设置页 |
| | | - 版本号更新为 `7.0.0`,Build 更新为 `700` |
| | | - 版本号更新为 `7.0.0`,Build 更新为 `20260517.0700` |
| | | |
| | | ## [6.0.5] — 2026-05-16 |
| | | |
| | |
| | | - 修复顶部模式说明使用无限宽度参与窗口约束计算时可能触发 AppKit 约束更新异常并闪退的问题 |
| | | - 修复新版 macOS 上 Safari 等系统 App 可能被扫描遗漏的问题:扫描器现在会识别搜索目录的直接 `.app` 子级、补充 Cryptex 系统应用目录,并用真实路径去重但保留稳定入口路径 |
| | | - 补齐编辑模式相关新增文案到全部语言文件,避免切换语言后出现缺失键 |
| | | - 版本号更新为 `6.0.5`,Build 更新为 `610` |
| | | - 版本号更新为 `6.0.5`,Build 更新为 `20260516.0610` |
| | | |
| | | ## [6.0.0] — 2026-05-16 |
| | | |
| | |
| | | - 为编辑模式新增只读标签状态区:单选显示当前标签,多选显示共同标签,并提示其他标签可能不同 |
| | | - 新扫描到的 App 会自动标记为“不常用”,并开始统计从 TagLauncher 打开的次数;达到 100 次后,只有系统自动加上的“不常用”才会被自动移除 |
| | | - 为新增功能补齐全部 29 个语言版本文案 |
| | | - 版本号更新为 `6.0.0`,Build 更新为 `600` |
| | | - 版本号更新为 `6.0.0`,Build 更新为 `20260516.0600` |
| | | |
| | | ## [5.7.8] — 2026-05-15 |
| | | |
| | |
| | | - 微调「应用列表样式」选择区:Flat 单独占满第一行,其余四个样式按两列两行排列,形成更稳定的视觉宽度关系 |
| | | - 收窄「应用列表样式」选项块高度,并为平铺、瀑布流容器、等高网格增加小图示,帮助用户快速区分布局类型 |
| | | - 在设置页的「语言」「数据」「关于」三个空白较多的页签增加 `⌥ + ⇧ + 空格键` 图形化快捷键提示,避免影响「通用」和「标签」页的主要设置/编辑区域 |
| | | - 版本号保持 `5.7.8`,Build 更新为 `583` |
| | | - 版本号保持 `5.7.8`,Build 更新为 `20260515.0583` |
| | | - 同步更新 `AppStore_Submission.md` 的版本信息和 What's New |
| | | |
| | | ## [5.7.5] — 2026-05-14 |
| | |
| | | - 修复全屏应用 Space 中打开设置时,设置窗口跑到其他窗口/屏幕的问题:设置窗口作为当前 TagLauncher overlay 的子窗口置顶显示 |
| | | - 优化设置窗口关闭后 overlay 的焦点恢复,减少设置窗口和主浮层之间的层级错乱 |
| | | - 为普通应用列表中的标签导航增加拖动排序退出兜底,尝试解决拖动后标签持续抖动的问题 |
| | | - 版本号更新为 `5.7.5`,Build 更新为 `575` |
| | | - 版本号更新为 `5.7.5`,Build 更新为 `20260514.0575` |
| | | |
| | | ## [5.7.0] — 2026-05-13 |
| | | |
| | |
| | | - 优化语言自动匹配逻辑,支持更多系统语言代码映射 |
| | | - 修复状态栏菜单项在语言切换后的刷新逻辑,避免重复创建状态栏图标 |
| | | - 固定设置窗口尺寸为 880×460,减少不同页签之间的高度和宽度跳动 |
| | | - 版本号更新为 `5.7.0`,Build 更新为 `570` |
| | | - 版本号更新为 `5.7.0`,Build 更新为 `20260513.0570` |
| | | |
| | | ## [5.6.0] — 2026-05-13 |
| | | |
| | |
| | | - App Store 沙盒构建下隐藏 Launch at Login 控件,避免沙盒环境中不可用功能误导用户 |
| | | - 移除已弃用的应用启动 API,统一使用现代 `NSWorkspace.OpenConfiguration` |
| | | - 新增 App Store 沙盒 entitlements,支持 App Store 构建验证 |
| | | - 版本号更新为 `5.6.0`,Build 更新为 `560` |
| | | - 版本号更新为 `5.6.0`,Build 更新为 `20260513.0560` |
| | | |
| | | ## [5.5.0] — 2026-05-11 |
| | | |
| | |
| | | - 数据页按钮文案由「导出 tag / 导入 tag」改为「导出分类与布局 / 导入分类与布局」,并同步所有已支持语言 |
| | | - 增加旧版非沙盒数据到 App Store 沙盒容器的数据迁移逻辑,降低更新后标签和排序丢失风险 |
| | | - 新增 App Store 提审资料文档,记录版本信息、隐私说明、截图建议和审核备注 |
| | | - 版本号更新为 `5.5.0`,Build 更新为 `550` |
| | | - 版本号更新为 `5.5.0`,Build 更新为 `20260511.0550` |
| | | |
| | | ## [5.2.0] — 2026-05-11 |
| | | |
| | | - 重做 App 拖动预览实现,改为 CALayer / AppKit 预览层方式,提升拖动过程的稳定性和跟手感 |
| | | - 优化拖动预览在 overlay 和全屏 Space 中的显示层级,减少拖动图标被遮挡或丢失的情况 |
| | | - 保持拖动投放逻辑与分类容器绑定,继续支持移动/复制到目标标签 |
| | | - 版本号更新为 `5.2.0`,Build 更新为 `520` |
| | | - 版本号更新为 `5.2.0`,Build 更新为 `20260511.0520` |
| | | |
| | | ## [5.1.12] — 2026-05-11 |
| | | |
| | |
| | | - 优化标签数据库导入/导出和排序数据结构处理 |
| | | - 调整图标资源生成流程,删除旧 `AppIcon.iconset`,使用压缩后的 `icon-icns.icns` 降低包体体积 |
| | | - 补充应用描述相关本地化文案 |
| | | - 版本号更新为 `5.1.12`,Build 更新为 `512` |
| | | - 版本号更新为 `5.1.12`,Build 更新为 `20260511.0512` |
| | | |
| | | ## [4.0.7] — 2026-05-11 |
| | | |
| | |
| | | - 更新 9 个既有语言的视图名称和说明文案 |
| | | - 完善 `build.sh`,强化构建流程中的 bundle 结构、资源复制、权限设置、strip 和签名步骤 |
| | | - 新增 `make_dmg.sh`,支持生成 DMG 发布包 |
| | | - 版本号更新为 `4.0.7`,Build 更新为 `407` |
| | | - 版本号更新为 `4.0.7`,Build 更新为 `20260511.0407` |
| | | |
| | | ## [4.0.0] — 2026-05-10 |
| | | |
| | |
| | | 项目决策记录(DECISIONS.md) |
| | | 由 Hermes Agent 自动维护,用于记录每个版本的需求背景和决策过程。 |
| | | |
| | | ## 2026-05-20 — 工作流程规范收口为单一权威文档 |
| | | |
| | | - 新增唯一权威流程文档:`Docs/ProjectManagement/Apptag_Development_Workflow_Standard_v1.0.md`。 |
| | | - 该文档统一收口项目级工作流程、文档更新责任、QA 门槛、版本管理、构建规则、发布门槛与冲突处理规则。 |
| | | - `.hermes.md` 现在只作为入口指针,不再单独维护散落的流程规则。 |
| | | - 明确将“build 过程不得回写受版本控制的源码文件”升级为硬性规则。 |
| | | - 当前 `build.sh` 回写 `Apptag/Info.plist` 的做法被定义为流程缺陷;治本要求是只改产物中的 `Info.plist`,不改仓库工作区。 |
| | | - 后续任何 coder(包括 AI coder)如果收到与流程规范冲突的指令,必须指出违反的具体条款,而不能静默执行。 |
| | | - 已在 `build.sh` 落地第一步修复:打包时先复制源码 `Info.plist` 到 `.app` 包内,再只修改产物中的 `CFBundleVersion`。 |
| | | - 验收结果:`build/TagLauncher.app/Contents/Info.plist` 的 `CFBundleVersion` 可独立刷新,而源码 `Apptag/Info.plist` 在构建后保持不变。 |
| | | |
| | | ## 2026-05-10 — 无色容器交互锁定 |
| | | |
| | | - 「无色容器」是 App 列表第 2 种视图样式,对应 `displayMode == "container"`。 |
| New file |
| | |
| | | # TagLauncher 当前 Quick Search 规则快照 |
| | | |
| | | 状态:当前代码实现备份 |
| | | 用途:在后续调整 Quick Search / 快速建议规则前,保存当前行为,便于回看、对照或恢复 |
| | | 生成日期:2026-05-20 |
| | | 主要代码来源: |
| | | |
| | | - `Apptag/QuickSearch.swift` |
| | | - `Apptag/ContentView.swift` |
| | | - `Apptag/ApptagApp.swift` |
| | | - `Apptag/PreferencesView.swift` |
| | | - `Apptag/AppDefaults.swift` |
| | | - `Apptag/DataLayer.swift` |
| | | |
| | | ## 1. 当前能力总览 |
| | | |
| | | 当前代码中的 Quick Search 已经包含以下能力: |
| | | |
| | | - 主界面内按空格打开 Quick Search。 |
| | | - 可配置一个全局 Quick Search 快捷键。 |
| | | - Quick Search 打开后显示浮层输入框。 |
| | | - 查询为空时显示默认建议列表。 |
| | | - 输入查询后按应用名称、标签、备注、包标识搜索。 |
| | | - 支持精确匹配、前缀匹配、子串匹配、缩写匹配、模糊子序列匹配。 |
| | | - 支持中文拼音候选匹配。 |
| | | - 支持键盘上下选择、回车启动、Esc 关闭。 |
| | | - 启动成功后记录启动次数和最近启动时间。 |
| | | |
| | | ## 2. 快捷键规则 |
| | | |
| | | ### 2.1 主界面快捷键 |
| | | |
| | | 当前默认主界面快捷键: |
| | | |
| | | ```text |
| | | ⇧ ⌥ Space |
| | | Shift + Option + Space |
| | | ``` |
| | | |
| | | 代码定义: |
| | | |
| | | ```swift |
| | | static var defaultMain: LauncherHotkey { |
| | | LauncherHotkey(keyCode: UInt32(kVK_Space), modifiers: UInt32(shiftKey | optionKey)) |
| | | } |
| | | ``` |
| | | |
| | | 当前行为: |
| | | |
| | | - 主界面快捷键始终返回默认值。 |
| | | - 设置页中主界面快捷键展示为一项设置,但当前不允许用户编辑。 |
| | | |
| | | ### 2.2 主界面内 Quick Search 快捷键 |
| | | |
| | | 当前主界面内快捷键: |
| | | |
| | | ```text |
| | | Space |
| | | ``` |
| | | |
| | | 触发条件: |
| | | |
| | | - 按下的是空格键。 |
| | | - 不是按键重复事件。 |
| | | - 没有任何修饰键。 |
| | | - 主界面窗口当前可见。 |
| | | - Quick Search 当前未打开。 |
| | | - 不在编辑模式。 |
| | | - 不在应用备注编辑状态。 |
| | | - 没有 modal interaction。 |
| | | - 当前焦点不在文本输入控件中。 |
| | | - 当前焦点不在会处理空格的控件中,例如按钮、分段控件、滑块。 |
| | | |
| | | 代码判断逻辑位于 `Apptag/ApptagApp.swift` 的 `shouldOpenQuickSearch(for:)`。 |
| | | |
| | | ### 2.3 全局 Quick Search 快捷键 |
| | | |
| | | 当前默认全局 Quick Search 快捷键: |
| | | |
| | | ```text |
| | | Fn + Space |
| | | ``` |
| | | |
| | | 代码定义: |
| | | |
| | | ```swift |
| | | static var defaultQuickSearch: LauncherHotkey { |
| | | LauncherHotkey(keyCode: UInt32(kVK_Space), modifiers: UInt32(kEventKeyModifierFnMask)) |
| | | } |
| | | ``` |
| | | |
| | | 当前行为: |
| | | |
| | | - 如果用户没有保存过 Quick Search 全局快捷键,默认返回 `Fn + Space`。 |
| | | - AppDefaults 迁移逻辑会在没有存储值时写入默认 `Fn + Space`。 |
| | | - 设置页允许用户修改全局 Quick Search 快捷键。 |
| | | - 设置页允许恢复默认全局 Quick Search 快捷键,也就是恢复为 `Fn + Space`。 |
| | | |
| | | ### 2.4 全局快捷键触发行为 |
| | | |
| | | 全局 Quick Search 快捷键触发后: |
| | | |
| | | - 如果主界面窗口已经可见,则不执行任何动作。 |
| | | - 如果主界面窗口不可见,则打开主界面,并以 Quick Search 模式进入。 |
| | | - 这种入口会设置 `quickSearchCloseHidesOverlay = true`。 |
| | | - 当用户关闭 Quick Search 时,主界面也会一起隐藏。 |
| | | |
| | | 代码行为: |
| | | |
| | | ```swift |
| | | private func showQuickSearchFromGlobalHotkey() { |
| | | guard overlayWindow?.isVisible != true else { return } |
| | | showOverlay(initialQuickSearchSource: QuickSearchOpenSource.globalHidden) |
| | | } |
| | | ``` |
| | | |
| | | ## 3. 快捷键设置和冲突处理 |
| | | |
| | | ### 3.1 快捷键注册方式 |
| | | |
| | | 当前使用 Carbon `RegisterEventHotKey` 注册全局快捷键。 |
| | | |
| | | 注册成功: |
| | | |
| | | - 保存快捷键。 |
| | | - 状态设置为 `Active`。 |
| | | - 清除 pending 快捷键。 |
| | | - 清除冲突信息。 |
| | | |
| | | 注册失败: |
| | | |
| | | - 保留之前可用的快捷键引用。 |
| | | - 保存用户刚录入但注册失败的 pending 快捷键。 |
| | | - 状态设置为 `Conflict`。 |
| | | - 写入冲突文案。 |
| | | |
| | | ### 3.2 当前快捷键状态 |
| | | |
| | | 当前支持三种状态: |
| | | |
| | | ```text |
| | | Active |
| | | Conflict |
| | | Disabled |
| | | ``` |
| | | |
| | | 设置页展示逻辑: |
| | | |
| | | - 正常时显示当前 active 快捷键。 |
| | | - 冲突时显示 pending 快捷键,并标记为 blocked。 |
| | | - 如果之前有可用快捷键,冲突说明中会提示“之前可用的快捷键仍保持可用”。 |
| | | |
| | | ### 3.3 已知冲突文案 |
| | | |
| | | 当前代码对以下快捷键有特殊冲突文案: |
| | | |
| | | | 快捷键 | 文案含义 | |
| | | |---|---| |
| | | | `⌘ Space` | Spotlight 冲突 | |
| | | | `⌥ ⌘ Space` | Finder 搜索窗口冲突 | |
| | | | `⌃ Space` | 上一个输入法冲突 | |
| | | | `⌃ ⌥ Space` | 下一个输入法冲突 | |
| | | | `⌃ ⌘ Space` | 表情与符号冲突 | |
| | | | `Fn + Space` | Fn / Globe / 输入法相关冲突 | |
| | | |
| | | 其他冲突使用 generic 文案: |
| | | |
| | | ```text |
| | | This shortcut is already used by macOS or another app. |
| | | Choose another shortcut, or change the shortcut in the other app and retry. |
| | | ``` |
| | | |
| | | ### 3.4 快捷键录制规则 |
| | | |
| | | 录制快捷键时: |
| | | |
| | | - 按 `Esc` 取消录制。 |
| | | - 纯修饰键不会被接受。 |
| | | - 至少要包含一个修饰键。 |
| | | - 支持 `Shift`、`Option`、`Control`、`Command`、`Fn`。 |
| | | - 会忽略单独的修饰键 keyCode。 |
| | | - 捕获到合法快捷键后立即尝试注册。 |
| | | |
| | | ## 4. Quick Search 打开和关闭规则 |
| | | |
| | | ### 4.1 打开规则 |
| | | |
| | | Quick Search 打开时: |
| | | |
| | | - 必须通过 `canOpenQuickSearch` 判断。 |
| | | - 会关闭应用备注气泡。 |
| | | - 会清空查询。 |
| | | - 会清除手动选择状态。 |
| | | - 会清除错误信息。 |
| | | - 会增加 focus token,使输入框获得焦点。 |
| | | - 会立即刷新搜索结果。 |
| | | - 会发送 Quick Search 可见状态通知。 |
| | | |
| | | `canOpenQuickSearch` 条件: |
| | | |
| | | - 不在编辑模式。 |
| | | - 没有未处理的 Uncategorized drop。 |
| | | - 没有 Smart Start notice。 |
| | | - 没有 drop refresh loading。 |
| | | - Quick Search 当前未打开。 |
| | | |
| | | ### 4.2 关闭规则 |
| | | |
| | | Quick Search 关闭时: |
| | | |
| | | - 设置 `quickSearchVisible = false`。 |
| | | - 清空查询。 |
| | | - 清空结果。 |
| | | - 清空选中项。 |
| | | - 清除手动选择状态。 |
| | | - 清除错误信息。 |
| | | - 重置 `quickSearchCloseHidesOverlay`。 |
| | | - 发送 Quick Search 可见状态通知。 |
| | | |
| | | 如果 Quick Search 是通过全局快捷键在隐藏主界面时直接打开的: |
| | | |
| | | - 关闭 Quick Search 时会隐藏主界面。 |
| | | |
| | | ### 4.3 Esc 和点击背景 |
| | | |
| | | 当前行为: |
| | | |
| | | - Quick Search 输入框内按 `Esc` 会关闭 Quick Search。 |
| | | - 主界面的本地键盘监听中,如果 Quick Search 已打开,按 `Esc` 会关闭 Quick Search。 |
| | | - 点击 Quick Search 背景层会关闭 Quick Search。 |
| | | |
| | | ## 5. 搜索索引规则 |
| | | |
| | | 当前每个应用会生成一个 `QuickSearchDocument`。 |
| | | |
| | | 文档字段: |
| | | |
| | | ```text |
| | | app |
| | | localizedNames |
| | | tagNames |
| | | note |
| | | bundleIdentifier |
| | | lastOpenedAt |
| | | openCount |
| | | ``` |
| | | |
| | | 字段来源: |
| | | |
| | | - `app` 来自扫描并经过 TagEditor 标注后的应用。 |
| | | - `localizedNames` 从应用 Bundle 中读取本地化名称、Bundle 名称和 Finder 展示名。 |
| | | - `tagNames` 来自应用当前标签。 |
| | | - `note` 优先使用 `store.appNotes[path]`,其次使用 `app.note`,最后为空字符串。 |
| | | - `bundleIdentifier` 来自应用包标识,没有则为空字符串。 |
| | | - `lastOpenedAt` 来自 `store.appLastOpenedAt[path]`。 |
| | | - `openCount` 来自 `store.appOpenCounts[path]`,没有则为 0。 |
| | | |
| | | 搜索索引刷新时机: |
| | | |
| | | - 应用扫描完成后生成。 |
| | | - 数据变化后刷新应用并重新生成。 |
| | | - 语言变化后刷新应用并重新生成。 |
| | | - 如果 Quick Search 正在打开,刷新完成后会重新计算结果。 |
| | | |
| | | ## 6. 查询标准化规则 |
| | | |
| | | 查询标准化: |
| | | |
| | | - 去掉首尾空白和换行。 |
| | | - 合并连续空白为单个空格。 |
| | | - 大小写不敏感。 |
| | | - 去除音调和变音符号。 |
| | | - 转为小写。 |
| | | |
| | | 如果标准化后的查询为空: |
| | | |
| | | - 进入空查询建议规则。 |
| | | |
| | | 如果标准化后的查询不为空: |
| | | |
| | | - 按空格切分为多个 token。 |
| | | - 每个 token 都必须在同一个应用的某个字段中匹配成功。 |
| | | - 任何 token 找不到匹配,该应用就不会进入结果。 |
| | | |
| | | ## 7. 搜索字段和权重 |
| | | |
| | | 当前搜索字段: |
| | | |
| | | | 字段 | 权重 | |
| | | |---|---:| |
| | | | 应用名称 / 本地化名称 | 100 | |
| | | | 标签名称 | 70 | |
| | | | 应用备注 | 45 | |
| | | | 包标识 | 20 | |
| | | |
| | | 字段优先级也会用于排序: |
| | | |
| | | ```text |
| | | 应用名称优先于标签 |
| | | 标签优先于备注 |
| | | 备注优先于包标识 |
| | | ``` |
| | | |
| | | ## 8. 匹配类型和权重 |
| | | |
| | | 当前支持的匹配类型: |
| | | |
| | | | 匹配类型 | 权重 | |
| | | |---|---:| |
| | | | 精确匹配 | 100 | |
| | | | 前缀匹配 | 80 | |
| | | | 子串匹配 | 60 | |
| | | | 缩写匹配 | 55 | |
| | | | 模糊子序列匹配 | 35 | |
| | | |
| | | ### 8.1 精确匹配 |
| | | |
| | | 字段标准化文本与 token 完全相等。 |
| | | |
| | | ### 8.2 前缀匹配 |
| | | |
| | | 字段标准化文本以 token 开头。 |
| | | |
| | | ### 8.3 子串匹配 |
| | | |
| | | 字段标准化文本包含 token。 |
| | | |
| | | ### 8.4 缩写匹配 |
| | | |
| | | 仅应用名称字段支持缩写匹配。 |
| | | |
| | | 缩写生成规则: |
| | | |
| | | - 单词开头字符进入缩写。 |
| | | - 非字母数字字符会开启下一个单词。 |
| | | - 小写字符后跟大写字符时,大写字符会作为新词开头。 |
| | | |
| | | 示例: |
| | | |
| | | ```text |
| | | Google Chrome -> gc |
| | | Final Cut Pro -> fcp |
| | | ``` |
| | | |
| | | 当前缩写匹配要求: |
| | | |
| | | ```text |
| | | 应用名称缩写必须以 token 开头。 |
| | | ``` |
| | | |
| | | ### 8.5 模糊子序列匹配 |
| | | |
| | | 当 token 长度至少为 2 时,支持非连续字符子序列匹配。 |
| | | |
| | | 示例: |
| | | |
| | | ```text |
| | | ps 可以匹配 Photoshop |
| | | ``` |
| | | |
| | | ### 8.6 位置加分 |
| | | |
| | | 非精确匹配有位置加分: |
| | | |
| | | ```text |
| | | positionBoost = max(0, 10 - min(matchStartIndex, 10)) |
| | | ``` |
| | | |
| | | 含义: |
| | | |
| | | - 越靠前命中,分数越高。 |
| | | - 最高位置加分为 10。 |
| | | - 精确匹配没有位置加分。 |
| | | |
| | | 单个 token 在单个字段上的分数: |
| | | |
| | | ```text |
| | | 字段权重 + 匹配类型权重 + 位置加分 |
| | | ``` |
| | | |
| | | ## 9. 中文和拼音匹配规则 |
| | | |
| | | 当前代码对包含汉字的字段生成拼音候选。 |
| | | |
| | | 拼音候选生成规则: |
| | | |
| | | 1. 对包含汉字的文本执行 `kCFStringTransformToLatin`。 |
| | | 2. 去掉声调。 |
| | | 3. 标准化并小写。 |
| | | 4. 按非字母数字字符切分后重新用空格连接。 |
| | | 5. 生成三个候选: |
| | | - 带空格拼音。 |
| | | - 去掉空格的紧凑拼音。 |
| | | - 拼音首字母。 |
| | | |
| | | 示例: |
| | | |
| | | ```text |
| | | 微信 -> wei xin / weixin / wx |
| | | ``` |
| | | |
| | | 拼音候选参与普通匹配流程: |
| | | |
| | | - 精确匹配。 |
| | | - 前缀匹配。 |
| | | - 子串匹配。 |
| | | - 模糊子序列匹配。 |
| | | |
| | | 应用名称、标签、备注都可以生成拼音候选。 |
| | | |
| | | 包标识不生成拼音候选。 |
| | | |
| | | ## 10. 搜索结果打分规则 |
| | | |
| | | 对于非空查询: |
| | | |
| | | 1. 将查询拆成多个 token。 |
| | | 2. 每个 token 在所有字段中寻找最高分匹配。 |
| | | 3. 所有 token 的最高匹配分相加,得到 `textScore`。 |
| | | 4. 加上行为加分,得到 `finalScore`。 |
| | | |
| | | 公式: |
| | | |
| | | ```text |
| | | finalScore = textScore + behaviorBoost |
| | | ``` |
| | | |
| | | 行为加分最高为 20: |
| | | |
| | | ```text |
| | | behaviorBoost = min(recentBoost + frequencyBoost, 20) |
| | | ``` |
| | | |
| | | 最近启动加分: |
| | | |
| | | | 最近启动时间 | 加分 | |
| | | |---|---:| |
| | | | 24 小时内 | 15 | |
| | | | 7 天内 | 10 | |
| | | | 30 天内 | 5 | |
| | | | 更早 | 2 | |
| | | | 从未启动 | 0 | |
| | | |
| | | 启动频率加分: |
| | | |
| | | ```text |
| | | frequencyBoost = min(openCount, 10) |
| | | ``` |
| | | |
| | | 说明: |
| | | |
| | | - 当前实现只有总启动次数 `openCount`,没有 7 天 / 30 天分窗口。 |
| | | - 行为加分是弱加分,最高只影响 20 分。 |
| | | |
| | | ## 11. 非空查询排序规则 |
| | | |
| | | 搜索结果排序规则: |
| | | |
| | | 1. `finalScore` 高的排前面。 |
| | | 2. `textScore` 高的排前面。 |
| | | 3. 最好命中的字段优先级更高的排前面。 |
| | | 4. 最近启动时间更近的排前面。 |
| | | 5. 启动次数更多的排前面。 |
| | | 6. 应用名称更短的排前面。 |
| | | 7. 应用名称按本地化标准排序。 |
| | | |
| | | 默认返回结果上限: |
| | | |
| | | ```text |
| | | 50 |
| | | ``` |
| | | |
| | | ## 12. 空查询建议规则 |
| | | |
| | | 当查询为空时,当前代码调用: |
| | | |
| | | ```swift |
| | | emptyQueryResults(documents: documents, limit: min(limit, 6)) |
| | | ``` |
| | | |
| | | 也就是说,空查询最多显示 6 个结果。 |
| | | |
| | | ### 12.1 候选来源 |
| | | |
| | | 空查询只使用两类候选: |
| | | |
| | | 1. 有最近启动时间的应用。 |
| | | 2. 启动次数大于 0 的应用。 |
| | | |
| | | 不会使用: |
| | | |
| | | - 当前标签上下文。 |
| | | - Smart Start 分类。 |
| | | - 冷启动推荐。 |
| | | - 应用名称字母兜底。 |
| | | - 固定项。 |
| | | - 随机应用。 |
| | | |
| | | ### 12.2 最近启动列表 |
| | | |
| | | 最近启动列表规则: |
| | | |
| | | - 只包含 `lastOpenedAt != nil` 的应用。 |
| | | - 按最近启动时间倒序排序。 |
| | | - 最近启动时间相同时,按应用名称本地化标准升序排序。 |
| | | |
| | | ### 12.3 高频启动列表 |
| | | |
| | | 高频启动列表规则: |
| | | |
| | | - 只包含 `openCount > 0` 的应用。 |
| | | - 按总启动次数倒序排序。 |
| | | - 启动次数相同时,按应用名称本地化标准升序排序。 |
| | | |
| | | ### 12.4 合并和去重 |
| | | |
| | | 空查询建议的合并规则: |
| | | |
| | | ```text |
| | | ordered = recent + frequent |
| | | ``` |
| | | |
| | | 然后按应用 URL 去重: |
| | | |
| | | - 最近启动列表排在高频启动列表前面。 |
| | | - 同一个应用如果同时在 recent 和 frequent 中,只保留 recent 中的位置。 |
| | | - 去重后取前 6 个。 |
| | | |
| | | ### 12.5 空查询结果分数 |
| | | |
| | | 空查询结果的 `finalScore` 使用行为加分: |
| | | |
| | | ```text |
| | | finalScore = behaviorBoost |
| | | textScore = 0 |
| | | bestFieldRank = Int.max |
| | | matchedTagName = nil |
| | | noteSnippet = nil |
| | | ``` |
| | | |
| | | 但由于空查询结果已经在 `emptyQueryResults` 内部按 recent + frequent 排好,后续没有再调用通用 rank 排序。 |
| | | |
| | | ### 12.6 当前空查询的实际特点 |
| | | |
| | | 当前空查询建议可以概括为: |
| | | |
| | | ```text |
| | | 优先最近启动。 |
| | | 最近启动不足时,用总启动次数补充。 |
| | | 最多 6 个。 |
| | | 没有历史时为空。 |
| | | ``` |
| | | |
| | | ## 13. 结果行展示规则 |
| | | |
| | | 每个结果行展示: |
| | | |
| | | - 应用图标。 |
| | | - 应用名称。 |
| | | - 一行详情文本,如果存在。 |
| | | - 右侧标签胶囊,如果存在。 |
| | | |
| | | ### 13.1 图标 |
| | | |
| | | 图标尺寸: |
| | | |
| | | ```text |
| | | 46 × 46 |
| | | ``` |
| | | |
| | | 圆角: |
| | | |
| | | ```text |
| | | 10 |
| | | ``` |
| | | |
| | | ### 13.2 应用名称 |
| | | |
| | | 应用名称: |
| | | |
| | | - 字号 20。 |
| | | - semibold。 |
| | | - 单行显示。 |
| | | - 超出尾部截断。 |
| | | |
| | | ### 13.3 详情文本 |
| | | |
| | | 详情文本优先级: |
| | | |
| | | 1. 如果本次匹配产生了 `noteSnippet`,显示 `noteSnippet`。 |
| | | 2. 否则显示完整应用备注的截断版本。 |
| | | 3. 如果没有备注,则不显示详情文本。 |
| | | |
| | | 备注截断规则: |
| | | |
| | | - 如果备注长度大于 72,则取前 69 个字符并加 `...`。 |
| | | - `noteSnippet` 如果原备注长度大于 80,则取前 77 个字符并加 `...`。 |
| | | |
| | | 当前行为说明: |
| | | |
| | | - 即使空查询建议没有匹配备注,也会显示应用已有备注。 |
| | | - 如果应用没有备注,不会用标签替代显示在详情文本位置。 |
| | | |
| | | ### 13.4 右侧标签 |
| | | |
| | | 右侧标签取值: |
| | | |
| | | ```text |
| | | matchedTagName ?? document.tagNames.first |
| | | ``` |
| | | |
| | | 含义: |
| | | |
| | | - 如果查询命中了某个标签,显示命中的标签。 |
| | | - 否则显示应用的第一个标签。 |
| | | - 如果没有标签,则不显示右侧标签。 |
| | | |
| | | 标签样式: |
| | | |
| | | - 字号 14。 |
| | | - semibold。 |
| | | - 胶囊背景。 |
| | | - 最大宽度 128。 |
| | | - 单行截断。 |
| | | |
| | | ## 14. 面板视觉和布局规则 |
| | | |
| | | Quick Search 面板: |
| | | |
| | | - 宽度固定为 760。 |
| | | - 背景为 `.regularMaterial`。 |
| | | - 圆角为 34。 |
| | | - 阴影为黑色 0.18,不透明度,半径 36,y 偏移 18。 |
| | | - 边框为主色 0.10,不透明度,线宽 1。 |
| | | |
| | | 输入区域: |
| | | |
| | | - 左侧显示放大镜图标。 |
| | | - 输入框字体大小为 28。 |
| | | - 输入框高度为 44。 |
| | | - 横向内边距为 28。 |
| | | - 顶部内边距为 22。 |
| | | - 底部内边距为 18。 |
| | | |
| | | 结果行: |
| | | |
| | | - 行高为 74。 |
| | | - 行间距为 2。 |
| | | - 列表外部上下内边距为 10。 |
| | | - 列表外部左右内边距为 10。 |
| | | |
| | | 选中态: |
| | | |
| | | - 深色模式:白色 0.14 不透明度。 |
| | | - 浅色模式:黑色 0.075 不透明度。 |
| | | - 选中背景圆角为 18。 |
| | | |
| | | ### 14.1 面板位置 |
| | | |
| | | 面板水平居中。 |
| | | |
| | | 顶部位置: |
| | | |
| | | ```text |
| | | max(notchHeight + 54, min(112, windowHeight * 0.12)) |
| | | ``` |
| | | |
| | | 面板中心点根据估算高度计算: |
| | | |
| | | ```text |
| | | estimatedPanelHeight = visibleRows * 76 + 122 |
| | | panelCenterY = panelTopY + estimatedPanelHeight / 2 |
| | | ``` |
| | | |
| | | ### 14.2 最大可见行数 |
| | | |
| | | 最大可见行数根据窗口高度动态计算: |
| | | |
| | | ```text |
| | | availableHeight = windowHeight - panelTopY - 84 - 122 |
| | | maxVisibleRows = max(1, min(8, floor(availableHeight / 76))) |
| | | ``` |
| | | |
| | | 含义: |
| | | |
| | | - 最多显示 8 行。 |
| | | - 至少显示 1 行。 |
| | | - 结果数超过可见行数时显示垂直滚动条。 |
| | | |
| | | 注意: |
| | | |
| | | - 空查询搜索引擎最多只返回 6 个。 |
| | | - 非空查询最多返回 50 个,但界面最多同时显示 8 行。 |
| | | |
| | | ## 15. 选择和导航规则 |
| | | |
| | | 结果刷新后: |
| | | |
| | | - 如果没有结果,清空选中项,并清除手动选择状态。 |
| | | - 如果用户此前手动选择过某项,并且该项仍在新结果中,则保留选择。 |
| | | - 否则选择第一项。 |
| | | |
| | | 键盘行为: |
| | | |
| | | | 按键 | 行为 | |
| | | |---|---| |
| | | | `↑` | 选择上一项 | |
| | | | `↓` | 选择下一项 | |
| | | | `Enter` | 打开选中应用 | |
| | | | `Esc` | 关闭 Quick Search | |
| | | |
| | | 上下移动规则: |
| | | |
| | | - 不循环。 |
| | | - 到第一项后继续上移仍停留在第一项。 |
| | | - 到最后一项后继续下移仍停留在最后一项。 |
| | | |
| | | 鼠标行为: |
| | | |
| | | - 悬停某个结果时,将该结果设为选中项。 |
| | | - 点击某个结果时,启动该应用。 |
| | | |
| | | ## 16. 启动行为和历史记录 |
| | | |
| | | ### 16.1 启动成功 |
| | | |
| | | 从 Quick Search 启动应用成功后: |
| | | |
| | | - 异步记录启动历史。 |
| | | - 关闭 Quick Search。 |
| | | - 隐藏主界面。 |
| | | |
| | | 记录的历史: |
| | | |
| | | ```text |
| | | appOpenCounts[path] += 1 |
| | | appLastOpenedAt[path] = Date() |
| | | ``` |
| | | |
| | | ### 16.2 启动失败 |
| | | |
| | | 从 Quick Search 启动应用失败后: |
| | | |
| | | - 不关闭 Quick Search。 |
| | | - 不隐藏主界面。 |
| | | - 显示错误文案。 |
| | | - 重新聚焦输入框。 |
| | | - 发送无障碍 announcement。 |
| | | - 不记录启动历史。 |
| | | |
| | | 错误文案 key: |
| | | |
| | | ```text |
| | | quickSearch.launchFailed |
| | | ``` |
| | | |
| | | ### 16.3 和 Uncommon 自动规则的关系 |
| | | |
| | | 记录启动历史时,如果应用的 uncommon 来源是自动标记,并且启动次数达到自动阈值: |
| | | |
| | | - 从 uncommon 应用列表移除。 |
| | | - 移除 uncommon 自动来源。 |
| | | |
| | | 这部分逻辑位于 `TagEditor.recordLauncherOpen(for:)`。 |
| | | |
| | | ## 17. 当前实现没有的规则 |
| | | |
| | | 以下是当前代码没有实现、但后续新方案可能会加入的规则: |
| | | |
| | | - 空查询时基于当前标签加权。 |
| | | - 空查询时基于 Smart Start 分类冷启动。 |
| | | - 空查询时应用名称字母排序兜底。 |
| | | - 空查询时固定显示高价值分类应用。 |
| | | - 空查询时手动固定建议项。 |
| | | - 7 天启动次数和 30 天启动次数分开统计。 |
| | | - 空查询建议的明确分数表。 |
| | | - 空查询建议列表固定不随窗口高度变化。 |
| | | - 主界面全局快捷键可编辑。 |
| | | |
| | | ## 18. 恢复当前规则时的关键点 |
| | | |
| | | 如果后续新规则出问题,需要恢复当前行为,重点恢复以下代码逻辑: |
| | | |
| | | 1. 全局 Quick Search 默认快捷键恢复为 `Fn + Space`。 |
| | | 2. 空查询逻辑恢复为 `emptyQueryResults(documents:limit:)`: |
| | | - 先取最近启动应用。 |
| | | - 再取高频启动应用。 |
| | | - 合并后按应用 URL 去重。 |
| | | - 最多取 6 个。 |
| | | - 没有历史时返回空列表。 |
| | | 3. 非空查询保留当前字段权重: |
| | | - 名称 100。 |
| | | - 标签 70。 |
| | | - 备注 45。 |
| | | - 包标识 20。 |
| | | 4. 非空查询保留当前匹配权重: |
| | | - 精确 100。 |
| | | - 前缀 80。 |
| | | - 子串 60。 |
| | | - 缩写 55。 |
| | | - 模糊 35。 |
| | | 5. 行为加分恢复为最高 20: |
| | | - 最近启动加分最高 15。 |
| | | - 启动次数加分最高 10。 |
| | | - 两者合计封顶 20。 |
| | | 6. 结果行恢复为: |
| | | - 优先显示 noteSnippet。 |
| | | - 否则显示应用备注。 |
| | | - 右侧显示命中标签或第一个标签。 |
| | | 7. Quick Search 面板恢复为: |
| | | - 固定宽度 760。 |
| | | - `.regularMaterial` 背景。 |
| | | - 最多可见 8 行。 |
| | | - 空查询最多 6 条。 |
| | | |
| New file |
| | |
| | | # TagLauncher 7.5 PRD:Quick Search 快速搜索 |
| | | |
| | | 状态:PMD 改写版,用于产品和架构评审 |
| | | 负责人:Product Manager |
| | | 功能:Quick Search、搜索浮层、可配置全局快捷键 |
| | | 版本:7.5 |
| | | |
| | | ## 目标 |
| | | |
| | | TagLauncher 7.5 增加一个键盘优先的 Quick Search 入口,服务于已经明确知道要启动哪个 App 的用户。 |
| | | |
| | | Quick Search 不是当前可见 App 列表的过滤器。它会搜索 TagLauncher 已知的全部可启动 App,搜索字段包括 App 名称、标签名称和 App 备注。 |
| | | |
| | | 默认启动路径: |
| | | |
| | | ```text |
| | | Shift + Option + Space -> 打开 TagLauncher 主界面 |
| | | Space -> 打开 Quick Search |
| | | Type -> 搜索并排序 App |
| | | Enter -> 启动选中的 App |
| | | ``` |
| | | |
| | | 高级用户可以配置一个直接打开 Quick Search 的全局快捷键。该快捷键默认关闭。 |
| | | |
| | | ## 产品决策 |
| | | |
| | | | 主题 | 决策 | |
| | | | ---------------------- | ------------------------------------------- | |
| | | | 默认全局快捷键 | 主界面继续使用 `Shift + Option + Space` | |
| | | | 直接打开 Quick Search 的快捷键 | 可配置,但默认关闭 | |
| | | | `Space` 行为 | 仅在主界面可见,且没有处于正常输入或控件交互状态时打开 Quick Search | |
| | | | 搜索范围 | 搜索全部可启动 App,不限于当前标签或当前可见列表 | |
| | | | 空查询 | 优先展示最近打开的 App,不足时用常用 App 补齐 | |
| | | | 启动成功 | 关闭 Quick Search,然后沿用现有 TagLauncher 启动后的窗口行为 | |
| | | | 启动失败 | 保留查询内容,并显示短错误提示 | |
| | | | 快捷键冲突 | 使用系统正常快捷键注册机制,不强行截获系统快捷键 | |
| | | | 隐私 | 搜索和排序数据只保存在本地 | |
| | | |
| | | ## 范围 |
| | | |
| | | 7.5 必须支持: |
| | | |
| | | - 在主界面按 `Space` 打开 Quick Search 浮层。 |
| | | - 设置中提供直接打开 Quick Search 的全局快捷键,默认关闭。 |
| | | - 支持按 App 显示名称、本地化 App 名称、标签名称和 App 备注搜索。 |
| | | - 支持精确匹配、前缀匹配、子串匹配、首字母缩写匹配、非连续字符匹配,以及拉丁字符大小写不敏感匹配。 |
| | | - 支持中文字符直接匹配。 |
| | | - 支持键盘导航和鼠标点击启动。 |
| | | - 支持最近打开和常用 App 排序加权。 |
| | | - 本地持久化快捷键设置和启动排序数据。 |
| | | - 通过快捷键注册成功或失败判断快捷键是否冲突。 |
| | | |
| | | 7.5 不做: |
| | | |
| | | - 搜索文件、文件夹、联系人、浏览器历史或网页结果。 |
| | | - 完整命令面板。 |
| | | - AI 生成搜索结果。 |
| | | - 远程排序或远程分析。 |
| | | - 拼音匹配。 |
| | | - 用户自定义别名。 |
| | | - 默认替换 Spotlight。 |
| | | - 默认占用 `Option + Space`。 |
| | | - 使用底层键盘拦截强行抢占系统快捷键。 |
| | | |
| | | ## 用户故事 |
| | | |
| | | 1. 作为用户,我可以打开 TagLauncher,按 `Space`,输入几个字符,然后按 `Enter` 启动选中的 App。 |
| | | 2. 作为用户,我可以按 App 名称、标签名称或 App 备注搜索。 |
| | | 3. 作为用户,我可以输入部分字符或非连续字符,并找到相关 App。 |
| | | 4. 作为用户,我可以用方向键切换选中的搜索结果。 |
| | | 5. 作为用户,我可以点击搜索结果启动 App。 |
| | | 6. 作为用户,当我从主界面打开 Quick Search 后,可以按 `Esc` 关闭 Quick Search,同时保留主界面。 |
| | | 7. 作为高级用户,我可以配置一个直接打开 Quick Search 的全局快捷键。 |
| | | 8. 作为用户,我可以看到快捷键当前是已启用、已关闭,还是被冲突阻塞。 |
| | | |
| | | ## 交互要求 |
| | | |
| | | ### 打开 |
| | | |
| | | 当 TagLauncher 主界面可见时,只有同时满足以下条件,按 `Space` 才打开 Quick Search: |
| | | |
| | | - Quick Search 当前未打开。 |
| | | - 当前没有输入框、搜索框、文本区域或可编辑字段获得焦点。 |
| | | - 当前没有模态弹窗、浮层菜单、菜单、确认弹窗或快捷键录制器处于激活状态。 |
| | | - 当前焦点不在一个预期用 `Space` 触发或切换的控件上。 |
| | | |
| | | 从主界面打开时: |
| | | |
| | | - 浮层显示在现有 App 列表上方。 |
| | | - App 列表不被推动、缩放或重排。 |
| | | - Quick Search 输入框立即获得焦点。 |
| | | - 如果有结果,默认选中第一个结果。 |
| | | |
| | | 从直接全局快捷键打开时: |
| | | |
| | | - TagLauncher 直接打开 Quick Search 浮层。 |
| | | - 输入框立即获得焦点。 |
| | | - 如果快捷键触发前主界面是隐藏状态,按 `Esc` 隐藏 Quick Search 窗口。 |
| | | |
| | | ### 浮层 |
| | | |
| | | Quick Search 以浮层形式显示在 TagLauncher 窗口顶部居中附近。 |
| | | |
| | | 必需行为: |
| | | |
| | | - 浮层尽量沿用现有视觉系统。 |
| | | - 输入框是视觉和交互焦点。 |
| | | - 结果列表显示在输入框下方,并处于同一浮层层级。 |
| | | - 浮层显示在 App 列表上方,不改变 App 列表布局。 |
| | | - 浮层支持空状态、加载状态、有结果状态、无结果状态和启动失败状态。 |
| | | |
| | | 可见结果数量:6 到 8 行。 |
| | | |
| | | ### 空查询 |
| | | |
| | | 当查询为空时: |
| | | |
| | | - 最多显示 6 个 App。 |
| | | - 按最近打开时间倒序排列。 |
| | | - 如果最近打开 App 少于 6 个,用最常打开的 App 补齐。 |
| | | - 不展示完整 App 目录。 |
| | | - 如果没有任何历史数据,显示空提示:`开始输入以搜索 App、标签和备注。` |
| | | |
| | | 最近和常用数据必须来自 TagLauncher 成功触发的 App 启动,不限于 Quick Search 启动。 |
| | | |
| | | ### 输入和选中 |
| | | |
| | | 用户输入时: |
| | | |
| | | - 搜索结果实时更新。 |
| | | - 如果用户没有手动改变选中项,每次查询更新后选中排名第一的结果。 |
| | | - 如果用户手动选中的结果在查询更新后仍然可见,保留该选中项。 |
| | | - 如果选中的结果消失,选中排名第一的结果。 |
| | | - 如果没有结果,不选中任何项目,按 `Enter` 无动作。 |
| | | - 如果没有结果,显示:`未找到 App。` |
| | | |
| | | ### 键盘 |
| | | |
| | | | 按键 | 行为 | |
| | | | ------------- | ------------------------- | |
| | | | `Up` | 选中上一个结果;如果已经是第一个结果,则保持不变 | |
| | | | `Down` | 选中下一个结果;如果已经是最后一个结果,则保持不变 | |
| | | | `Enter` | 启动选中的结果 | |
| | | | `Esc` | 关闭 Quick Search | |
| | | | 输入框内的 `Space` | 输入空格字符 | |
| | | |
| | | `Esc` 行为: |
| | | |
| | | - 如果 Quick Search 是从可见主界面打开的,只关闭 Quick Search,并返回主界面。 |
| | | - 如果 Quick Search 是在主界面隐藏时通过直接全局快捷键打开的,关闭 Quick Search 并隐藏窗口。 |
| | | |
| | | ### 鼠标 |
| | | |
| | | - 鼠标悬停结果时,高亮该结果并更新当前选中项。 |
| | | - 点击结果时,启动对应 App。 |
| | | - 点击主界面内但浮层外的区域时,关闭 Quick Search,并保留主界面可见。 |
| | | - 点击 TagLauncher 窗口外时,沿用现有 App 行为。 |
| | | |
| | | ## 搜索要求 |
| | | |
| | | ### 可搜索字段 |
| | | |
| | | | 字段 | 是否必需 | 排序权重 | |
| | | | ----------------- | -----: | ---- | |
| | | | App 显示名称 | 是 | 最高 | |
| | | | 本地化 App 名称 | 有数据时必需 | 最高 | |
| | | | 标签名称 | 是 | 高 | |
| | | | App 备注 | 是 | 中 | |
| | | | Bundle identifier | 可选 | 低 | |
| | | |
| | | 别名、拼音、命令历史和 TagLauncher 操作等未来字段不得阻塞 7.5 发布。 |
| | | |
| | | ### 查询归一化 |
| | | |
| | | 匹配前需要处理: |
| | | |
| | | - 去掉首尾空白。 |
| | | - 合并连续空格。 |
| | | - 拉丁字符大小写不敏感。 |
| | | - 将 App 名称中的标点作为首字母缩写匹配的分隔符。 |
| | | - 保留中文字符作为可搜索字符。 |
| | | |
| | | 多词查询使用 `AND` 语义: |
| | | |
| | | - 每个查询词都必须至少命中一个可搜索字段。 |
| | | - 不同查询词可以命中同一个 App 的不同字段。 |
| | | - 排序时累加每个查询词的最佳得分。 |
| | | |
| | | ### 匹配类型 |
| | | |
| | | 必需匹配类型: |
| | | |
| | | | 类型 | 示例 | |
| | | | ---------- | -------------------------------------- | |
| | | | 精确匹配 | `figma` 匹配 `Figma` | |
| | | | 前缀匹配 | `fig` 匹配 `Figma` | |
| | | | 子串匹配 | `shop` 匹配 `Photoshop` | |
| | | | 首字母缩写匹配 | `gc` 匹配 `Google Chrome` | |
| | | | 非连续字符匹配 | `ps` 匹配 `Photoshop` | |
| | | | 拉丁字符大小写不敏感 | `chrome`、`Chrome` 和 `CHROME` 命中同一个 App | |
| | | | 中文字符直接匹配 | `设计` 匹配包含 `设计` 的标签、名称或备注 | |
| | | |
| | | 首字母缩写从 App 显示名称和本地化名称生成,分隔依据包括空格、标点和 camel-case 边界。 |
| | | |
| | | 非连续字符匹配仅在查询词至少 2 个字符时生效。排序低于精确匹配、前缀匹配、子串匹配和首字母缩写匹配。 |
| | | |
| | | 拼音匹配不在 7.5 范围内。 |
| | | |
| | | ## 排序要求 |
| | | |
| | | 排序必须确定且可测试。 |
| | | |
| | | 7.5 评分模型: |
| | | |
| | | ```text |
| | | finalScore = textScore + behaviorBoost |
| | | textScore = sum(best token score for each query token) |
| | | behaviorBoost = min(recentBoost + frequencyBoost, 20) |
| | | ``` |
| | | |
| | | 字段权重: |
| | | |
| | | | 字段 | 权重 | |
| | | | ----------------- | --: | |
| | | | App 显示名称 / 本地化名称 | 100 | |
| | | | 标签名称 | 70 | |
| | | | App 备注 | 45 | |
| | | | Bundle identifier | 20 | |
| | | |
| | | 匹配类型权重: |
| | | |
| | | | 匹配类型 | 权重 | |
| | | | ------- | --: | |
| | | | 精确匹配 | 100 | |
| | | | 前缀匹配 | 80 | |
| | | | 子串匹配 | 60 | |
| | | | 首字母缩写匹配 | 55 | |
| | | | 非连续字符匹配 | 35 | |
| | | |
| | | 位置加分: |
| | | |
| | | - 字段中越靠前的命中最多加 10 分。 |
| | | - 精确匹配不应用位置加分。 |
| | | |
| | | 行为加分: |
| | | |
| | | - `recentBoost`:最高 15 分。 |
| | | - `frequencyBoost`:最高 10 分。 |
| | | - 两者合计不得超过 20 分。 |
| | | - 行为加分不得让备注中的弱匹配超过同一查询下的强 App 名称匹配。 |
| | | |
| | | 同分排序: |
| | | |
| | | 1. `textScore` 更高者优先。 |
| | | 2. App 名称或本地化名称命中优先于标签命中。 |
| | | 3. 标签命中优先于备注命中。 |
| | | 4. 最近一次通过 TagLauncher 成功启动时间更近者优先。 |
| | | 5. 启动次数更多者优先。 |
| | | 6. 显示名称更短者优先。 |
| | | 7. 按显示名称字母顺序排列。 |
| | | |
| | | 最低排序样例: |
| | | |
| | | | 查询 | 预期行为 | |
| | | | -------- | ----------------------------------------------------- | |
| | | | `fig` | `Figma` 的 App 名称前缀匹配排在备注包含 `fig` 的 App 前面 | |
| | | | `shop` | 返回 `Photoshop` 的子串匹配结果 | |
| | | | `gc` | 返回 `Google Chrome` 的首字母缩写匹配结果 | |
| | | | `ps` | 返回 `Photoshop` 的非连续字符匹配结果,但排在更强的精确或前缀匹配之后 | |
| | | | `design` | 当文本强度接近时,带 `Design` 标签的 App 排在仅备注包含 `design` 的 App 前面 | |
| | | | `ai` | 常用 AI App 可以超过备注中的弱匹配,但不能超过 App 名称精确匹配 | |
| | | |
| | | ## 结果行要求 |
| | | |
| | | 每一行搜索结果包含: |
| | | |
| | | - App 图标。 |
| | | - App 显示名称。 |
| | | - 当标签字段参与命中时,显示命中的标签名称。 |
| | | - 仅当备注字段参与命中时,显示备注片段。 |
| | | - 清晰的选中状态。 |
| | | |
| | | 7.5 可以不做: |
| | | |
| | | - 高亮名称、标签或备注中的命中字符。 |
| | | - 显示 Bundle identifier 作为辅助信息,仅在需要区分相似 App 时再考虑。 |
| | | |
| | | 结果行必须保持紧凑。Quick Search 不是详情页。 |
| | | |
| | | ## 启动行为 |
| | | |
| | | 当用户按 `Enter` 或点击结果时: |
| | | |
| | | 1. 尝试启动选中的 App。 |
| | | 2. 如果启动成功,更新 `lastOpenedAt` 和 `openCount`。 |
| | | 3. 关闭 Quick Search。 |
| | | 4. 沿用现有 TagLauncher 启动 App 后隐藏或保留主界面的行为。 |
| | | |
| | | 如果启动失败: |
| | | |
| | | - 保持 Quick Search 打开。 |
| | | - 保留用户的查询内容。 |
| | | - 不更新 `lastOpenedAt` 或 `openCount`。 |
| | | - 显示:`无法打开这个 App。请重试或选择其他 App。` |
| | | |
| | | ## 快捷键设置 |
| | | |
| | | 设置中必须提供: |
| | | |
| | | | 设置项 | 默认值 | |
| | | | ---------------------- | ------------------------ | |
| | | | 主界面快捷键 | `Shift + Option + Space` | |
| | | | 直接打开 Quick Search 的快捷键 | 关闭 | |
| | | |
| | | 必需操作: |
| | | |
| | | - 录制快捷键。 |
| | | - 清除快捷键。 |
| | | - 恢复主界面默认快捷键。 |
| | | - 冲突解决后重试注册。 |
| | | - 在系统支持时打开 macOS Keyboard Shortcuts 设置。 |
| | | |
| | | 快捷键状态: |
| | | |
| | | | 状态 | 含义 | |
| | | | -------- | ---------------------------- | |
| | | | Active | 快捷键注册成功,并立即可用 | |
| | | | Conflict | 快捷键无法注册,因为 macOS 或其他 App 已占用 | |
| | | | Disabled | 未分配快捷键 | |
| | | |
| | | 用户录制快捷键时: |
| | | |
| | | - TagLauncher 立即尝试注册该快捷键。 |
| | | - 如果注册成功,保存快捷键并显示 `Active`。 |
| | | - 如果注册失败,显示 `Conflict`,不得显示为已启用。 |
| | | - 如果之前已有一个可用快捷键,新快捷键注册失败时,旧快捷键继续保持可用。 |
| | | - 快捷键变更不需要重启 App。 |
| | | |
| | | 以下已知 macOS 快捷键在注册失败时需要显示特定说明: |
| | | |
| | | | 快捷键 | macOS 默认用途 | |
| | | | --------------------------- | ----------- | |
| | | | `Command + Space` | Spotlight | |
| | | | `Option + Command + Space` | Finder 搜索窗口 | |
| | | | `Control + Space` | 上一个输入法 | |
| | | | `Control + Option + Space` | 下一个输入法 | |
| | | | `Control + Command + Space` | 表情与符号 | |
| | | |
| | | 冲突文案规则: |
| | | |
| | | - 如果快捷键属于已知 macOS 默认快捷键,且注册失败,显示对应的 macOS 指引。 |
| | | - 其他失败统一显示:`这个快捷键已被 macOS 或其他 App 使用。请选择其他快捷键,或先修改其他 App 中的快捷键后再重试。` |
| | | - TagLauncher 不得使用底层键盘拦截绕过 macOS 的快捷键归属。 |
| | | |
| | | ## 数据要求 |
| | | |
| | | 搜索文档字段: |
| | | |
| | | ```text |
| | | appId |
| | | bundleIdentifier |
| | | displayName |
| | | localizedNames |
| | | tagNames |
| | | note |
| | | lastOpenedAt |
| | | openCount |
| | | ``` |
| | | |
| | | 索引刷新触发条件: |
| | | |
| | | - App 目录变化。 |
| | | - App 安装或移除扫描。 |
| | | - 标签分配变化。 |
| | | - 标签重命名。 |
| | | - App 备注变化。 |
| | | - 当本地化名称或标签可用时,App 语言或 locale 变化。 |
| | | |
| | | 启动排序数据: |
| | | |
| | | - 存储在本地。 |
| | | - 仅在 TagLauncher 成功触发 App 启动后更新。 |
| | | - 现有用户从空历史和 `openCount = 0` 开始。 |
| | | - 当 App 从本地目录移除时,移除对应排序数据。 |
| | | |
| | | ## 性能要求 |
| | | |
| | | 搜索必须本地运行,并支持离线使用。 |
| | | |
| | | 目标: |
| | | |
| | | - 打开浮层不得阻塞于网络请求或 App 扫描。 |
| | | - 在 1,000 条本地 App 记录下,可见结果必须在典型支持 Mac 上 p95 50 ms 内更新。 |
| | | - 当索引已在内存中时,输入过程必须保持视觉流畅。 |
| | | - App 可以在 TagLauncher 运行期间将搜索索引保存在内存中。 |
| | | |
| | | 性能测量包含查询处理和结果列表更新,不包含 App 启动时间。 |
| | | |
| | | ## 隐私要求 |
| | | |
| | | - 不得将搜索查询发送到服务器。 |
| | | - 不得为了该功能将 App 名称、标签名称、App 备注、快捷键设置、最近启动数据或启动次数发送到服务器。 |
| | | - 快捷键设置存储在本地。 |
| | | - 最近和常用启动数据存储在本地。 |
| | | |
| | | ## 可访问性和本地化 |
| | | |
| | | 可访问性: |
| | | |
| | | - 必须支持完整键盘操作。 |
| | | - 输入框必须有可访问性标签。 |
| | | - 在系统支持的情况下,结果行必须向可访问性 API 暴露 App 名称和相关元数据。 |
| | | - 选中状态必须在视觉上清晰。 |
| | | - 在系统支持的情况下,无结果和启动失败状态需要被朗读或通知。 |
| | | |
| | | 本地化: |
| | | |
| | | - 所有用户可见字符串必须支持本地化。 |
| | | - 快捷键冲突指引必须支持本地化。 |
| | | - 有本地化 App 名称和标签名称时,搜索使用本地化内容。 |
| | | |
| | | ## 验收标准 |
| | | |
| | | Quick Search: |
| | | |
| | | - `Shift + Option + Space` 打开 TagLauncher 主界面。 |
| | | - 在有效的主界面状态下按 `Space` 打开 Quick Search。 |
| | | - Quick Search 以浮层形式显示,且不重排 App 列表。 |
| | | - 输入框立即获得焦点。 |
| | | - 空查询显示最近和常用 App,不显示完整目录。 |
| | | - 无结果状态清晰。 |
| | | - 启动失败状态保留查询内容。 |
| | | |
| | | 搜索: |
| | | |
| | | - 搜索 TagLauncher 已知的全部可启动 App。 |
| | | - 搜索 App 显示名称、有数据时的本地化名称、标签名称和 App 备注。 |
| | | - 支持精确匹配、前缀匹配、子串匹配、首字母缩写匹配、非连续字符匹配、拉丁字符大小写不敏感匹配和中文字符直接匹配。 |
| | | - 多词查询要求每个查询词都命中。 |
| | | - 排序遵循本文档中的字段权重、匹配类型权重、行为加分和同分排序规则。 |
| | | |
| | | 键盘和鼠标: |
| | | |
| | | - `Up` 和 `Down` 可以切换选中项。 |
| | | - `Enter` 启动选中结果。 |
| | | - 没有结果时,`Enter` 无动作。 |
| | | - `Esc` 按照 Quick Search 的打开方式执行正确关闭行为。 |
| | | - 鼠标悬停更新当前选中项。 |
| | | - 点击结果启动对应 App。 |
| | | - 点击主界面内但浮层外区域关闭 Quick Search,并保留主界面可见。 |
| | | |
| | | 快捷键: |
| | | |
| | | - 主界面快捷键可配置。 |
| | | - 直接打开 Quick Search 的快捷键可配置,且默认关闭。 |
| | | - 快捷键变更无需重启。 |
| | | - 快捷键设置在 App 重启后保持。 |
| | | - 快捷键注册失败时显示 `Conflict`,不得显示为 `Active`。 |
| | | - 新快捷键注册失败时,之前可用的快捷键继续可用。 |
| | | - 已知 macOS 冲突显示特定指引。 |
| | | - 未知冲突显示通用指引。 |
| | | - 用户解决冲突后可以重试。 |
| | | |
| | | 隐私和性能: |
| | | |
| | | - 搜索可离线使用。 |
| | | - 搜索不会将查询或 App 备注发送到服务器。 |
| | | - 结果更新达到 1,000 条记录下的 p95 性能目标。 |
| | | |
| | | ## QA 场景 |
| | | |
| | | 1. 用 `Shift + Option + Space` 打开主界面,按 `Space`,验证 Quick Search 打开且输入框获得焦点。 |
| | | 2. 当文本框、模态弹窗、菜单或快捷键录制器处于激活状态时按 `Space`,验证 Quick Search 不打开。 |
| | | 3. 打开 Quick Search 且查询为空,验证最近打开 App 优先显示。 |
| | | 4. 验证没有历史数据的用户看到 `开始输入以搜索 App、标签和备注。` |
| | | 5. 按 App 名称搜索,并用 `Enter` 启动。 |
| | | 6. 在有本地化名称时,按本地化 App 名称搜索。 |
| | | 7. 按标签名称搜索,验证相关标签下的 App 出现。 |
| | | 8. 按 App 备注搜索,验证仅在备注命中时显示备注片段。 |
| | | 9. 搜索 `gc`,验证首字母缩写匹配。 |
| | | 10. 搜索 `ps`,验证非连续字符匹配。 |
| | | 11. 搜索中文字符,验证中文直接匹配。 |
| | | 12. 使用 `Up` 和 `Down` 切换选中项,然后按 `Enter` 启动。 |
| | | 13. 从主界面打开后按 `Esc`,验证主界面仍然可见。 |
| | | 14. 在窗口隐藏时通过直接全局快捷键打开后按 `Esc`,验证窗口隐藏。 |
| | | 15. 配置一个可用的直接 Quick Search 快捷键,验证它立即生效。 |
| | | 16. 当 Spotlight 占用 `Command + Space` 时配置该快捷键,验证冲突状态和 Spotlight 特定指引。 |
| | | 17. 新快捷键注册失败后,验证之前可用的快捷键仍然有效。 |
| | | 18. 解决或更换冲突快捷键后点击 Retry,验证状态更新。 |
| | | 19. 重启 TagLauncher,验证快捷键设置保持。 |
| | | 20. 确认在 Quick Search 输入时没有网络请求。 |
| | | 21. 测试 1,000 条 App 记录,验证可见结果更新达到性能目标。 |
| | | |
| New file |
| | |
| | | # TagLauncher 7.5 产品需求文档:快速建议 |
| | | |
| | | 状态:产品与架构评审草案 |
| | | 负责人:产品经理 / 架构师 |
| | | 功能:快速建议 |
| | | 所属能力:快速搜索 |
| | | 版本:7.5 |
| | | |
| | | ## 1. 产品目标 |
| | | |
| | | 快速建议是快速搜索在空查询状态下显示的默认建议列表。 |
| | | |
| | | 当用户打开快速搜索,但还没有输入任何内容时,TagLauncher 不应该展示完整应用列表,也不应该显示空白界面,而应该主动给出一组“此刻最可能想打开的应用”。 |
| | | |
| | | 快速建议的目标是: |
| | | |
| | | - 让快速搜索一打开就有可操作对象。 |
| | | - 帮用户快速重复打开最近使用的应用。 |
| | | - 帮用户快速进入高频应用。 |
| | | - 在不输入任何字符的情况下,也能通过 `Enter` 直接打开最可能的应用。 |
| | | - 保持快速搜索作为“快速启动入口”的产品气质,而不是退化成另一个应用列表。 |
| | | |
| | | 一句话定义: |
| | | |
| | | ```text |
| | | 快速建议 = 用户还没输入时,TagLauncher 对“你现在可能想打开什么”的本地预测。 |
| | | ``` |
| | | |
| | | ## 2. 产品定位 |
| | | |
| | | 快速搜索有两个状态: |
| | | |
| | | | 状态 | 用户输入 | 产品行为 | |
| | | |---|---|---| |
| | | | 快速建议 | 查询为空 | 显示推荐应用 | |
| | | | 搜索结果 | 查询不为空 | 显示匹配应用 | |
| | | |
| | | 快速建议不是搜索结果,也不是完整应用目录。 |
| | | |
| | | 它的定位是: |
| | | |
| | | ```text |
| | | 打开即建议。 |
| | | 默认可回车。 |
| | | 少量、高质量、动态变化。 |
| | | ``` |
| | | |
| | | 快速建议的生成原则是: |
| | | |
| | | ```text |
| | | 近期优先,频率兜底,当前上下文轻微加权。 |
| | | ``` |
| | | |
| | | ## 3. 已确认的产品规则 |
| | | |
| | | ### 3.1 不显示列表标题 |
| | | |
| | | 快速建议列表上方不显示“快速建议”“最近使用”“推荐应用”等标题。 |
| | | |
| | | 快速搜索输入框下方直接显示建议列表。这样可以保持接近 Spotlight / Raycast 的快速感,避免界面变成列表页或管理页。 |
| | | |
| | | ### 3.2 固定最多显示 6 个建议 |
| | | |
| | | 快速建议最多显示 6 个应用。 |
| | | |
| | | 规则: |
| | | |
| | | - 建议数量上限固定为 6 个。 |
| | | - 不做 5 到 8 个的自适应数量。 |
| | | - 不足 6 个时显示实际数量。 |
| | | - 不为了凑满 6 个而显示低质量、随机或无意义的应用。 |
| | | - 不显示完整应用目录。 |
| | | |
| | | ### 3.3 默认显示一行备注 |
| | | |
| | | 每个建议项默认显示应用备注,但只显示一行。 |
| | | |
| | | 展示优先级: |
| | | |
| | | 1. 应用图标。 |
| | | 2. 应用名称。 |
| | | 3. 一行应用备注。 |
| | | 4. 如果没有备注,则显示标签信息。 |
| | | 5. 如果备注和标签都没有,则只显示应用名称。 |
| | | |
| | | 备注过长时: |
| | | |
| | | - 只显示一行。 |
| | | - 超出部分截断。 |
| | | - 不撑高建议项。 |
| | | - 不影响列表整体高度。 |
| | | |
| | | ### 3.4 冷启动复用 Smart Start 分类 |
| | | |
| | | 新用户或历史不足的用户进入冷启动模式。 |
| | | |
| | | 冷启动触发条件: |
| | | |
| | | ```text |
| | | 通过 TagLauncher 成功启动应用的总次数少于 3 次 |
| | | 或 |
| | | 通过 TagLauncher 成功启动过的不同应用少于 3 个 |
| | | ``` |
| | | |
| | | 冷启动时,快速建议优先展示本机已安装且属于高价值分类的应用。 |
| | | |
| | | 高价值分类顺序: |
| | | |
| | | ```text |
| | | 浏览器 > 沟通 > AI 工具 > 开发 > 效率 > 设计 > 系统工具 |
| | | ``` |
| | | |
| | | 冷启动候选来源: |
| | | |
| | | 1. 当前标签上下文中的应用,如果用户是从某个标签视图进入快速搜索。 |
| | | 2. 本机已安装且命中 Smart Start 高价值分类的应用。 |
| | | 3. 本机已安装的常见高价值应用。 |
| | | 4. 应用名称字母排序兜底。 |
| | | |
| | | 冷启动不允许随机。 |
| | | |
| | | ### 3.5 7.5 不支持用户手动固定建议项 |
| | | |
| | | 7.5 不提供用户手动固定快速建议项的功能。 |
| | | |
| | | 不做的内容: |
| | | |
| | | - 不做固定按钮。 |
| | | - 不做取消固定。 |
| | | - 不做右键固定菜单。 |
| | | - 不做固定建议项设置页。 |
| | | |
| | | 可以预留的数据和架构能力: |
| | | |
| | | - 数据模型可以预留 `isPinned` 字段。 |
| | | - 排序服务可以预留固定加权入口。 |
| | | - 7.5 的用户界面不暴露固定操作。 |
| | | |
| | | ### 3.6 使用明确的本地排序公式 |
| | | |
| | | 7.5 使用简单、可解释、可测试的本地评分模型。 |
| | | |
| | | 排序公式: |
| | | |
| | | ```text |
| | | 总分 = |
| | | 最近启动分 |
| | | + 高频启动分 |
| | | + 当前标签加权分 |
| | | + 冷启动分 |
| | | ``` |
| | | |
| | | 核心约束: |
| | | |
| | | ```text |
| | | 最近启动分 > 高频启动分 > 当前标签加权分 |
| | | ``` |
| | | |
| | | 也就是说: |
| | | |
| | | - 最近启动是最强信号。 |
| | | - 高频启动用于兜底长期习惯。 |
| | | - 当前标签只做轻微加权,不能变成过滤条件。 |
| | | - 冷启动分只在用户历史不足时明显生效。 |
| | | |
| | | ## 4. 用户故事 |
| | | |
| | | 1. 作为用户,我打开快速搜索后,即使不输入,也能看到几个可能想打开的应用。 |
| | | 2. 作为用户,我可以直接按 `Enter` 打开默认选中的第一个建议。 |
| | | 3. 作为用户,我可以用 `↑` / `↓` 在建议列表中移动选择。 |
| | | 4. 作为用户,我最近通过 TagLauncher 打开过的应用,会优先出现在建议里。 |
| | | 5. 作为用户,我经常打开的应用,即使今天还没打开,也有机会出现在建议里。 |
| | | 6. 作为用户,如果我从某个标签上下文里打开快速搜索,相关应用可以更容易出现,但快速建议仍然不局限于当前标签。 |
| | | 7. 作为新用户,我没有足够启动历史时,仍然能看到一组合理的常见应用建议。 |
| | | |
| | | ## 5. 入口行为 |
| | | |
| | | 当快速搜索被打开时: |
| | | |
| | | - 如果查询为空,显示快速建议。 |
| | | - 第一个建议项默认被选中。 |
| | | - 用户按 `Enter`,打开当前选中的建议应用。 |
| | | - 用户开始输入任意字符后,快速建议切换为搜索结果。 |
| | | - 用户删除所有输入,使查询再次为空时,重新显示快速建议。 |
| | | |
| | | 状态流: |
| | | |
| | | ```text |
| | | 打开快速搜索 |
| | | ↓ |
| | | 查询为空 |
| | | ↓ |
| | | 显示快速建议 |
| | | ↓ |
| | | 用户输入 |
| | | ↓ |
| | | 显示搜索结果 |
| | | ↓ |
| | | 用户清空输入 |
| | | ↓ |
| | | 重新显示快速建议 |
| | | ``` |
| | | |
| | | ## 6. 展示要求 |
| | | |
| | | 快速建议显示在快速搜索输入框下方。 |
| | | |
| | | 列表规则: |
| | | |
| | | - 不显示列表标题。 |
| | | - 最多显示 6 个建议。 |
| | | - 第一个建议默认选中。 |
| | | - 每个建议项高度稳定,不因备注长短变化而跳动。 |
| | | - 建议列表需要紧凑、可扫读、可键盘操作。 |
| | | - 不显示几十个应用。 |
| | | - 不把快速建议做成浏览页面。 |
| | | |
| | | 每个建议项至少包含: |
| | | |
| | | - 应用图标。 |
| | | - 应用名称。 |
| | | |
| | | 每个建议项推荐包含: |
| | | |
| | | - 一行应用备注。 |
| | | - 如果没有备注,则显示标签信息。 |
| | | |
| | | 展示优先级: |
| | | |
| | | ```text |
| | | 应用图标 + 应用名称 + 一行备注 |
| | | 应用图标 + 应用名称 + 标签信息 |
| | | 应用图标 + 应用名称 |
| | | ``` |
| | | |
| | | 如果没有任何可用建议: |
| | | |
| | | - 显示轻量空状态。 |
| | | - 输入框继续保持聚焦。 |
| | | - `Enter` 不执行任何操作。 |
| | | - 不显示错误态。 |
| | | |
| | | 空状态文案: |
| | | |
| | | ```text |
| | | 输入应用、标签或备注开始搜索 |
| | | ``` |
| | | |
| | | ## 7. 排序信号 |
| | | |
| | | ### 7.1 最近启动分 |
| | | |
| | | 最近启动是快速建议的第一优先级。 |
| | | |
| | | 数据来源: |
| | | |
| | | - 仅使用 TagLauncher 自己记录的启动历史。 |
| | | - 不读取 macOS 全局应用使用记录。 |
| | | - 不依赖系统隐私敏感数据。 |
| | | |
| | | 最近启动分规则: |
| | | |
| | | | 最近成功启动时间 | 分数 | |
| | | |---|---:| |
| | | | 10 分钟内 | 100 | |
| | | | 1 小时内 | 80 | |
| | | | 今天内 | 60 | |
| | | | 7 天内 | 40 | |
| | | | 30 天内 | 20 | |
| | | | 30 天以前或从未启动 | 0 | |
| | | |
| | | 规则说明: |
| | | |
| | | - 最近刚通过 TagLauncher 启动的应用应该明显靠前。 |
| | | - 同一个应用只出现一次。 |
| | | - 如果应用启动失败,不更新最近启动时间。 |
| | | |
| | | ### 7.2 高频启动分 |
| | | |
| | | 高频启动用于补充“最近启动”的不足。 |
| | | |
| | | 原因: |
| | | |
| | | - 用户每天都用的应用,即使今天还没打开,也应该有机会出现。 |
| | | - 只按最近启动排序会导致列表过于短期化。 |
| | | |
| | | 高频启动分规则: |
| | | |
| | | ```text |
| | | 高频启动分 = |
| | | min(过去 7 天成功启动次数 × 4, 24) |
| | | + min(过去 30 天成功启动次数 × 1, 20) |
| | | ``` |
| | | |
| | | 分数上限: |
| | | |
| | | ```text |
| | | 高频启动分最高 44 分 |
| | | ``` |
| | | |
| | | 规则说明: |
| | | |
| | | - 过去 7 天启动次数反映近期习惯。 |
| | | - 过去 30 天启动次数反映稳定习惯。 |
| | | - 高频分不能压过强最近分。 |
| | | - 如果应用启动失败,不增加启动次数。 |
| | | |
| | | ### 7.3 当前标签加权分 |
| | | |
| | | 如果用户是在主界面的某个标签上下文中打开快速搜索,则当前标签下的应用获得轻微加权。 |
| | | |
| | | 当前标签加权分: |
| | | |
| | | ```text |
| | | 属于当前标签:+12 分 |
| | | 不属于当前标签:+0 分 |
| | | ``` |
| | | |
| | | 重要规则: |
| | | |
| | | - 当前上下文只加权,不过滤。 |
| | | - 快速建议仍然可以显示其他标签下的应用。 |
| | | - 快速搜索始终是全局启动入口。 |
| | | |
| | | 错误行为: |
| | | |
| | | ```text |
| | | 当前标签是“设计”,所以快速建议只显示设计类应用。 |
| | | ``` |
| | | |
| | | 正确行为: |
| | | |
| | | ```text |
| | | 当前标签是“设计”,所以设计类应用获得 12 分加权。 |
| | | Chrome、Cursor、ChatGPT 等高意图应用仍然可以出现。 |
| | | ``` |
| | | |
| | | ### 7.4 冷启动分 |
| | | |
| | | 冷启动分只在冷启动模式下启用。 |
| | | |
| | | 冷启动触发条件: |
| | | |
| | | ```text |
| | | 通过 TagLauncher 成功启动应用的总次数少于 3 次 |
| | | 或 |
| | | 通过 TagLauncher 成功启动过的不同应用少于 3 个 |
| | | ``` |
| | | |
| | | 冷启动分类分: |
| | | |
| | | | Smart Start 分类 | 分数 | |
| | | |---|---:| |
| | | | 浏览器 | 50 | |
| | | | 沟通 | 45 | |
| | | | AI 工具 | 42 | |
| | | | 开发 | 40 | |
| | | | 效率 | 36 | |
| | | | 设计 | 32 | |
| | | | 系统工具 | 25 | |
| | | | 其他分类 | 0 | |
| | | |
| | | 规则说明: |
| | | |
| | | - 一个应用属于多个分类时,取最高分类分。 |
| | | - 冷启动分只用于历史不足的用户。 |
| | | - 当用户积累足够启动历史后,冷启动分不再参与排序。 |
| | | - 冷启动候选必须是本机已安装应用。 |
| | | - 冷启动不允许随机推荐。 |
| | | |
| | | ### 7.5 固定项加权入口 |
| | | |
| | | 7.5 不启用用户手动固定功能。 |
| | | |
| | | 实现上可以预留: |
| | | |
| | | ```text |
| | | 固定项加权分 = 0 |
| | | ``` |
| | | |
| | | 未来如果支持固定项,可以在不重写排序架构的情况下加入固定加权。 |
| | | |
| | | ## 8. 最终排序规则 |
| | | |
| | | 每个候选应用计算一次总分: |
| | | |
| | | ```text |
| | | 总分 = |
| | | 最近启动分 |
| | | + 高频启动分 |
| | | + 当前标签加权分 |
| | | + 冷启动分 |
| | | ``` |
| | | |
| | | 排序规则: |
| | | |
| | | 1. 总分高的排前面。 |
| | | 2. 总分相同时,最近启动时间更近的排前面。 |
| | | 3. 最近启动时间也相同时,过去 7 天启动次数更多的排前面。 |
| | | 4. 仍然相同时,应用名称按当前语言环境排序。 |
| | | |
| | | 候选去重规则: |
| | | |
| | | 1. 优先按 `bundleIdentifier` 去重。 |
| | | 2. 没有 `bundleIdentifier` 时按稳定应用标识去重。 |
| | | 3. 仍无法判断时按规范化后的应用名称兜底去重。 |
| | | |
| | | 数量规则: |
| | | |
| | | ```text |
| | | 排序后取前 6 个。 |
| | | ``` |
| | | |
| | | ## 9. 排序例子 |
| | | |
| | | ### 9.1 普通用户 |
| | | |
| | | 用户最近通过 TagLauncher 打开过: |
| | | |
| | | ```text |
| | | Cursor |
| | | Chrome |
| | | Figma |
| | | ChatGPT |
| | | ``` |
| | | |
| | | 用户过去 30 天高频打开: |
| | | |
| | | ```text |
| | | Chrome |
| | | Notion |
| | | WeChat |
| | | Finder |
| | | ``` |
| | | |
| | | 快速建议可能显示: |
| | | |
| | | ```text |
| | | Cursor |
| | | Chrome |
| | | ChatGPT |
| | | Figma |
| | | Notion |
| | | WeChat |
| | | ``` |
| | | |
| | | ### 9.2 当前标签是设计 |
| | | |
| | | 当前主界面标签是: |
| | | |
| | | ```text |
| | | 设计 |
| | | ``` |
| | | |
| | | 最近启动: |
| | | |
| | | ```text |
| | | Chrome |
| | | Cursor |
| | | ChatGPT |
| | | ``` |
| | | |
| | | 设计标签下高相关应用: |
| | | |
| | | ```text |
| | | Figma |
| | | Photoshop |
| | | Sketch |
| | | ``` |
| | | |
| | | 快速建议可能显示: |
| | | |
| | | ```text |
| | | Chrome |
| | | Cursor |
| | | Figma |
| | | ChatGPT |
| | | Photoshop |
| | | ``` |
| | | |
| | | 说明: |
| | | |
| | | - 设计类应用获得 12 分加权。 |
| | | - 列表没有被设计标签过滤。 |
| | | |
| | | ### 9.3 新用户 |
| | | |
| | | 用户没有足够启动历史。 |
| | | |
| | | 本机已安装: |
| | | |
| | | ```text |
| | | Finder |
| | | Safari |
| | | Chrome |
| | | WeChat |
| | | Cursor |
| | | Figma |
| | | Notion |
| | | ``` |
| | | |
| | | 快速建议可能显示: |
| | | |
| | | ```text |
| | | Chrome |
| | | Safari |
| | | WeChat |
| | | Cursor |
| | | Notion |
| | | Figma |
| | | ``` |
| | | |
| | | 说明: |
| | | |
| | | - 使用 Smart Start 高价值分类产生冷启动建议。 |
| | | - 不显示完整应用列表。 |
| | | - 不随机推荐。 |
| | | |
| | | ## 10. 数据要求 |
| | | |
| | | 快速建议需要以下本地数据: |
| | | |
| | | | 字段 | 是否必须 | 说明 | |
| | | |---|---|---| |
| | | | 应用稳定标识 | 必须 | 本地稳定身份 | |
| | | | 包标识 | 推荐 | 用于去重和应用身份识别 | |
| | | | 应用名称 | 必须 | 用于展示和兜底排序 | |
| | | | 应用图标 | 必须 | 用于展示 | |
| | | | 标签标识 / 标签名称 | 必须 | 用于当前标签加权和展示 | |
| | | | 应用备注 | 可选 | 用于展示一行备注 | |
| | | | 最近成功启动时间 | 必须 | 用于最近启动分 | |
| | | | 过去 7 天成功启动次数 | 推荐 | 用于高频启动分 | |
| | | | 过去 30 天成功启动次数 | 推荐 | 用于高频启动分 | |
| | | | 总成功启动次数 | 推荐 | 用于判断历史是否充足 | |
| | | | 成功启动过的不同应用数量 | 推荐 | 用于判断历史是否充足 | |
| | | | 是否固定 | 预留 | 7.5 不暴露用户操作 | |
| | | | Smart Start 分类 | 推荐 | 用于冷启动分 | |
| | | |
| | | 启动历史记录要求: |
| | | |
| | | - 应用通过 TagLauncher 成功启动后,记录启动时间。 |
| | | - 应用通过 TagLauncher 成功启动后,增加启动次数。 |
| | | - 应用启动失败时,不更新最近启动时间,不增加启动次数。 |
| | | - 数据存储在本地。 |
| | | |
| | | ## 11. 隐私要求 |
| | | |
| | | 快速建议必须是本地优先能力。 |
| | | |
| | | 要求: |
| | | |
| | | - 不上传应用启动历史。 |
| | | - 不上传快速搜索输入内容。 |
| | | - 7.5 不读取 macOS 全局应用使用历史。 |
| | | - 仅使用 TagLauncher 自己记录的启动历史和本地应用元数据。 |
| | | - 排序数据存储在本地。 |
| | | |
| | | 这点很重要,因为快速建议可能反映用户的使用习惯。 |
| | | |
| | | ## 12. 刷新规则 |
| | | |
| | | 快速建议应该在以下时机重新计算: |
| | | |
| | | - 快速搜索打开时。 |
| | | - 应用通过 TagLauncher 成功启动后。 |
| | | - 应用目录发生变化时。 |
| | | - 应用标签发生变化时。 |
| | | - 应用备注发生变化时。 |
| | | - 用户在打开快速搜索前切换了当前标签。 |
| | | |
| | | 当快速搜索已经打开且查询为空时: |
| | | |
| | | - 本次打开会话中的建议列表保持稳定。 |
| | | - 用户正在用键盘导航时,不因为后台数据变化而重新排序。 |
| | | - 避免用户准备按 `Enter` 时选中项突然移动。 |
| | | |
| | | ## 13. 键盘和选择行为 |
| | | |
| | | 要求: |
| | | |
| | | - 第一个建议默认选中。 |
| | | - `Enter` 打开选中的建议应用。 |
| | | - `↑` 和 `↓` 移动选择。 |
| | | - 鼠标悬停可以更新视觉高亮。 |
| | | - 鼠标点击打开建议应用。 |
| | | - 用户输入任意字符后切换到搜索结果。 |
| | | |
| | | 如果建议为空: |
| | | |
| | | - `Enter` 不执行任何操作。 |
| | | - 输入框保持聚焦。 |
| | | |
| | | ## 14. 边界情况 |
| | | |
| | | ### 14.1 没有启动历史 |
| | | |
| | | 进入冷启动模式,使用 Smart Start 高价值分类生成建议。 |
| | | |
| | | ### 14.2 建议不足 6 个 |
| | | |
| | | 如果排序结果少于 6 个: |
| | | |
| | | 1. 先补充冷启动候选。 |
| | | 2. 再补充本机已安装的常见高价值应用。 |
| | | 3. 最后按应用名称排序兜底。 |
| | | |
| | | 不允许使用随机应用补齐。 |
| | | |
| | | ### 14.3 应用已被移除 |
| | | |
| | | 如果历史中的应用已经不在本机可启动应用列表中: |
| | | |
| | | - 不显示为可启动建议。 |
| | | - 是否保留历史数据,遵循现有应用历史数据策略。 |
| | | |
| | | ### 14.4 重复应用记录 |
| | | |
| | | 重复应用只显示一次。 |
| | | |
| | | 去重优先级: |
| | | |
| | | 1. 包标识。 |
| | | 2. 稳定应用标识。 |
| | | 3. 规范化应用名称。 |
| | | |
| | | ### 14.5 用户正在其他输入框编辑文本 |
| | | |
| | | 快速建议只在快速搜索被明确打开后显示。 |
| | | |
| | | 如果用户正在其他输入框中输入空格,不应触发快速搜索,也不应显示快速建议。 |
| | | |
| | | ## 15. 非目标 |
| | | |
| | | 7.5 不做以下内容: |
| | | |
| | | - 读取 macOS 屏幕使用时间或系统级应用使用历史。 |
| | | - 云端排序。 |
| | | - AI 生成建议。 |
| | | - 跨设备同步启动历史。 |
| | | - 用户手动固定建议项。 |
| | | - 完整命令面板推荐。 |
| | | - 文件、联系人、浏览器历史或网页建议。 |
| | | - 按窗口高度动态改变建议数量。 |
| | | |
| | | ## 16. 验收标准 |
| | | |
| | | 快速建议行为: |
| | | |
| | | - 打开快速搜索且查询为空时,显示快速建议。 |
| | | - 快速建议最多显示 6 个应用。 |
| | | - 快速建议不显示列表标题。 |
| | | - 快速建议不显示完整应用目录。 |
| | | - 第一个建议默认选中。 |
| | | - 按 `Enter` 打开选中的建议应用。 |
| | | - 按 `↑` / `↓` 改变选中项。 |
| | | - 输入任意字符后,从快速建议切换到搜索结果。 |
| | | - 清空输入后,重新显示快速建议。 |
| | | |
| | | 展示: |
| | | |
| | | - 每个建议项显示应用图标和应用名称。 |
| | | - 有备注时显示一行备注。 |
| | | - 无备注但有标签时显示标签信息。 |
| | | - 备注过长时只显示一行,不撑高列表。 |
| | | |
| | | 排序: |
| | | |
| | | - 最近启动的应用在正常情况下优先出现。 |
| | | - 高频应用即使今天没打开,也有机会出现。 |
| | | - 当前标签相关应用获得 12 分加权。 |
| | | - 当前标签加权不能把列表过滤成当前标签内应用。 |
| | | - 冷启动用户看到基于 Smart Start 高价值分类的合理建议。 |
| | | - 重复应用不会出现两次。 |
| | | - 建议不足 6 个时,不使用随机应用补齐。 |
| | | |
| | | 隐私: |
| | | |
| | | - 建议在本地生成。 |
| | | - 搜索输入不上传。 |
| | | - 启动历史不上传。 |
| | | - 7.5 不读取 macOS 全局应用使用历史。 |
| | | |
| | | 稳定性: |
| | | |
| | | - 用户在空查询建议列表中导航时,列表不应突然重新排序。 |
| | | - 已移除应用不显示为可启动建议。 |
| | | - 应用成功启动后才更新启动时间和启动次数。 |
| | | |
| | | ## 17. 测试用例 |
| | | |
| | | 1. 打开快速搜索且不输入内容,确认快速建议可见。 |
| | | 2. 确认列表最多显示 6 个应用。 |
| | | 3. 确认列表上方不显示“快速建议”“最近使用”等标题。 |
| | | 4. 确认第一个建议默认选中。 |
| | | 5. 按 `Enter`,确认选中的应用被打开。 |
| | | 6. 按 `↓` 后再按 `Enter`,确认第二个建议被打开。 |
| | | 7. 输入一个字符,确认界面切换为搜索结果。 |
| | | 8. 删除输入内容,确认界面回到快速建议。 |
| | | 9. 通过 TagLauncher 成功打开一个应用后,再次打开快速搜索,确认该应用获得最近启动优先级。 |
| | | 10. 构造一个过去 7 天和 30 天的高频应用,确认它可以进入快速建议。 |
| | | 11. 从某个标签上下文打开快速搜索,确认该标签下应用获得加权,但列表没有被过滤到该标签。 |
| | | 12. 使用全新用户状态,确认冷启动建议来自本机已安装的高价值分类应用。 |
| | | 13. 移除或卸载一个曾经启动过的应用,确认它不再作为可启动建议出现。 |
| | | 14. 确认快速建议展示时不会产生网络请求。 |
| | | 15. 应用启动失败时,确认不更新最近启动时间和启动次数。 |
| | | |
| | | ## 18. 发布原则 |
| | | |
| | | 快速建议第一版不需要复杂,但必须稳定、直觉、可解释。 |
| | | |
| | | 它应该让用户在打开快速搜索的第一眼就感觉: |
| | | |
| | | ```text |
| | | 这些就是我大概率现在要打开的应用。 |
| | | ``` |
| | | |
| | | 快速搜索负责输入后的搜索命中。 |
| | | |
| | | 快速建议负责输入前的启动预测。 |
| | | |
| New file |
| | |
| | | # TagLauncher 7.5 PRD: Quick Search |
| | | |
| | | Status: Draft for product and architecture review |
| | | Owner: Product Manager / Architect |
| | | Feature: Quick Search, search overlay, custom global shortcuts |
| | | Version: 7.5 |
| | | |
| | | ## Product Goal |
| | | |
| | | TagLauncher 7.5 should add a fast, keyboard-first Quick Search experience that lets users launch apps through muscle memory. |
| | | |
| | | The main TagLauncher interface remains the place for browsing, organizing, tagging, and managing apps. Quick Search is a second launch entry: it is optimized for users who already have an intent and want to type a few characters, select the right app, and press Enter. |
| | | |
| | | The feature must feel close to macOS Spotlight and Raycast in speed and clarity, while preserving TagLauncher's identity around app tags and app notes. |
| | | |
| | | ## Product Positioning |
| | | |
| | | TagLauncher has two complementary entry modes: |
| | | |
| | | | Mode | User intent | Primary behavior | |
| | | |---|---|---| |
| | | | Main interface | Browse, organize, manage, understand app groups | Show tags, app list, notes, and management affordances | |
| | | | Quick Search | Quickly locate and launch an app | Search across all apps by app name, tag name, and app note | |
| | | |
| | | Quick Search must not be implemented as a simple filter inside the current app list. It must search across all available apps, regardless of which tag or view the main interface is currently showing. |
| | | |
| | | Example: |
| | | |
| | | - If the main interface is currently showing only the `Design` tag, searching `chrome` in Quick Search should still find Google Chrome. |
| | | - If the user searches a tag name such as `AI`, Quick Search should return apps associated with that tag. |
| | | - If the user searches a word that appears only in an app note, Quick Search should still be able to surface that app. |
| | | |
| | | ## Background |
| | | |
| | | The current main interface shortcut is: |
| | | |
| | | ```text |
| | | Shift + Option + Space |
| | | ⇧ ⌥ Space |
| | | ``` |
| | | |
| | | This shortcut is reasonable for opening the full TagLauncher interface because it avoids the most common macOS system conflicts and avoids the increasingly crowded `Option + Space` shortcut used by AI tools and launchers. |
| | | |
| | | However, fast app launching benefits from an even lighter interaction once TagLauncher is visible. The proposed 7.5 interaction is: |
| | | |
| | | ```text |
| | | ⇧ ⌥ Space |
| | | Open TagLauncher |
| | | |
| | | Space |
| | | Open Quick Search overlay |
| | | |
| | | Type |
| | | Search and rank apps in real time |
| | | |
| | | Enter |
| | | Open selected app |
| | | ``` |
| | | |
| | | Users who want TagLauncher to become their first launcher should be able to configure a direct global Quick Search shortcut in Settings, including `⌥ Space` or `⌘ Space`, with clear conflict detection and resolution guidance. |
| | | |
| | | ## Shortcut Strategy |
| | | |
| | | The product principle is: |
| | | |
| | | ```text |
| | | Default: avoid conflict. |
| | | Settings: let advanced users choose a stronger shortcut. |
| | | ``` |
| | | |
| | | Default behavior: |
| | | |
| | | | Shortcut | Behavior | Default status | |
| | | |---|---|---| |
| | | | `⇧ ⌥ Space` | Open main TagLauncher interface | Enabled | |
| | | | `Space` while TagLauncher is visible | Open Quick Search overlay | Enabled | |
| | | | Direct global Quick Search shortcut | Open Quick Search directly | Not enabled by default | |
| | | |
| | | Recommended optional shortcuts shown in Settings: |
| | | |
| | | | Shortcut | Meaning | Product guidance | |
| | | |---|---|---| |
| | | | `⌥ Space` | Launcher-style quick entry | Fast and familiar, but may conflict with ChatGPT, Raycast, Alfred, or other tools | |
| | | | `⌘ Space` | Replace Spotlight | Powerful for advanced users, but conflicts with macOS Spotlight unless the system shortcut is changed | |
| | | | Custom shortcut | User-defined | Recommended when the user already has many AI or launcher tools installed | |
| | | |
| | | ## Core User Stories |
| | | |
| | | 1. As a user, I can open TagLauncher with `⇧ ⌥ Space`, press `Space`, type a few letters, and launch the selected app with `Enter`. |
| | | 2. As a user, I can search by app name, tag name, or app note. |
| | | 3. As a user, I can type partial or non-contiguous letters and still get useful results. |
| | | 4. As a user, I can use arrow keys to select a result and press `Enter` to open it. |
| | | 5. As a user, I can click a search result to open it. |
| | | 6. As a user, I can press `Esc` to close Quick Search without closing the main interface. |
| | | 7. As an advanced user, I can assign a direct global shortcut to Quick Search. |
| | | 8. As a user, if my chosen shortcut conflicts with macOS or another app, I get a clear explanation and a practical next step. |
| | | |
| | | ## Interaction Requirements |
| | | |
| | | ### Opening Quick Search |
| | | |
| | | When TagLauncher is visible and no text input field is focused: |
| | | |
| | | - Pressing `Space` opens Quick Search. |
| | | - The Quick Search input is focused immediately. |
| | | - The cursor is visible in the input field. |
| | | - The app list behind the overlay must not be reflowed or resized. |
| | | |
| | | If the main interface is hidden: |
| | | |
| | | - Pressing `⇧ ⌥ Space` opens the main interface. |
| | | - If the user has configured and successfully enabled a direct Quick Search global shortcut, pressing that shortcut opens Quick Search directly. |
| | | |
| | | ### Search Overlay |
| | | |
| | | Quick Search should appear as a floating overlay above the existing app list. |
| | | |
| | | Visual direction: |
| | | |
| | | - Spotlight-like search field. |
| | | - Pure black or near-black background. |
| | | - White input text. |
| | | - Minimal border or shadow for separation. |
| | | - Large, clear input typography. |
| | | - Positioned near the top center of the TagLauncher window. |
| | | - High z-index above the app list. |
| | | - Does not push, resize, or rearrange the main app list. |
| | | |
| | | Recommended layout: |
| | | |
| | | ```text |
| | | ┌──────────────────────────────────────────────┐ |
| | | │ Search apps, tags, notes... │ |
| | | └──────────────────────────────────────────────┘ |
| | | |
| | | ┌──────────────────────────────────────────────┐ |
| | | │ App icon App name Tags │ |
| | | │ matched note snippet │ |
| | | ├──────────────────────────────────────────────┤ |
| | | │ App icon App name Tags │ |
| | | │ matched note snippet │ |
| | | └──────────────────────────────────────────────┘ |
| | | ``` |
| | | |
| | | The result list can appear directly below the search field in the same overlay layer. |
| | | |
| | | ### Empty Query State |
| | | |
| | | When Quick Search opens with an empty query: |
| | | |
| | | - Show a small list of recent or frequently opened apps. |
| | | - Select the first item by default if results exist. |
| | | - Do not show the full app catalog as a giant list. |
| | | |
| | | This makes the overlay immediately useful even before typing. |
| | | |
| | | ### Typing and Matching |
| | | |
| | | While the user types: |
| | | |
| | | - Results update in real time. |
| | | - Matching should feel instant. |
| | | - The current selection should default to the top-ranked result. |
| | | - If the current selected app remains in the result list after typing, preserve the selection when reasonable. |
| | | - If the selected app disappears, select the top result. |
| | | |
| | | ### Keyboard Navigation |
| | | |
| | | Required keys: |
| | | |
| | | | Key | Behavior | |
| | | |---|---| |
| | | | `↑` | Move selection to previous result | |
| | | | `↓` | Move selection to next result | |
| | | | `Enter` | Open selected result | |
| | | | `Esc` | Close Quick Search | |
| | | | `Space` inside the input | Insert a space character | |
| | | |
| | | Escape behavior: |
| | | |
| | | - If Quick Search is open, `Esc` closes Quick Search and returns to the main interface. |
| | | - If Quick Search is closed and the main interface is visible, existing main interface close behavior may continue to apply. |
| | | |
| | | ### Mouse Interaction |
| | | |
| | | Required behavior: |
| | | |
| | | - Hovering a result highlights it. |
| | | - Clicking a result opens the app. |
| | | - Clicking outside the overlay closes Quick Search only if this matches the existing main interface behavior. If the existing product does not use outside-click dismissal, keep behavior consistent. |
| | | |
| | | ## Search Scope |
| | | |
| | | Quick Search searches all launchable apps known to TagLauncher. |
| | | |
| | | Required searchable fields: |
| | | |
| | | | Field | Requirement | Weight | |
| | | |---|---|---| |
| | | | App display name | Required | Highest | |
| | | | App localized name, if available | Required when available | Highest | |
| | | | Tag names | Required | Medium-high | |
| | | | App note / remark | Required | Medium | |
| | | | Bundle identifier | Optional, lower priority | Low | |
| | | |
| | | Future searchable fields: |
| | | |
| | | - User-defined aliases. |
| | | - Pinyin or initials for Chinese app names and notes. |
| | | - Recent command history. |
| | | - TagLauncher actions such as settings or tag management commands. |
| | | |
| | | These future fields must not block the 7.5 release. |
| | | |
| | | ## Fuzzy Search Requirements |
| | | |
| | | The word "fuzzy" has two meanings in this PRD. |
| | | |
| | | First, search must cover multiple fields: |
| | | |
| | | - App names. |
| | | - Tag names. |
| | | - App notes. |
| | | |
| | | Second, character matching does not require a strict full prefix match. |
| | | |
| | | Required match types: |
| | | |
| | | | Match type | Example | |
| | | |---|---| |
| | | | Exact match | `Figma` finds `Figma` | |
| | | | Prefix match | `fig` finds `Figma` | |
| | | | Substring match | `shop` finds `Photoshop` | |
| | | | Acronym match | `gc` finds `Google Chrome` | |
| | | | Subsequence match | `ps` finds `Photoshop` | |
| | | | Case-insensitive match | `chrome`, `Chrome`, and `CHROME` can all find `Google Chrome` | |
| | | |
| | | For Chinese text: |
| | | |
| | | - Direct Chinese character matching is required. |
| | | - Mixed Chinese and Latin text should be searchable when present in app names, tags, or notes. |
| | | - Pinyin matching is not required for 7.5, but the search index should not make it hard to add later. |
| | | |
| | | ## Ranking Requirements |
| | | |
| | | Search ranking should optimize for launching the intended app with as few keystrokes as possible. |
| | | |
| | | Recommended scoring model: |
| | | |
| | | ```text |
| | | finalScore = |
| | | textMatchScore |
| | | + fieldWeight |
| | | + recentOpenBoost |
| | | + frequencyBoost |
| | | ``` |
| | | |
| | | Field weights: |
| | | |
| | | | Field | Ranking rule | |
| | | |---|---| |
| | | | App name | Strongest signal | |
| | | | App localized name | Strongest signal | |
| | | | Tag name | Strong signal | |
| | | | App note | Useful supporting signal | |
| | | | Bundle identifier | Weak supporting signal | |
| | | |
| | | Text match priority: |
| | | |
| | | ```text |
| | | exact match |
| | | prefix match |
| | | substring match |
| | | acronym match |
| | | subsequence match |
| | | ``` |
| | | |
| | | Behavioral boosts: |
| | | |
| | | - Apps opened recently should receive a small boost. |
| | | - Apps opened frequently should receive a small boost. |
| | | - Behavioral boosts must not completely overpower strong text matches. |
| | | |
| | | Example: |
| | | |
| | | - Searching `fi` should rank `Figma` above an app whose note merely contains `file`. |
| | | - Searching `ai` may rank a frequently used AI app above a rarely used app with a weak note match. |
| | | |
| | | ## Result Row Requirements |
| | | |
| | | Each result row should include: |
| | | |
| | | - App icon. |
| | | - App display name. |
| | | - Matched tags, if relevant. |
| | | - Note snippet, if the note contributed to the match. |
| | | - Visual selected state. |
| | | |
| | | Optional but recommended: |
| | | |
| | | - Highlight the matched part of app names, tags, or notes. |
| | | - Show a small secondary label such as bundle name only when useful. |
| | | |
| | | The row must remain compact and scannable. Quick Search is not a detail view. |
| | | |
| | | ## Launch Behavior |
| | | |
| | | When the user presses `Enter` or clicks a result: |
| | | |
| | | 1. Launch the selected app. |
| | | 2. Close Quick Search. |
| | | 3. Close or hide the main interface according to existing TagLauncher launch behavior. |
| | | 4. Update recent-open and open-count data if TagLauncher already tracks this, or add the minimum local tracking needed for ranking. |
| | | |
| | | If app launch fails: |
| | | |
| | | - Keep Quick Search open or return to the main interface. |
| | | - Show a short, clear error message. |
| | | - Do not lose the user's query immediately. |
| | | |
| | | ## Custom Shortcut Settings |
| | | |
| | | Settings must expose shortcut configuration for: |
| | | |
| | | | Setting | Default | |
| | | |---|---| |
| | | | Main interface shortcut | `⇧ ⌥ Space` | |
| | | | Direct Quick Search shortcut | Disabled / unset | |
| | | |
| | | The shortcut recording UI must: |
| | | |
| | | - Let users record a new shortcut. |
| | | - Let users clear a shortcut. |
| | | - Let users restore the default main interface shortcut. |
| | | - Show whether the shortcut is active. |
| | | - Detect conflicts before presenting a shortcut as successfully enabled. |
| | | |
| | | Recommended UI states: |
| | | |
| | | | State | Meaning | |
| | | |---|---| |
| | | | Active | Shortcut was registered successfully | |
| | | | Conflict | Shortcut is already used by macOS or another app | |
| | | | Pending | User chose the shortcut, but it cannot currently be activated | |
| | | | Disabled | No shortcut is assigned | |
| | | |
| | | ## Shortcut Conflict Detection |
| | | |
| | | When a user records or saves a shortcut, TagLauncher must attempt to register it immediately. |
| | | |
| | | If registration succeeds: |
| | | |
| | | - Save the shortcut. |
| | | - Show it as active. |
| | | - The shortcut should work immediately without restarting the app. |
| | | |
| | | If registration fails: |
| | | |
| | | - Do not silently accept the shortcut as active. |
| | | - Show a clear conflict state. |
| | | - Explain the likely reason. |
| | | - Offer a practical resolution path. |
| | | |
| | | Known macOS conflicts that should receive special copy: |
| | | |
| | | | Shortcut | Default macOS use | |
| | | |---|---| |
| | | | `⌘ Space` | Spotlight | |
| | | | `⌥ ⌘ Space` | Finder search window | |
| | | | `⌃ Space` | Previous input source | |
| | | | `⌃ ⌥ Space` | Next input source | |
| | | | `⌃ ⌘ Space` | Emoji and symbols | |
| | | |
| | | For unknown conflicts: |
| | | |
| | | ```text |
| | | This shortcut is already used by macOS or another app. |
| | | Choose another shortcut, or change the shortcut in the other app and try again. |
| | | ``` |
| | | |
| | | For `⌘ Space`: |
| | | |
| | | ```text |
| | | ⌘ Space is currently used by macOS Spotlight. TagLauncher cannot use it at the same time. |
| | | |
| | | To use ⌘ Space for TagLauncher: |
| | | 1. Open System Settings > Keyboard > Keyboard Shortcuts > Spotlight. |
| | | 2. Turn off or change "Show Spotlight search". |
| | | 3. Return to TagLauncher and click Retry. |
| | | ``` |
| | | |
| | | Required actions: |
| | | |
| | | - Choose another shortcut. |
| | | - Retry. |
| | | - Open system shortcut settings when possible. |
| | | |
| | | Important implementation rule: |
| | | |
| | | - TagLauncher should not use low-level keyboard interception to forcibly steal system shortcuts. |
| | | - The product should prefer transparent registration, clear status, and user-controlled resolution. |
| | | |
| | | ## Data and Architecture Requirements |
| | | |
| | | Quick Search should be implemented as a separate search capability, not as logic embedded inside the app list UI. |
| | | |
| | | Recommended module boundaries: |
| | | |
| | | ```text |
| | | App data / Tag data / Note data |
| | | ↓ |
| | | SearchIndexService |
| | | ↓ |
| | | SearchController |
| | | ↓ |
| | | QuickSearchOverlay UI |
| | | ↓ |
| | | Launch action |
| | | ``` |
| | | |
| | | Responsibilities: |
| | | |
| | | | Module | Responsibility | |
| | | |---|---| |
| | | | SearchIndexService | Build and refresh searchable documents | |
| | | | SearchController | Manage query, result ranking, selected index, keyboard navigation | |
| | | | QuickSearchOverlay UI | Render input, results, selected state, empty state | |
| | | | ShortcutSettings | Record shortcuts, persist settings, show status | |
| | | | ShortcutRegistration | Register global shortcuts and return success or conflict state | |
| | | |
| | | Searchable document shape: |
| | | |
| | | ```text |
| | | appId |
| | | bundleIdentifier |
| | | displayName |
| | | localizedNames |
| | | tagNames |
| | | note |
| | | aliases |
| | | lastOpenedAt |
| | | openCount |
| | | ``` |
| | | |
| | | Index refresh triggers: |
| | | |
| | | - App catalog changes. |
| | | - Tag assignment changes. |
| | | - Tag rename. |
| | | - App note changes. |
| | | - App install or removal scan. |
| | | - Locale or display language change, if localized tag names or app names are used. |
| | | |
| | | ## Performance Requirements |
| | | |
| | | Quick Search must feel instant for normal local app catalogs. |
| | | |
| | | Required: |
| | | |
| | | - Opening the overlay should feel immediate. |
| | | - Typing should update visible results without noticeable lag. |
| | | - Search should run locally. |
| | | - No network request is required for search. |
| | | - The index may be kept in memory while TagLauncher is running. |
| | | |
| | | Target: |
| | | |
| | | - Result update within 50 ms for typical user catalogs. |
| | | - Search should remain smooth for at least 1,000 local app records. |
| | | |
| | | ## Privacy Requirements |
| | | |
| | | Quick Search operates on local app metadata, user tags, and user notes. |
| | | |
| | | Required: |
| | | |
| | | - Do not send search queries to a server. |
| | | - Do not send app notes to a server. |
| | | - Store shortcut settings locally. |
| | | - Store recent-open and open-count data locally if used for ranking. |
| | | |
| | | ## Accessibility and Localization |
| | | |
| | | Accessibility requirements: |
| | | |
| | | - Full keyboard operation is required. |
| | | - The input field must have an accessible label. |
| | | - Result rows must expose app name and relevant metadata to accessibility APIs where supported. |
| | | - Selected state must be visually clear. |
| | | |
| | | Localization requirements: |
| | | |
| | | - All user-facing strings in the overlay and settings must be localizable. |
| | | - Shortcut conflict guidance must be localized. |
| | | - Search should use localized tag names where the current app language provides them. |
| | | |
| | | ## Non-Goals for 7.5 |
| | | |
| | | The following are not required for 7.5: |
| | | |
| | | - Searching files, folders, contacts, browser history, or web results. |
| | | - Building a full command palette. |
| | | - AI-generated results or remote ranking. |
| | | - Pinyin search. |
| | | - Replacing Spotlight by default. |
| | | - Taking over `⌥ Space` by default. |
| | | - Forcibly intercepting system shortcuts through low-level keyboard event hooks. |
| | | |
| | | ## Acceptance Criteria |
| | | |
| | | Quick Search overlay: |
| | | |
| | | - `⇧ ⌥ Space` opens the main TagLauncher interface. |
| | | - Pressing `Space` while the main interface is visible and no text field is focused opens Quick Search. |
| | | - Quick Search appears as a floating overlay and does not reflow the app list. |
| | | - The search input is focused immediately. |
| | | - `Esc` closes Quick Search. |
| | | - `Enter` opens the selected app. |
| | | - `↑` and `↓` move through results. |
| | | - Clicking a result opens the app. |
| | | |
| | | Search behavior: |
| | | |
| | | - Search covers all apps known to TagLauncher, not only the currently visible tag or list. |
| | | - App name search works. |
| | | - Tag name search works. |
| | | - App note search works. |
| | | - Prefix, substring, acronym, and subsequence matches work. |
| | | - Matching is case-insensitive for Latin text. |
| | | - Direct Chinese character matching works. |
| | | - Empty query shows recent or frequently opened apps instead of the full catalog. |
| | | - No-result state is clear and does not look broken. |
| | | |
| | | Ranking: |
| | | |
| | | - App name matches outrank note-only matches when the query strength is comparable. |
| | | - Recent and frequent apps receive a modest boost. |
| | | - Strong textual relevance remains the dominant ranking factor. |
| | | |
| | | Shortcut settings: |
| | | |
| | | - Main interface shortcut is configurable. |
| | | - Direct Quick Search shortcut is configurable. |
| | | - Direct Quick Search shortcut is disabled or unset by default. |
| | | - Shortcut changes apply without restarting the app. |
| | | - Shortcut settings persist across app relaunch. |
| | | - Conflicting shortcuts are not shown as active. |
| | | - `⌘ Space` shows Spotlight-specific conflict guidance when registration fails. |
| | | - Unknown conflicts show generic conflict guidance. |
| | | - The user can retry after resolving a conflict. |
| | | - The user can choose another shortcut. |
| | | |
| | | Privacy and performance: |
| | | |
| | | - Search works offline. |
| | | - Search queries are not sent to any server. |
| | | - Result updates feel immediate on a normal local app catalog. |
| | | |
| | | ## QA Test Cases |
| | | |
| | | Required manual QA scenarios: |
| | | |
| | | 1. Open main interface with `⇧ ⌥ Space`, press `Space`, verify Quick Search opens and input is focused. |
| | | 2. Search by app name and launch the app with `Enter`. |
| | | 3. Search by tag name and verify matching apps appear. |
| | | 4. Search by app note and verify matching apps appear. |
| | | 5. Search with non-prefix input such as `ps` for `Photoshop` and verify the app can be found. |
| | | 6. Use `↑` and `↓` to change selection, then press `Enter`. |
| | | 7. Open Quick Search, type a query, press `Esc`, verify the main interface remains visible. |
| | | 8. Configure a direct Quick Search shortcut that is available, verify it works immediately. |
| | | 9. Try to configure `⌘ Space` while Spotlight still owns it, verify conflict status and guidance. |
| | | 10. Resolve or change the conflicting shortcut, click Retry, verify the status updates. |
| | | 11. Relaunch TagLauncher and verify shortcut settings persist. |
| | | 12. Confirm Quick Search does not send network requests during typing. |
| | | |
| | | ## Open Product Questions |
| | | |
| | | 1. Should direct Quick Search remain disabled by default, or should onboarding offer a guided choice during first run? |
| | | 2. Should the empty query state prioritize recent apps, frequent apps, or a blend of both? |
| | | 3. Should Quick Search always close the main interface after launching an app, or follow the current main interface behavior exactly? |
| | | 4. Should app note snippets be visible by default in result rows, or only when the note field is the reason for the match? |
| | | |
| | | ## Release Principle |
| | | |
| | | 7.5 should make Quick Search feel like a native, reliable second launch path: |
| | | |
| | | ```text |
| | | Open. |
| | | Type. |
| | | Select. |
| | | Launch. |
| | | ``` |
| | | |
| | | The feature should avoid shortcut fights by default, but give advanced users enough control to make TagLauncher their primary launcher when they choose to do so. |
| New file |
| | |
| | | # TagLauncher 7.5 PRD: Quick Search |
| | | |
| | | Status: PMD rewrite for product and architecture review |
| | | Owner: Product Manager |
| | | Feature: Quick Search, search overlay, configurable global shortcuts |
| | | Version: 7.5 |
| | | |
| | | ## Goal |
| | | |
| | | TagLauncher 7.5 adds a keyboard-first Quick Search entry for users who already know what they want to launch. |
| | | |
| | | Quick Search is not a filter for the currently visible app list. It searches all launchable apps known to TagLauncher across app names, tag names, and app notes. |
| | | |
| | | Default launch path: |
| | | |
| | | ```text |
| | | Shift + Option + Space -> open main TagLauncher interface |
| | | Space -> open Quick Search |
| | | Type -> search and rank apps |
| | | Enter -> launch selected app |
| | | ``` |
| | | |
| | | Advanced users can configure a direct global Quick Search shortcut. This shortcut is disabled by default. |
| | | |
| | | ## Product Decisions |
| | | |
| | | | Topic | Decision | |
| | | |---|---| |
| | | | Default global shortcut | Keep `Shift + Option + Space` for the main interface | |
| | | | Direct Quick Search shortcut | Configurable, but disabled by default | |
| | | | `Space` behavior | Opens Quick Search only when the main interface is visible and normal typing/control interaction is not active | |
| | | | Search scope | All launchable apps, not only the current tag or current visible list | |
| | | | Empty query | Show recent apps first, then frequent apps to fill remaining slots | |
| | | | Launch success | Close Quick Search, then follow existing TagLauncher launch-window behavior | |
| | | | Launch failure | Keep the query and show a short error | |
| | | | Shortcut conflicts | Use normal shortcut registration; do not forcibly intercept system shortcuts | |
| | | | Privacy | Search and ranking data stay local | |
| | | |
| | | ## Scope |
| | | |
| | | Required for 7.5: |
| | | |
| | | - Quick Search overlay opened from the main interface with `Space`. |
| | | - Direct global Quick Search shortcut in Settings, disabled by default. |
| | | - Search across app display name, localized app name, tag name, and app note. |
| | | - Exact, prefix, substring, acronym, subsequence, and case-insensitive Latin matching. |
| | | - Direct Chinese character matching. |
| | | - Keyboard navigation and mouse launch. |
| | | - Recent and frequent app ranking boosts. |
| | | - Local persistence for shortcut settings and launch ranking data. |
| | | - Shortcut conflict detection through registration success or failure. |
| | | |
| | | Not required for 7.5: |
| | | |
| | | - File, folder, contact, browser history, or web search. |
| | | - Full command palette. |
| | | - AI-generated search results. |
| | | - Remote ranking or analytics. |
| | | - Pinyin matching. |
| | | - User-defined aliases. |
| | | - Replacing Spotlight by default. |
| | | - Taking over `Option + Space` by default. |
| | | - Low-level keyboard interception to steal system shortcuts. |
| | | |
| | | ## User Stories |
| | | |
| | | 1. As a user, I can open TagLauncher, press `Space`, type a few characters, and launch the selected app with `Enter`. |
| | | 2. As a user, I can search by app name, tag name, or app note. |
| | | 3. As a user, I can type partial or non-contiguous characters and still find relevant apps. |
| | | 4. As a user, I can use arrow keys to change the selected result. |
| | | 5. As a user, I can click a result to launch it. |
| | | 6. As a user, I can press `Esc` to close Quick Search without losing the main interface when I opened it from the main interface. |
| | | 7. As an advanced user, I can configure a direct global shortcut for Quick Search. |
| | | 8. As a user, I can see whether a shortcut is active, disabled, or blocked by a conflict. |
| | | |
| | | ## Interaction Requirements |
| | | |
| | | ### Opening |
| | | |
| | | When the main TagLauncher interface is visible, pressing `Space` opens Quick Search only if all conditions are true: |
| | | |
| | | - Quick Search is not already open. |
| | | - No text input, search field, text area, or editable field is focused. |
| | | - No modal, popover, menu, confirmation dialog, or shortcut recorder is active. |
| | | - Focus is not on a control where `Space` is expected to activate or toggle that control. |
| | | |
| | | When opened from the main interface: |
| | | |
| | | - The overlay appears above the existing app list. |
| | | - The app list is not pushed, resized, or reflowed. |
| | | - The Quick Search input is focused immediately. |
| | | - The first available result is selected by default. |
| | | |
| | | When opened from a direct global shortcut: |
| | | |
| | | - TagLauncher opens the Quick Search overlay directly. |
| | | - The input is focused immediately. |
| | | - If the main interface was hidden before the shortcut was pressed, `Esc` hides the Quick Search window. |
| | | |
| | | ### Overlay |
| | | |
| | | Quick Search appears as a floating overlay near the top center of the TagLauncher window. |
| | | |
| | | Required behavior: |
| | | |
| | | - The overlay uses the existing visual system where possible. |
| | | - The input is the primary focus. |
| | | - The result list appears below the input in the same overlay layer. |
| | | - The overlay sits above the app list and does not change the app list layout. |
| | | - The overlay supports empty, loading, result, no-result, and launch-failed states. |
| | | |
| | | Visible result count: 6 to 8 rows. |
| | | |
| | | ### Empty Query |
| | | |
| | | When the query is empty: |
| | | |
| | | - Show up to 6 apps. |
| | | - Sort by most recently opened first. |
| | | - If fewer than 6 recent apps exist, fill the remaining slots with most frequently opened apps. |
| | | - Do not show the full app catalog. |
| | | - If no history exists, show an empty prompt: `Start typing to search apps, tags, and notes.` |
| | | |
| | | Recent and frequent data must use successful TagLauncher-mediated app launches, not only launches from Quick Search. |
| | | |
| | | ### Typing and Selection |
| | | |
| | | While the user types: |
| | | |
| | | - Results update in real time. |
| | | - If the user has not manually changed selection, select the top-ranked result after each query update. |
| | | - If the user manually selected a result and that result remains visible after the query update, preserve the selection. |
| | | - If the selected result disappears, select the top-ranked result. |
| | | - If there are no results, no item is selected and `Enter` does nothing. |
| | | - If there are no results, show: `No apps found.` |
| | | |
| | | ### Keyboard |
| | | |
| | | | Key | Behavior | |
| | | |---|---| |
| | | | `Up` | Move selection to the previous result; stay at the first result when already first | |
| | | | `Down` | Move selection to the next result; stay at the last result when already last | |
| | | | `Enter` | Launch the selected result | |
| | | | `Esc` | Close Quick Search | |
| | | | `Space` inside input | Insert a space character | |
| | | |
| | | `Esc` behavior: |
| | | |
| | | - If Quick Search was opened from the visible main interface, close only Quick Search and return to the main interface. |
| | | - If Quick Search was opened directly while the main interface was hidden, close Quick Search and hide the window. |
| | | |
| | | ### Mouse |
| | | |
| | | - Hovering a result highlights it and updates the active selection. |
| | | - Clicking a result launches the app. |
| | | - Clicking inside the main interface but outside the overlay closes Quick Search and leaves the main interface visible. |
| | | - Clicking outside the TagLauncher window follows existing app behavior. |
| | | |
| | | ## Search Requirements |
| | | |
| | | ### Searchable Fields |
| | | |
| | | | Field | Required | Ranking weight | |
| | | |---|---:|---| |
| | | | App display name | Yes | Highest | |
| | | | Localized app name | Yes, when available | Highest | |
| | | | Tag names | Yes | High | |
| | | | App note | Yes | Medium | |
| | | | Bundle identifier | Optional | Low | |
| | | |
| | | Future fields such as aliases, pinyin, command history, and TagLauncher actions must not block 7.5. |
| | | |
| | | ### Query Normalization |
| | | |
| | | Before matching: |
| | | |
| | | - Trim leading and trailing whitespace. |
| | | - Collapse repeated spaces. |
| | | - Match Latin text case-insensitively. |
| | | - Treat punctuation in app names as separators for acronym matching. |
| | | - Keep Chinese characters as searchable characters. |
| | | |
| | | Multi-word queries use `AND` semantics: |
| | | |
| | | - Every query token must match at least one searchable field. |
| | | - Different tokens may match different fields on the same app. |
| | | - Ranking sums the best score from each matched token. |
| | | |
| | | ### Match Types |
| | | |
| | | Required match types: |
| | | |
| | | | Type | Example | |
| | | |---|---| |
| | | | Exact | `figma` matches `Figma` | |
| | | | Prefix | `fig` matches `Figma` | |
| | | | Substring | `shop` matches `Photoshop` | |
| | | | Acronym | `gc` matches `Google Chrome` | |
| | | | Subsequence | `ps` matches `Photoshop` | |
| | | | Case-insensitive Latin | `chrome`, `Chrome`, and `CHROME` match the same app | |
| | | | Direct Chinese character | `设计` matches a tag, name, or note containing `设计` | |
| | | |
| | | Acronyms are generated from app display names and localized names by splitting on spaces, punctuation, and camel-case boundaries. |
| | | |
| | | Subsequence matching applies only when the query token has at least 2 characters. It ranks below exact, prefix, substring, and acronym matches. |
| | | |
| | | Pinyin matching is out of scope for 7.5. |
| | | |
| | | ## Ranking Requirements |
| | | |
| | | Ranking must be deterministic and testable. |
| | | |
| | | Scoring model for 7.5: |
| | | |
| | | ```text |
| | | finalScore = textScore + behaviorBoost |
| | | textScore = sum(best token score for each query token) |
| | | behaviorBoost = min(recentBoost + frequencyBoost, 20) |
| | | ``` |
| | | |
| | | Field weights: |
| | | |
| | | | Field | Weight | |
| | | |---|---:| |
| | | | App display name / localized name | 100 | |
| | | | Tag name | 70 | |
| | | | App note | 45 | |
| | | | Bundle identifier | 20 | |
| | | |
| | | Match type weights: |
| | | |
| | | | Match type | Weight | |
| | | |---|---:| |
| | | | Exact | 100 | |
| | | | Prefix | 80 | |
| | | | Substring | 60 | |
| | | | Acronym | 55 | |
| | | | Subsequence | 35 | |
| | | |
| | | Position bonus: |
| | | |
| | | - Add up to 10 points for earlier matches in the field. |
| | | - Do not apply position bonus to exact matches. |
| | | |
| | | Behavior boosts: |
| | | |
| | | - `recentBoost`: maximum 15 points. |
| | | - `frequencyBoost`: maximum 10 points. |
| | | - Combined behavior boost must never exceed 20 points. |
| | | - Behavior boost must not let a note-only weak match outrank a strong app-name match for the same query. |
| | | |
| | | Tie-break order: |
| | | |
| | | 1. Higher `textScore`. |
| | | 2. App name or localized name match beats tag match. |
| | | 3. Tag match beats note match. |
| | | 4. More recent successful TagLauncher launch. |
| | | 5. Higher launch count. |
| | | 6. Shorter display name. |
| | | 7. Alphabetical display name. |
| | | |
| | | Minimum ranking examples: |
| | | |
| | | | Query | Expected behavior | |
| | | |---|---| |
| | | | `fig` | `Figma` app-name prefix ranks above apps whose notes contain `fig` | |
| | | | `shop` | `Photoshop` substring match is returned | |
| | | | `gc` | `Google Chrome` acronym match is returned | |
| | | | `ps` | `Photoshop` subsequence match is returned, but below stronger exact/prefix matches | |
| | | | `design` | Apps tagged `Design` rank above apps with `design` only in notes when text strength is otherwise comparable | |
| | | | `ai` | A frequently launched AI app may outrank a weak note-only match, but not an exact app-name match | |
| | | |
| | | ## Result Row Requirements |
| | | |
| | | Each result row includes: |
| | | |
| | | - App icon. |
| | | - App display name. |
| | | - Matched tag names when the tag field contributed to the match. |
| | | - Note snippet only when the note field contributed to the match. |
| | | - Clear selected state. |
| | | |
| | | Can ship without: |
| | | |
| | | - Highlight matched text inside names, tags, or notes. |
| | | - Show bundle identifier as secondary text only when useful for disambiguation. |
| | | |
| | | Rows must stay compact. Quick Search is not a detail view. |
| | | |
| | | ## Launch Behavior |
| | | |
| | | When the user presses `Enter` or clicks a result: |
| | | |
| | | 1. Attempt to launch the selected app. |
| | | 2. If launch succeeds, update `lastOpenedAt` and `openCount`. |
| | | 3. Close Quick Search. |
| | | 4. Apply the existing TagLauncher behavior for hiding or keeping the main interface after launching an app. |
| | | |
| | | If launch fails: |
| | | |
| | | - Keep Quick Search open. |
| | | - Keep the user's query. |
| | | - Do not update `lastOpenedAt` or `openCount`. |
| | | - Show: `Could not open this app. Try again or choose another app.` |
| | | |
| | | ## Shortcut Settings |
| | | |
| | | Settings must expose: |
| | | |
| | | | Setting | Default | |
| | | |---|---| |
| | | | Main interface shortcut | `Shift + Option + Space` | |
| | | | Direct Quick Search shortcut | Disabled | |
| | | |
| | | Required actions: |
| | | |
| | | - Record shortcut. |
| | | - Clear shortcut. |
| | | - Restore default main interface shortcut. |
| | | - Retry registration after conflict resolution. |
| | | - Open macOS Keyboard Shortcuts settings when supported. |
| | | |
| | | Shortcut status: |
| | | |
| | | | Status | Meaning | |
| | | |---|---| |
| | | | Active | Shortcut registered successfully and works immediately | |
| | | | Conflict | Shortcut could not be registered because macOS or another app already uses it | |
| | | | Disabled | No shortcut is assigned | |
| | | |
| | | When the user records a shortcut: |
| | | |
| | | - TagLauncher attempts to register it immediately. |
| | | - If registration succeeds, save it and show `Active`. |
| | | - If registration fails, show `Conflict` and do not present it as active. |
| | | - If a previous shortcut was active, keep the previous shortcut active until the new shortcut registers successfully. |
| | | - Shortcut changes must not require app restart. |
| | | |
| | | Known macOS shortcuts that need specific guidance when registration fails: |
| | | |
| | | | Shortcut | Default macOS use | |
| | | |---|---| |
| | | | `Command + Space` | Spotlight | |
| | | | `Option + Command + Space` | Finder search window | |
| | | | `Control + Space` | Previous input source | |
| | | | `Control + Option + Space` | Next input source | |
| | | | `Control + Command + Space` | Emoji and symbols | |
| | | |
| | | Conflict copy rules: |
| | | |
| | | - If the shortcut is a known macOS default and registration fails, show the specific macOS guidance. |
| | | - For all other failures, show: `This shortcut is already used by macOS or another app. Choose another shortcut, or change the shortcut in the other app and try again.` |
| | | - TagLauncher must not use low-level keyboard interception to bypass macOS shortcut ownership. |
| | | |
| | | ## Data Requirements |
| | | |
| | | Search document fields: |
| | | |
| | | ```text |
| | | appId |
| | | bundleIdentifier |
| | | displayName |
| | | localizedNames |
| | | tagNames |
| | | note |
| | | lastOpenedAt |
| | | openCount |
| | | ``` |
| | | |
| | | Index refresh triggers: |
| | | |
| | | - App catalog changes. |
| | | - App install or removal scan. |
| | | - Tag assignment changes. |
| | | - Tag rename. |
| | | - App note changes. |
| | | - App language or locale changes when localized names or tags are available. |
| | | |
| | | Launch ranking data: |
| | | |
| | | - Stored locally. |
| | | - Updated only after successful TagLauncher-mediated app launches. |
| | | - Existing users start with empty history and `openCount = 0`. |
| | | - When an app is removed from the local catalog, remove its associated ranking data. |
| | | |
| | | ## Performance Requirements |
| | | |
| | | Search must run locally and work offline. |
| | | |
| | | Targets: |
| | | |
| | | - Opening the overlay must not block on network or app scanning. |
| | | - For 1,000 local app records, visible results must update within 50 ms at p95 on a typical supported Mac. |
| | | - Typing must remain visually smooth while the index is in memory. |
| | | - The app can keep the search index in memory while TagLauncher is running. |
| | | |
| | | Performance measurement includes query processing and result list update, not app launch time. |
| | | |
| | | ## Privacy Requirements |
| | | |
| | | - Do not send search queries to a server. |
| | | - Do not send app names, tag names, app notes, shortcut settings, recent launch data, or launch counts to a server for this feature. |
| | | - Store shortcut settings locally. |
| | | - Store recent and frequent launch data locally. |
| | | |
| | | ## Accessibility and Localization |
| | | |
| | | Accessibility: |
| | | |
| | | - Full keyboard operation is required. |
| | | - The input must have an accessible label. |
| | | - Result rows must expose app name and relevant metadata to accessibility APIs where supported. |
| | | - Selected state must be visually clear. |
| | | - No-result and launch-failed states must be announced where supported. |
| | | |
| | | Localization: |
| | | |
| | | - All user-facing strings must be localizable. |
| | | - Shortcut conflict guidance must be localizable. |
| | | - Search uses localized app and tag names when available. |
| | | |
| | | ## Acceptance Criteria |
| | | |
| | | Quick Search: |
| | | |
| | | - `Shift + Option + Space` opens the main TagLauncher interface. |
| | | - Pressing `Space` in the valid main-interface state opens Quick Search. |
| | | - Quick Search appears as a floating overlay and does not reflow the app list. |
| | | - The input is focused immediately. |
| | | - Empty query shows recent/frequent apps, not the full catalog. |
| | | - No-result state is clear. |
| | | - Launch-failed state keeps the query visible. |
| | | |
| | | Search: |
| | | |
| | | - Searches all launchable apps known to TagLauncher. |
| | | - Searches app display name, localized name when available, tag names, and app notes. |
| | | - Supports exact, prefix, substring, acronym, subsequence, case-insensitive Latin, and direct Chinese character matching. |
| | | - Multi-word queries require every token to match. |
| | | - Ranking follows the field, match type, behavior boost, and tie-break rules in this PRD. |
| | | |
| | | Keyboard and mouse: |
| | | |
| | | - `Up` and `Down` change selection. |
| | | - `Enter` launches the selected result. |
| | | - `Enter` does nothing when there is no result. |
| | | - `Esc` closes Quick Search with the correct behavior for the way it was opened. |
| | | - Hover updates active selection. |
| | | - Clicking a result launches it. |
| | | - Clicking the main interface outside the overlay closes Quick Search and keeps the main interface visible. |
| | | |
| | | Shortcuts: |
| | | |
| | | - Main interface shortcut is configurable. |
| | | - Direct Quick Search shortcut is configurable and disabled by default. |
| | | - Shortcut changes apply without restart. |
| | | - Shortcut settings persist across relaunch. |
| | | - Failed shortcut registration is shown as `Conflict`, not `Active`. |
| | | - Previous active shortcut remains active if a new shortcut fails registration. |
| | | - Known macOS conflicts show specific guidance. |
| | | - Unknown conflicts show generic guidance. |
| | | - Retry works after the user resolves the conflict. |
| | | |
| | | Privacy and performance: |
| | | |
| | | - Search works offline. |
| | | - Search does not send queries or app notes to a server. |
| | | - Result updates meet the 1,000-record p95 target. |
| | | |
| | | ## QA Scenarios |
| | | |
| | | 1. Open the main interface with `Shift + Option + Space`, press `Space`, and verify Quick Search opens with input focused. |
| | | 2. Press `Space` while a text field, modal, menu, or shortcut recorder is active and verify Quick Search does not open. |
| | | 3. Open Quick Search with an empty query and verify recent apps appear first. |
| | | 4. Verify an empty-history user sees `Start typing to search apps, tags, and notes.` |
| | | 5. Search by app name and launch with `Enter`. |
| | | 6. Search by localized app name when available. |
| | | 7. Search by tag name and verify tagged apps appear. |
| | | 8. Search by app note and verify the note snippet appears only when the note matched. |
| | | 9. Search `gc` and verify acronym matching. |
| | | 10. Search `ps` and verify subsequence matching. |
| | | 11. Search Chinese characters and verify direct Chinese matching. |
| | | 12. Use `Up` and `Down`, then press `Enter` to launch the selected result. |
| | | 13. Press `Esc` after opening from the main interface and verify the main interface remains visible. |
| | | 14. Press `Esc` after opening from a direct global shortcut while the window was hidden and verify the window hides. |
| | | 15. Configure an available direct Quick Search shortcut and verify it works immediately. |
| | | 16. Configure `Command + Space` while Spotlight owns it and verify conflict status and Spotlight-specific guidance. |
| | | 17. After a failed shortcut registration, verify the previous active shortcut still works. |
| | | 18. Resolve or change the conflicting shortcut, click Retry, and verify status updates. |
| | | 19. Relaunch TagLauncher and verify shortcut settings persist. |
| | | 20. Confirm typing in Quick Search sends no network requests. |
| | | 21. Test 1,000 app records and verify visible results update within the performance target. |
| New file |
| | |
| | | # Apptag Development Workflow Standard |
| | | |
| | | Status: Active |
| | | Version: 1.0 |
| | | Effective date: 2026-05-20 |
| | | Owner: Project owner / Architect |
| | | |
| | | ## 1. Purpose |
| | | |
| | | This document is the single authoritative workflow standard for the Apptag project. |
| | | |
| | | Its job is to consolidate the process rules that were previously scattered across project notes, release docs, QA docs, PRDs, and agent instructions, so that every coder, reviewer, QA role, architect role, and operator follows the same execution model. |
| | | |
| | | This document governs how work is planned, implemented, reviewed, tested, versioned, built, and released. |
| | | |
| | | ## 2. Authority And Precedence |
| | | |
| | | 1. This document is the top-level workflow authority for the repository. |
| | | 2. Feature PRDs, QA cases, release checklists, and data-operation docs remain active, but they are subordinate to this workflow standard. |
| | | 3. If two lower-level documents conflict, this document wins unless the conflict is resolved by an explicit new decision entry in `Decisions.md`. |
| | | 4. If a coder receives a request from any role, including the project commander, that conflicts with this document, the coder must pause and cite the exact clause that is being violated before continuing. |
| | | 5. No silent exceptions are allowed. |
| | | |
| | | ## 3. Source Documents Consolidated Here |
| | | |
| | | The following documents currently contribute workflow or release constraints and are now consolidated by this standard: |
| | | |
| | | | Source document | Current role after consolidation | |
| | | |---|---| |
| | | | `.hermes.md` | Pointer to this standard; no longer the main place for workflow rules | |
| | | | `Decisions.md` | Decision log for architecture, workflow exceptions, and major behavior changes | |
| | | | `CHANGELOG.md` | User-visible release change log | |
| | | | `AppStore_Submission.md` | Canonical App Store submission content and compliance notes | |
| | | | `AppStore_TODO_7.3.5_744.md` and future release TODO files | Release execution checklists for a specific version | |
| | | | `Docs/QA/*.md` | Feature-specific QA gates and manual test cases | |
| | | | `Docs/PRD/*.md` | Feature contracts, product scope, and acceptance criteria | |
| | | | `Docs/ProjectManagement/*.md` | Architecture-approved implementation plans and project management records | |
| | | | `CatalogOps/README.md` | Smart Start catalog data-operations rules | |
| | | | `SmartStart_GTD.md` | Historical role/workflow reference; future role flow should follow this standard | |
| | | |
| | | ## 4. Mandatory End-To-End Workflow |
| | | |
| | | ### 4.1 Intake And Scope Control |
| | | |
| | | 1. No non-trivial product-facing feature starts without one of the following: |
| | | - an approved PRD, or |
| | | - a PRD-level task brief that clearly defines scope, non-goals, and acceptance criteria. |
| | | 2. If the request changes user-visible behavior, search rules, data behavior, persistence, or release posture, the work is non-trivial by default. |
| | | 3. If scope is unclear, ambiguity must be resolved before implementation, not after code is already merged. |
| | | |
| | | ### 4.2 Required Delivery Sequence |
| | | |
| | | The default delivery sequence is: |
| | | |
| | | 1. Product defines the requirement. |
| | | 2. Architect reviews data safety, module boundaries, and release risk when the change is behaviorally or structurally significant. |
| | | 3. QA writes or updates test cases for the feature before the feature is considered complete. |
| | | 4. Coder implements the smallest approved slice that can be built and reviewed safely. |
| | | 5. Coder runs the required validation commands and records risks. |
| | | 6. Reviewer checks code against the PRD, QA cases, this workflow standard, and existing release constraints. |
| | | 7. Release docs are updated before any version is treated as shippable. |
| | | |
| | | ### 4.3 Documentation Duties During Work |
| | | |
| | | The following updates are mandatory when applicable: |
| | | |
| | | 1. `Decisions.md` must be updated for: |
| | | - architecture decisions, |
| | | - workflow changes, |
| | | - intentional product behavior deviations from an approved PRD or snapshot, |
| | | - one-off exceptions approved by the project owner. |
| | | 2. `CHANGELOG.md` must be updated for any user-visible change that is intended to ship. |
| | | 3. The relevant PRD, rule snapshot, or QA doc must be updated when code intentionally changes a documented feature contract. |
| | | 4. If code and docs disagree, the discrepancy must be treated as an issue to resolve, not ignored as “just documentation drift”. |
| | | |
| | | ## 5. Roles And Responsibilities |
| | | |
| | | ### 5.1 Product |
| | | |
| | | - Define goals, scope, non-goals, and acceptance criteria. |
| | | - Clarify edge cases before implementation. |
| | | - Do not treat unstated assumptions as approved behavior. |
| | | |
| | | ### 5.2 Architect |
| | | |
| | | - Protect data safety, module boundaries, and release quality. |
| | | - Review risky changes before they become default implementation. |
| | | - Decide whether a behavior change is a narrow fix or a contract change that requires doc and QA updates. |
| | | |
| | | ### 5.3 Coder |
| | | |
| | | - Keep changes small, buildable, and reviewable. |
| | | - Run the required build/validation flow. |
| | | - Report file-level changes, known risks, and any conflict with this standard. |
| | | - Do not silently widen behavior, search reach, data mutation, or release scope. |
| | | |
| | | ### 5.4 QA |
| | | |
| | | - Write or update test cases from the PRD. |
| | | - Verify implementation against the PRD and this standard, not just against the current code. |
| | | - Treat missing QA coverage as an open risk. |
| | | |
| | | ### 5.5 Ops / Data Ops |
| | | |
| | | - Maintain reproducible scripts, data generation notes, and QA reports. |
| | | - Do not directly overwrite official production catalogs through automation. |
| | | - Promote catalog data only after human review and approval. |
| | | |
| | | ## 6. Non-Negotiable Engineering Rules |
| | | |
| | | ### 6.1 User Data Safety |
| | | |
| | | 1. No feature may silently overwrite existing user tags, notes, or meaningful preferences unless an approved product decision explicitly says so. |
| | | 2. Automatic classification, seeding, migration, or cleanup work must preserve user-authored data by default. |
| | | 3. Destructive or hard-to-reverse behavior requires backup, undo, confirmation, or an equivalent safety control. |
| | | |
| | | ### 6.2 Product Contract Integrity |
| | | |
| | | 1. Code must not silently diverge from approved product scope. |
| | | 2. If implementation intentionally exceeds PRD scope, the PRD and QA docs must be updated before the behavior is treated as accepted. |
| | | 3. “The code already does it” is not by itself approval. |
| | | |
| | | ### 6.3 Search And Ranking Changes |
| | | |
| | | Search behavior is release-sensitive. |
| | | |
| | | Any change to search scope, matching type, ranking, fuzzy behavior, pinyin handling, searchable fields, or default suggestion logic must include: |
| | | |
| | | 1. an explicit statement of the rule change, |
| | | 2. before/after example queries, |
| | | 3. updated PRD or rule-snapshot documentation when the contract changes, |
| | | 4. regression review for both precision and recall, |
| | | 5. QA coverage for representative edge cases. |
| | | |
| | | No coder may quietly broaden search recall by adding extra matching paths without documenting and reviewing the tradeoff. |
| | | |
| | | ### 6.4 Catalog And Ruleset Operations |
| | | |
| | | 1. Smart Start catalog automation may generate candidates, reports, and cleaned outputs. |
| | | 2. Automation must not directly overwrite the official runtime catalog. |
| | | 3. Promotion into the official catalog requires human approval. |
| | | 4. Stable tag IDs must remain stable and must not be replaced by localized display names. |
| | | |
| | | ## 7. Versioning, Build, And Release Rules |
| | | |
| | | ### 7.1 Version Metadata Ownership |
| | | |
| | | 1. `CFBundleShortVersionString` is the committed marketing version and must remain stable in source control until intentionally changed. |
| | | 2. `CFBundleVersion` uses the format `YYYYMMDD.HHmm`. |
| | | 3. Version and build values shown in source, changelog, release docs, and shipped artifacts must agree. |
| | | |
| | | ### 7.2 Build Must Not Pollute The Source Tree |
| | | |
| | | This is a hard rule. |
| | | |
| | | 1. The build process must not mutate tracked source files as part of normal packaging. |
| | | 2. Build metadata that changes per build, including `CFBundleVersion`, must be injected into the built app bundle artifact, not written back into the repository working copy. |
| | | 3. `Apptag/Info.plist` is source configuration, not build output. |
| | | 4. If a build changes tracked files, the build flow is defective and must be fixed. |
| | | |
| | | ### 7.3 Required Fix For The Current Build Flow |
| | | |
| | | The current `build.sh` behavior that rewrites the tracked `Apptag/Info.plist` is not acceptable as a long-term workflow. |
| | | |
| | | The required remediation is: |
| | | |
| | | 1. copy the source `Info.plist` into the app bundle, |
| | | 2. write the dynamic build number only into the bundle copy, |
| | | 3. leave the tracked source plist unchanged, |
| | | 4. verify after build that `git status --short` does not show tracked changes caused by packaging. |
| | | |
| | | Any alternative that relies on manually reverting the file, ignoring the file, or asking humans not to commit the change is only a temporary workaround and is not considered a valid final fix. |
| | | |
| | | ### 7.4 Release Readiness Gates |
| | | |
| | | A version is not release-ready until all of the following are true: |
| | | |
| | | 1. build succeeds, |
| | | 2. version/build metadata are internally consistent, |
| | | 3. relevant manual QA or smoke checks are completed, |
| | | 4. `CHANGELOG.md` is updated, |
| | | 5. release docs are updated when the build is intended for external distribution, |
| | | 6. no known blocker remains open without explicit sign-off. |
| | | |
| | | ## 8. Required Validation And Review Gates |
| | | |
| | | ### 8.1 Minimum Validation Per Change |
| | | |
| | | At minimum, the implementer or reviewer must verify: |
| | | |
| | | 1. the project still builds, |
| | | 2. the directly affected feature still works, |
| | | 3. no tracked source file was unintentionally modified by the validation process, |
| | | 4. relevant docs remain aligned with the code. |
| | | |
| | | ### 8.2 Feature-Specific Gates |
| | | |
| | | In addition to the minimum validation: |
| | | |
| | | - Initial-default changes must preserve existing user values and satisfy the initial-default QA cases. |
| | | - Smart Start catalog changes must satisfy the catalog validation gates and QA reports before bundling. |
| | | - Release-bound changes must be checked against `AppStore_Submission.md` and the active release checklist. |
| | | - Search changes must satisfy the search-and-ranking rules in section 6.3. |
| | | |
| | | ## 9. Conflict Handling And Escalation |
| | | |
| | | If a request conflicts with this standard: |
| | | |
| | | 1. the coder must stop, |
| | | 2. the coder must identify the exact clause number, |
| | | 3. the coder must explain the consequence of violating it, |
| | | 4. the work may continue only if: |
| | | - the request is changed to comply, or |
| | | - a deliberate one-time exception is approved and recorded in `Decisions.md`. |
| | | |
| | | The project commander is not exempt from this process. Instructions from above can change the standard, but they do not silently bypass it. |
| | | |
| | | ## 10. Practical Operating Checklist |
| | | |
| | | Before marking work complete, confirm: |
| | | |
| | | - Is the requirement documented well enough to implement safely? |
| | | - Does the change need PRD, QA, changelog, or decision-log updates? |
| | | - Does the change protect existing user data? |
| | | - Does the build pass? |
| | | - Did the build leave the repo clean? |
| | | - Do release/version docs still match the artifact? |
| | | - If the behavior changed, is the contract documentation updated too? |
| | | |
| | | ## 11. Future Maintenance Rule |
| | | |
| | | When this workflow standard is updated: |
| | | |
| | | 1. increment the document version, |
| | | 2. record the reason in `Decisions.md`, |
| | | 3. update any pointer docs that reference the authoritative workflow standard. |
| | | |
| | | Until superseded by a newer version, this document is the workflow contract for Apptag. |
| | |
| | | .trim(); |
| | | } |
| | | |
| | | function stripLeadingPunctuation(value) { |
| | | const clean = String(value ?? "") |
| | | .replace(/\s+/g, " ") |
| | | .trim(); |
| | | |
| | | if (clean.startsWith(".NET")) { |
| | | return `Microsoft .NET${clean.slice(".NET".length)}`.trim(); |
| | | } |
| | | |
| | | return clean |
| | | .replace(/^[\p{P}\s]+/u, "") |
| | | .trim(); |
| | | } |
| | | |
| | | function truncateNote(value) { |
| | | const clean = stripTerminalPunctuation(value); |
| | | const clean = stripTerminalPunctuation(stripLeadingPunctuation(value)); |
| | | if (charLength(clean) <= noteLimit) return clean; |
| | | let sliced = Array.from(clean).slice(0, noteLimit).join(""); |
| | | return stripTerminalPunctuation(sliced); |
| | |
| | | return translations; |
| | | } |
| | | |
| | | function localizedGeneratedNote(name, tags, code, translations) { |
| | | const categoryMap = translations.get(code) ?? translations.get("en") ?? {}; |
| | | const meaningfulTags = tags.filter((tag) => tag !== "other").slice(0, 2); |
| | | const shownTags = meaningfulTags.length > 0 ? meaningfulTags : tags.slice(0, 1); |
| | | const labels = shownTags.map((tag) => categoryMap[tag] ?? tag); |
| | | const joiner = ["ar", "ar-Najdi"].includes(code) ? "، " : ["zh-Hans", "zh-Hant", "ja"].includes(code) ? "、" : ", "; |
| | | const separator = ["zh-Hans", "zh-Hant", "ja"].includes(code) ? ":" : ": "; |
| | | const full = `${name}${separator}${labels.join(joiner)}`; |
| | | if (charLength(full) <= noteLimit) return full; |
| | | |
| | | const compact = `${name}${separator}${labels[0] ?? "App"}`; |
| | | if (charLength(compact) <= noteLimit) return compact; |
| | | |
| | | return truncateNote(compact); |
| | | function inferSourceNoteLanguage(note) { |
| | | const value = String(note ?? ""); |
| | | if (/[\u3040-\u30ff]/u.test(value)) return "ja"; |
| | | if (/[\uac00-\ud7af]/u.test(value)) return "ko"; |
| | | return "zh-Hans"; |
| | | } |
| | | |
| | | function buildLocalizedNotes(name, tags, noteZH, translations) { |
| | | function buildLocalizedNotes(noteZH) { |
| | | if (!noteZH) return {}; |
| | | const notes = {}; |
| | | for (const code of translations.keys()) { |
| | | if (code === "zh-Hans") { |
| | | notes[code] = truncateNote(noteZH); |
| | | } else { |
| | | notes[code] = localizedGeneratedNote(name, tags, code, translations); |
| | | } |
| | | } |
| | | return notes; |
| | | return { |
| | | [inferSourceNoteLanguage(noteZH)]: truncateNote(noteZH), |
| | | }; |
| | | } |
| | | |
| | | function parseAppleNotes() { |
| | |
| | | }; |
| | | } |
| | | |
| | | const duplicateAliasSuffixes = ["-app", "-desktop", "-mac", "-macos"]; |
| | | |
| | | function duplicateAliasBase(normalizedName) { |
| | | const clean = String(normalizedName ?? "").trim(); |
| | | for (const suffix of duplicateAliasSuffixes) { |
| | | if (clean.endsWith(suffix)) { |
| | | return clean.slice(0, -suffix.length); |
| | | } |
| | | } |
| | | return clean; |
| | | } |
| | | |
| | | function duplicateComparable(row) { |
| | | return JSON.stringify({ |
| | | defaultTag: String(row.defaultTag ?? "").trim(), |
| | | tager: String(row.tager ?? "").trim(), |
| | | bundleIdentifier: normalizeBundle(row.bundleIdentifier), |
| | | noteZH: truncateNote(row["defaultNote-ZH"]), |
| | | }); |
| | | } |
| | | |
| | | function dedupeCuratedRows(rows, stats) { |
| | | const byNormalized = new Map(); |
| | | for (const row of rows) { |
| | | const normalizedName = String(row.normalizedName ?? "").trim() || normalizeName(row.Name ?? ""); |
| | | if (normalizedName && !byNormalized.has(normalizedName)) { |
| | | byNormalized.set(normalizedName, row); |
| | | } |
| | | } |
| | | |
| | | const filtered = []; |
| | | for (const row of rows) { |
| | | const normalizedName = String(row.normalizedName ?? "").trim() || normalizeName(row.Name ?? ""); |
| | | const aliasBase = duplicateAliasBase(normalizedName); |
| | | const baseRow = aliasBase === normalizedName ? null : byNormalized.get(aliasBase); |
| | | if (baseRow && duplicateComparable(row) === duplicateComparable(baseRow)) { |
| | | stats.aliasDuplicatesRemoved += 1; |
| | | continue; |
| | | } |
| | | filtered.push(row); |
| | | } |
| | | return filtered; |
| | | } |
| | | |
| | | function build() { |
| | | fs.mkdirSync(outputDir, { recursive: true }); |
| | | const translations = loadCategoryTranslations(); |
| | |
| | | (JSON.parse(fs.readFileSync(outputs.runtimeJSON, "utf8")).entries ?? []).map((entry) => [entry.normalizedName, entry]), |
| | | ) |
| | | : new Map(); |
| | | const curatedRows = readCSVObjects(sources.curatedCatalog); |
| | | const rawCuratedRows = readCSVObjects(sources.curatedCatalog); |
| | | const unknownTagerTokens = new Set(); |
| | | const stats = { |
| | | curatedRows: curatedRows.length, |
| | | curatedRows: rawCuratedRows.length, |
| | | aliasDuplicatesRemoved: 0, |
| | | rowsWithSourceNotes: 0, |
| | | appleNotesAttached: 0, |
| | | tagChangedVsPrevious: 0, |
| | |
| | | bundleChangedVsPrevious: 0, |
| | | missingLocalizedNotes: 0, |
| | | }; |
| | | const curatedRows = dedupeCuratedRows(rawCuratedRows, stats); |
| | | const finalRows = curatedRows.map((row, index) => { |
| | | const name = String(row.Name ?? "").trim(); |
| | | const normalizedName = String(row.normalizedName ?? "").trim() || normalizeName(name); |
| | |
| | | stats.rowsWithSourceNotes += 1; |
| | | } |
| | | |
| | | const notes = buildLocalizedNotes(name, mapping.tags, noteZH, translations); |
| | | const notes = buildLocalizedNotes(noteZH); |
| | | const previous = previousRuntimeEntries.get(normalizedName); |
| | | if (previous) { |
| | | if (JSON.stringify(previous.defaultTag ?? []) !== JSON.stringify(mapping.tags)) { |
| | |
| | | const exactOtherRows = finalRows.filter((row) => row.tags.length === 1 && row.tags[0] === "other"); |
| | | const mixedOtherRows = finalRows.filter((row) => row.tags.length > 1 && row.tags.includes("other")); |
| | | const noteRows = finalRows.filter((row) => row.noteZH); |
| | | const localizedNoteIssues = []; |
| | | const noteQualityIssues = []; |
| | | for (const row of noteRows) { |
| | | for (const code of translations.keys()) { |
| | | const note = row.notes[code]; |
| | | if (!note) { |
| | | localizedNoteIssues.push({ name: row.name, code, issue: "missing" }); |
| | | stats.missingLocalizedNotes += 1; |
| | | } else if (charLength(note) > noteLimit) { |
| | | localizedNoteIssues.push({ name: row.name, code, issue: `over_limit:${charLength(note)}` }); |
| | | for (const [code, note] of Object.entries(row.notes)) { |
| | | if (charLength(note) > noteLimit) { |
| | | noteQualityIssues.push({ name: row.name, code, issue: `over_limit:${charLength(note)}` }); |
| | | } else if (stripTerminalPunctuation(note) != note) { |
| | | localizedNoteIssues.push({ name: row.name, code, issue: "trailing_punctuation" }); |
| | | noteQualityIssues.push({ name: row.name, code, issue: "trailing_punctuation" }); |
| | | } else if (stripLeadingPunctuation(note) != note) { |
| | | noteQualityIssues.push({ name: row.name, code, issue: "leading_punctuation" }); |
| | | } |
| | | } |
| | | } |
| | |
| | | const sourceLines = [ |
| | | "- curated CSV: `Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog.csv`", |
| | | `- curated rows: ${stats.curatedRows}`, |
| | | `- curated rows after alias dedupe: ${curatedRows.length}`, |
| | | `- alias duplicates removed: ${stats.aliasDuplicatesRemoved}`, |
| | | `- unknown tager tokens: ${unknownTagerTokens.size}`, |
| | | ].join("\n"); |
| | | const topTagLines = stableTagOrder |
| | |
| | | - Chinese note changes vs previous runtime JSON: ${stats.zhNoteChangedVsPrevious} |
| | | - Bundle identifier changes vs previous runtime JSON: ${stats.bundleChangedVsPrevious} |
| | | - Unknown tager tokens: ${unknownTagerTokens.size} |
| | | - Localized note issues: ${localizedNoteIssues.length} |
| | | - Note quality issues: ${noteQualityIssues.length} |
| | | |
| | | ## Tag Distribution |
| | | |
| | |
| | | ## Notes |
| | | |
| | | - Runtime tags are generated from the curated CSV \`tager\` column, not the legacy \`defaultTag\` column. |
| | | - Runtime notes are generated for all supported localization files when a Chinese source note exists. |
| | | - Non-Chinese localized notes currently use localized tag-summary copy generated from existing category translations; high-traffic languages can be manually polished later. |
| | | - Runtime notes are generated only from real source notes. The generator must not synthesize notes from app names or category labels. |
| | | - Missing translations are intentionally omitted until a real translation pipeline or reviewed translation table provides them. |
| | | `; |
| | | fs.writeFileSync(outputs.report, report); |
| | | |
| | |
| | | |
| | | - Supported languages: ${runtime.supportedLanguages.length} |
| | | - Rows with source Chinese notes: ${noteRows.length} |
| | | - Required localized notes: ${noteRows.length * runtime.supportedLanguages.length} |
| | | - Issues: ${localizedNoteIssues.length} |
| | | - Source notes: ${noteRows.length} |
| | | - Required machine/reviewed translations: ${noteRows.length * (runtime.supportedLanguages.length - 1)} |
| | | - Generated placeholder translations: 0 |
| | | - Note quality issues: ${noteQualityIssues.length} |
| | | - Note limit: ${noteLimit} |
| | | |
| | | ## Issue Sample |
| | | |
| | | ${localizedNoteIssues.slice(0, 50).map((issue) => `- ${issue.name} / ${issue.code}: ${issue.issue}`).join("\n") || "- None"} |
| | | ${noteQualityIssues.slice(0, 50).map((issue) => `- ${issue.name} / ${issue.code}: ${issue.issue}`).join("\n") || "- None"} |
| | | `; |
| | | fs.writeFileSync(outputs.translationQA, translationReport); |
| | | |
| | |
| | | emptyNormalizedRows: emptyNormalizedRows.length, |
| | | exactOtherRows: exactOtherRows.length, |
| | | mixedOtherRows: mixedOtherRows.length, |
| | | localizedNoteIssues: localizedNoteIssues.length, |
| | | noteQualityIssues: noteQualityIssues.length, |
| | | unknownTagerTokens: [...unknownTagerTokens].sort(), |
| | | outputDir, |
| | | }; |
| | |
| | | ,high-on-life,entertainment|game,game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,markedit,writing,writing,null,Markdown 编辑器,适合写作、整理文档和发布内容 |
| | | ,anydesk,utilities,network-tools,null,远程桌面工具,适合远程访问和协助操作电脑 |
| | | ,tailscale-app,utilities|security,security|network-tools,null,VPN 工具,适合加密连接、远程组网和保护隐私 |
| | | ,the-outer-worlds,entertainment|game,game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,raspberry-pi-imager,media|picture-photo|utilities,picture-photo,null,树莓派系统写盘工具,制作启动卡很省事 |
| | | ,starfield,entertainment|game,game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | |
| | | ,google-gemini,productivity|ai-tools,ai-tools,null,效率工具,适合文档、记录或日常工作流 |
| | | ,wailbrew,utilities,utilities,null,Homebrew 图形界面工具,适合查看和管理本机软件包 |
| | | ,opera,browser,browser,null,网页浏览器,适合日常上网、访问网页和使用 Web 服务 |
| | | ,wireshark-app,utilities,network-tools,null,网络协议分析工具,适合抓包、排查和分析网络问题 |
| | | ,wispr-flow,ai-tools,ai-tools,null,AI 语音输入工具,适合用语音快速转写和输入文本 |
| | | ,macwhisper,utilities,utilities,null,语音转文字工具,适合本地转录音频和整理文字稿 |
| | | ,beekeeper-studio,development,database-tools,null,数据库工具,适合连接、查询和管理数据库 |
| | |
| | | ,loom,media|video,video,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,jd-gui,utilities,terminal-tools,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,finicky,browser|utilities,browser,null,macOS应用程序,能够让用户根据特定规则决定每个网址打开的浏览器 |
| | | ,xcodes-app,development,ide,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,granola,communication|productivity|writing|ai-tools,ai-tools|writing|Meeting,null,自动记录会议重点,把对话变成可追踪的行动项 |
| | | ,webex,communication|productivity|media|video,Meeting,null,企业级视频会议工具,适合正式远程沟通 |
| | | ,barrier,utilities,device-management,null,键鼠共享工具,适合在多台电脑间共用键盘和鼠标 |
| | |
| | | ,font-inter,utilities,Font,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,pika,utilities,utilities,null,取色工具,适合从屏幕上拾取和管理颜色 |
| | | ,lidanglesensor,media|audio|utilities|system-enhancement,audio|device-management|Automation,null,读取笔记本开合角度的小工具,适合自动化和硬件实验 |
| | | ,syncthing-app,transfer|utilities,transfer,null,传输工具,适合下载、同步或共享文件 |
| | | ,cleanmymac,utilities,system-maintenance,null,Mac 清理维护工具,适合清理垃圾、卸载应用和优化系统 |
| | | ,gqrx,media|audio,audio,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,postico,development,database-tools,null,数据库工具,适合连接、查询和管理数据库 |
| | |
| | | ,geekbench,utilities,system-maintenance,null,跨平台基准测试工具,可测试处理器和内存性能 |
| | | ,cork,utilities,utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,dosbox,utilities,utilities,null,兼容运行环境,适合运行部分 Windows 或经典 DOS 应用 |
| | | ,r-app,utilities,utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,apache-directory-studio,browser,database-tools,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,pdf-expert,writing,PDF,null,PDF 阅读、批注和编辑工具,处理合同论文都方便 |
| | | ,mysql-shell,development,database-tools|terminal-tools,null,数据库工具,适合连接、查询和管理数据库 |
| | |
| | | ,local,development,ide,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,muxy-app-tap-muxy,utilities,utilities,null, |
| | | ,prusaslicer,utilities,utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,squirrel-app,utilities,utilities,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,superset,development,ide,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,google-chrome-beta,browser,browser,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,orion,browser,browser,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | |
| | | ,remote-desktop-manager,utilities,network-tools,null,远程连接管理工具,适合集中管理服务器和远程桌面 |
| | | ,home-assistant,productivity|utilities|system-enhancement,Automation,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,homerow,utilities|system-enhancement,system-maintenance,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,dotnet-runtime,utilities,utilities,null,.NET 应用运行时 |
| | | ,dotnet-runtime,utilities,utilities,null,Microsoft .NET 应用运行时 |
| | | ,viber,communication|utilities|security,communication|security,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,fedora-media-writer,writing|media|picture-photo,picture-photo|writing,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,jdk-mission-control,utilities|system-enhancement,window-management|runtime-sdk,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | |
| | | ,heroic,entertainment|game,game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,battle-net,entertainment|game,game,null,暴雪游戏启动器,管理战网游戏和更新 |
| | | ,phpstorm,development,ide|runtime-sdk,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,mkvtoolnix-app,media|video,video,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,qqmusic,media|audio|entertainment,audio,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,siddharthvaddem-openscreen-openscreen,utilities,utilities,null, |
| | | ,font-zed-mono-nerd-font,development|utilities,Font,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | |
| | | ,r-lib-rig-rig,utilities,utilities,null, |
| | | ,font-ibm-plex-sans,media|video|utilities|entertainment,Font,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,1password-tap-1password-cli,utilities|security,security,null, |
| | | ,opensc-app,utilities,file-management,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,dynatrace-oss-tap-dtctl,utilities,utilities,null, |
| | | ,font-terminess-ttf-nerd-font,utilities,Font,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-space-mono-nerd-font,utilities,Font,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | |
| | | ,winehq-stable,utilities,utilities,null,兼容运行环境,适合运行部分 Windows 或经典 DOS 应用 |
| | | ,gstreamer-runtime-package,utilities,utilities,null, |
| | | ,vlc-media-player,media|video,video,null,多格式媒体播放器,适合播放本地视频和音频文件 |
| | | ,net-sdk,development,runtime-sdk,null,.NET 开发工具包,适合构建、运行和发布 .NET 应用 |
| | | ,net-sdk,development,runtime-sdk,null,Microsoft .NET 开发工具包,适合构建、运行和发布 .NET 应用 |
| | | ,session-manager-plugin-for-the-aws-cli,utilities,utilities,null, |
| | | ,brave,browser|utilities|security,browser|security,null,网页调试和浏览工具,适合开发者检查页面细节 |
| | | ,azul-zulu-java-standard-edition-development-kit,development,runtime-sdk,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | |
| | | ,amazon-corretto-jdk,utilities,runtime-sdk,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,winehq-devel,utilities,utilities,null,兼容运行环境,适合运行部分 Windows 或经典 DOS 应用 |
| | | ,aws-client-vpn,utilities|security,security|network-tools,null, |
| | | ,jetbrains-rider,development,ide,null,.NET 集成开发环境 |
| | | ,jetbrains-rider,development,ide,null,Microsoft .NET 集成开发环境 |
| | | ,macvim,development|writing,ide,null,文本编辑器,适合编辑纯文本、配置和轻量写作 |
| | | ,teleport-tsh,communication|productivity,communication,null,Teleport 命令行入口,适合安全登录服务器和集群 |
| | | ,cmake,utilities,utilities,null,跨平台工程配置和构建工具 |
| New file |
| | |
| | | name,normalizedName,tager,legacyDefaultTag,runtimeDefaultTag,bundleIdentifier,defaultNote-ZH |
| | | ,docker-desktop,devops,development|utilities|system-enhancement,development,com.docker.docker,在 Mac 上运行容器和微服务,本地开发环境更容易复现 |
| | | ,brave-browser,browser|security,browser,browser|security,com.brave.Browser,主打隐私和广告拦截的 Chromium 浏览器 |
| | | ,finder,file-management,file-management|utilities|system,file-management|utilities,com.apple.finder,macOS 系统自带工具,适合完成对应的系统管理或日常操作 |
| | | ,slack,communication,communication|productivity,communication,com.tinyspeck.slackmacgap,团队聊天和工作流入口,项目沟通不必埋在邮件里 |
| | | ,libreoffice,office,productivity,productivity|writing,null,开源 Office 套件,文档、表格和演示都能编辑 |
| | | ,1password-cli,security|terminal-tools,utilities|security,development|security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,claude,ai-tools,productivity|ai-tools,ai-tools,com.anthropic.claudefordesktop,桌面入口,适合长文阅读、写作和思考辅助 |
| | | ,cc-switch,ai-tools,development|ai-tools,ai-tools,null,把 AI 带进开发流程,适合写代码、调试和自动化 |
| | | ,orbstack,devops,development|utilities|system-enhancement,development,null,轻量容器和 Linux 环境,替代 Docker Desktop 很顺手 |
| | | ,chromedriver,browser|api-tools,browser|utilities,browser|development,null,Chrome WebDriver 工具,适合自动化测试网页应用 |
| | | ,zoom,Meeting,communication|productivity|media|video,communication|productivity,us.zoom.xos,视频会议常用入口,远程沟通和线上课程都离不开 |
| | | ,warp,ai-tools|terminal-tools,development,development|ai-tools,null,现代终端,把命令行、搜索和 AI 辅助结合起来 |
| | | ,tencent-meeting,Meeting,communication|productivity|media|video,communication|productivity,com.tencent.meeting,腾讯会议入口,中文办公和远程协作很常见 |
| | | ,minecraft,game,productivity|entertainment|game,entertainment|game,com.mojang.minecraftlauncher,开放世界沙盒游戏,建造、探索和模组玩法都很丰富 |
| | | ,macfuse,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,raycast,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,com.raycast.macos,键盘驱动的效率入口,启动 App、脚本和搜索都很快 |
| | | ,facetime,communication|video,communication|video,communication|media|video,com.apple.FaceTime,苹果生态里的音视频通话入口 |
| | | ,maccy,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,剪贴板历史工具,复制过的内容随时找回来 |
| | | ,telegram,communication|security,communication|utilities|security,communication|security,ru.keepcoder.Telegram,即时通讯工具,主打速度和安全 |
| | | ,spotify,audio,media|audio|entertainment,media|audio,com.spotify.client,流媒体音乐播放器,工作和放松都能配一首歌 |
| | | ,blackhole-2ch,audio|device-management,media|audio|utilities,media|audio|utilities|system-enhancement,null,虚拟音频驱动,适合录屏、直播和音频路由 |
| | | ,xquartz,runtime-sdk,development|utilities,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,ollama,ai-tools,development|ai-tools,ai-tools,com.electron.ollama,把 AI 带进开发流程,适合写代码、调试和自动化 |
| | | ,signal,communication|security,communication|utilities|security,communication|security,org.whispersystems.signal-desktop,重视隐私的加密聊天工具 |
| | | ,baidu-netdisk,transfer,file-management|transfer|utilities,transfer|utilities,com.baidu.netdisk,百度网盘客户端,适合云端备份、同步和分享文件 |
| | | ,chatgpt,ai-tools|Notes,communication|productivity|ai-tools,productivity|writing|ai-tools,com.openai.chat,把 AI 助手放到桌面,写作、学习和头脑风暴随手就来 |
| | | ,sublime-text,ide,development|writing,development,null,轻快的代码与文本编辑器,写代码、改配置和记草稿都顺手 |
| | | ,wps-office,office,productivity,productivity|writing,com.kingsoft.wpsoffice.mac,办公套件,适合编辑文档、表格和演示稿 |
| | | ,adobe-acrobat-reader,PDF,design|writing,writing|utilities,null,PDF 阅读和批注工具,合同、论文和表单都能处理 |
| | | ,1password,security,utilities|security,security,com.1password.1password,密码和密钥管理器,账号安全的核心保险箱 |
| | | ,figma,ui-prototyping,productivity|design,design,com.figma.Desktop,在线协作设计工具,界面、原型和设计系统都能做 |
| | | ,netease-cloud-music,audio,media|audio|entertainment,media|audio,com.netease.163music,网易云音乐桌面端,听歌、歌单和中文音乐社区都方便 |
| | | ,music,audio,media|audio|entertainment,media|audio,com.apple.Music,本地和流媒体音乐播放器 |
| | | ,terminal,terminal-tools,development|utilities|system,development,com.apple.Terminal,命令行入口,Mac 的隐藏驾驶舱 |
| | | ,utm,devops,development|utilities,development,null,虚拟化或远程连接工具,适合运行系统环境和访问远程电脑 |
| | | ,lm-studio,ai-tools,development|utilities|ai-tools,ai-tools,ai.lmstudio.app,本地大模型运行工具,适合下载、测试和调用开源模型 |
| | | ,qq-music,audio,communication|media|audio|entertainment,media|audio,com.tencent.QQMusicMac,音乐播放器,适合听歌、管理歌单和使用腾讯音乐服务 |
| | | ,activity-monitor,system-maintenance,utilities|system|system-enhancement,utilities|system-enhancement,com.apple.ActivityMonitor,Mac 的仪表盘,专看谁在耗电、吃内存、拖慢电脑 |
| | | ,audio-midi-setup,audio|device-management,audio|utilities|system,media|audio|utilities|system-enhancement,com.apple.audio.audiomidisetup,管音频设备和 MIDI 路由,音乐人和调试党很常用 |
| | | ,automator,Automation,utilities|system-enhancement,productivity|system-enhancement,com.apple.automator,不写代码也能串起一串 Mac 自动化动作 |
| | | ,bluetooth-file-exchange,transfer|device-management,transfer|utilities|system,transfer|utilities|system-enhancement,com.apple.bluetoothfileexchange,用蓝牙收发文件,古早但关键时能救急 |
| | | ,clock,GTD,productivity|utilities,productivity,com.apple.clock,闹钟、计时器、秒表和世界时钟的统一入口 |
| | | ,cmux,ai-tools,development|ai-tools,ai-tools,null,适合整理媒体元数据、命名或封装文件 |
| | | ,colorsync-utility,picture-photo,design|picture-photo|utilities|system,media|picture-photo,com.apple.colorsyncutility,查看和修复色彩配置文件,处理显示和打印色差 |
| | | ,console,system-maintenance,utilities|system,utilities|system-enhancement,com.apple.console,看系统日志的窗口,排查异常时很有用 |
| | | ,contacts,communication,communication|productivity,communication,com.apple.addressbook,通讯录中枢,邮件、信息和 FaceTime 都会用到它 |
| | | ,dictionary,writing|education,writing|utilities|education,writing|education,com.apple.dictionary,离线词典和同义词库,写作查词不用开浏览器 |
| | | ,digital-color-meter,picture-photo,design|picture-photo|utilities,media|picture-photo,com.apple.digitalcolormeter,屏幕取色器,设计师临时取色的小神器 |
| | | ,disk-utility,system-maintenance,utilities|system,utilities|system-enhancement,com.apple.DiskUtility,管磁盘、分区、格式化和急救,别乱点但很重要 |
| | | ,freeform,Notes,productivity|design,productivity|writing,com.apple.freeform,无限白板,适合头脑风暴、草图和乱七八糟的想法 |
| | | ,grapher,education,utilities|education,education,com.apple.grapher,把方程画成图,数学可视化的隐藏工具 |
| | | ,image-capture,picture-photo|transfer|device-management,transfer|picture-photo|utilities,transfer|media|picture-photo|utilities|system-enhancement,com.apple.image_capture,从相机或扫描仪导入图片,朴素但稳定 |
| | | ,image-playground,ai-tools|picture-photo,design|picture-photo|ai-tools,media|picture-photo|ai-tools,com.apple.generativeplaygroundapp,用 Apple 智能生成图像,适合快速玩创意草稿 |
| | | ,maps,GTD,productivity|utilities,productivity,com.apple.Maps,查路线、看城市,也能把目的地推给 iPhone |
| | | ,migration-assistant,transfer,transfer|utilities|system,transfer|utilities,com.apple.migrateassistant,换新 Mac 时搬家,把旧资料迁到新机器 |
| | | ,mission-control,system,system|system-enhancement,utilities|system,com.apple.exposelauncher,窗口和桌面的空中俯视图,乱了就看它 |
| | | ,numbers,office,productivity,productivity|writing,com.apple.iWork.Numbers,苹果表格工具,轻量报表比 Excel 更清爽 |
| | | ,pages,writing|office,writing,productivity|writing,com.apple.iWork.Pages,苹果文字处理器,写文档和排版都好看 |
| | | ,passwords,security,utilities|security,security,com.apple.passwords,系统密码管家,账号、验证码和通行密钥集中管 |
| | | ,photo-booth,picture-photo,media|picture-photo|entertainment,media|picture-photo,com.apple.photobooth,摄像头自拍和小特效,测试摄像头也方便 |
| | | ,podcasts,audio,media|audio|entertainment,media|audio,com.apple.podcasts,听播客的官方入口,通勤和学习都能用 |
| | | ,preview,picture-photo|PDF,writing|media|picture-photo|utilities|system,writing|media|picture-photo|utilities,com.apple.Preview,Mac 最被低估的工具:看图、批注 PDF、简单编辑全能 |
| | | ,screen-sharing,communication|network-tools,communication|utilities|system,communication|utilities,com.apple.screensharing,远程控制另一台 Mac,帮人修电脑很方便 |
| | | ,screenshot,video|picture-photo,video|picture-photo|utilities,media|video|picture-photo,com.apple.screenshot.launcher,截图和录屏入口,Shift-Command-5 的背后就是它 |
| | | ,script-editor,Automation,development|utilities|system-enhancement,productivity|system-enhancement,com.apple.scripteditor2,写和运行 AppleScript,控制老派 Mac 自动化 |
| | | ,sf-symbols,ui-prototyping,development|design|utilities,design,com.apple.sfsymbols,Apple 官方符号库,做原生界面必备 |
| | | ,shortcuts,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,com.apple.shortcuts,把多个动作串成一键流程,是现代版 Automator |
| | | ,system-information,device-management,utilities|system,utilities|system-enhancement,com.apple.systemprofiler,查看硬件、软件和设备详情,查配置最准确 |
| | | ,tips,education,utilities|education,education,com.apple.helpviewer,苹果官方小技巧,偶尔能发现你没用过的功能 |
| | | ,tv,video,media|video|entertainment,media|video,com.apple.TV,影视内容播放和管理入口 |
| | | ,db-browser-for-sqlite,database-tools,browser|development,development,null,数据库工具,适合连接、查询和管理数据库 |
| | | ,tencent-video,video,media|video|entertainment,media|video,com.tencent.tenvideo,腾讯视频客户端,适合观看影视、综艺和在线视频内容 |
| | | ,bitwarden,security,utilities|security,security,null,开源密码管理器,跨平台保存账号和验证码 |
| | | ,hammerspoon,Automation|runtime-sdk,productivity|development|utilities|system-enhancement,productivity|development|system-enhancement,null,用 Lua 自动化 Mac,键盘、窗口和脚本都能接管 |
| | | ,iqiyi,video,media|video|entertainment,media|video,com.iqiyi.player,爱奇艺视频客户端,适合观看影视、综艺和在线视频内容 |
| | | ,youku,video,media|video|entertainment,media|video,com.youku.mac,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,obs,video,media|video|entertainment,media|video,null,直播和录屏工具,课程、演示和游戏录制都很常用 |
| | | ,bilibili,video,media|video|entertainment,media|video,com.bilibili.bilibili,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,pearcleaner,system-maintenance,browser|utilities,utilities|system-enhancement,null,macOS 应用卸载工具,适合删除 App 并清理残留文件 |
| | | ,gimp,picture-photo,design|media|picture-photo,media|picture-photo,null,开源图像编辑器,修图和简单设计不必上重型套件 |
| | | ,ximalaya,audio,media|audio|entertainment,media|audio,com.ximalaya.ting,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,google-cloud-cli,terminal-tools|devops,utilities,development,null,Google Cloud 命令行工具,适合管理云资源和部署应用 |
| | | ,keka,file-management,utilities,file-management|utilities,null,压缩解压工具,处理 ZIP、7z 和 RAR 很方便 |
| | | ,linearmouse,device-management,productivity|utilities|system-enhancement,utilities|system-enhancement,null,鼠标和触控板调校工具,滚动、加速度和按键更顺手 |
| | | ,sketch,ui-prototyping,productivity|development|design,design,com.bohemiancoding.sketch3,经典 Mac 界面设计工具,适合 UI 和图标设计 |
| | | ,dockdoor,Automation,utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,google-drive,transfer,productivity|transfer|utilities,transfer|utilities,com.google.drivefs,云端文件同步和协作入口,跨设备找资料很省心 |
| | | ,photoshop,picture-photo,design|media|picture-photo,media|picture-photo,null,专业图像编辑工具,修图、合成和设计都绕不开 |
| | | ,adobe-photoshop,picture-photo,design|media|picture-photo,media|picture-photo,com.adobe.Photoshop,专业图像编辑工具,修图、合成和商业设计都很强 |
| | | ,tencent-lemon-cleaner,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,com.tencent.Lemon,Mac 清理工具,适合清理垃圾文件和管理存储空间 |
| | | ,adobe-lightroom,picture-photo,design|media|picture-photo,media|picture-photo,com.adobe.Lightroom,照片管理和调色工具,处理 RAW 与批量照片很顺 |
| | | ,cyberduck,transfer|network-tools,browser|file-management|transfer|utilities,transfer|utilities,null,FTP/SFTP 和云存储客户端,传文件很方便 |
| | | ,gemini,file-management|system-maintenance,productivity|ai-tools,file-management|utilities|system-enhancement,null,重复和相似文件查找工具,可帮助释放磁盘空间 |
| | | ,puremac,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,journey,game,utilities|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,keepassxc,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,canva,picture-photo|office,productivity|design,productivity|writing|media|picture-photo,com.canva.CanvaDesktop,模板化设计工具,海报、社媒图和演示稿都能快速出图 |
| | | ,shottr,picture-photo,media|picture-photo|utilities,media|picture-photo,null,截图和标注工具,做产品反馈和视觉说明很利索 |
| | | ,alfred,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,com.runningwithcrayons.Alfred,老牌效率启动器,搜索、工作流和剪贴板都很强 |
| | | ,the-unarchiver,file-management,utilities,file-management|utilities,null,轻量解压工具,打开各种压缩包很省事 |
| | | ,fuse-t,file-management,utilities,file-management|utilities,null,FUSE 文件系统组件,适合让 macOS 挂载和访问扩展文件系统 |
| | | ,microsoft-word,writing|office,writing,productivity|writing,com.microsoft.Word,经典文字处理器,正式文档和审阅协作都很稳 |
| | | ,swiftbar,Automation|runtime-sdk,development|utilities|system-enhancement,productivity|development|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,microsoft-excel,office,productivity,productivity|writing,com.microsoft.Excel,表格和数据分析老将,财务、运营和模型都靠它 |
| | | ,tor-browser,browser|security,browser|utilities|security,browser|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,background-music,audio|Automation,media|audio|utilities|entertainment,productivity|media|audio|system-enhancement,null,按 App 调节音量,还能把系统声音录进工作流 |
| | | ,kiro-cli,ai-tools|terminal-tools|ide,productivity|development|ai-tools,development|ai-tools,null,把 AI 带进开发流程,适合写代码、调试和自动化 |
| | | ,microsoft-powerpoint,office,productivity,productivity|writing,com.microsoft.Powerpoint,经典演示工具,商务汇报和课程课件都常用 |
| | | ,coteditor,ide,development|writing,development,null,针对 macOS 开发的轻量级代码编辑器 |
| | | ,microsoft-office,office,productivity,productivity|writing,null,办公套件,适合处理文档、表格和演示稿 |
| | | ,finetune,ai-tools|audio,productivity|media|audio|ai-tools,media|audio|ai-tools,null,AI 音频工具,适合整理、转写或优化声音内容 |
| | | ,dropbox,transfer,productivity|file-management|transfer|utilities,transfer|utilities,com.getdropbox.dropbox,老牌云同步工具,跨设备和团队共享文件很稳定 |
| | | ,openmtp,transfer|device-management,file-management|transfer|utilities,transfer|utilities|system-enhancement,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,raspberry-pi-imager,picture-photo,media|picture-photo|utilities,media|picture-photo,null,树莓派系统写盘工具,制作启动卡很省事 |
| | | ,font-jetbrains-mono-nerd-font,Font,development|utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,vivaldi,browser,browser|communication,browser,null,邮件客户端,适合集中收发和管理邮箱 |
| | | ,lulu,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,comfyui,ai-tools|picture-photo,development|media|picture-photo|ai-tools,media|picture-photo|ai-tools,null,节点式 AI 绘图工作流,适合精细控制生成过程 |
| | | ,epic-games-launcher,game,productivity|entertainment|game,entertainment|game,com.epicgames.EpicGamesLauncher,Epic 游戏启动器,领取、下载和更新游戏都靠它 |
| | | ,gcc-arm-embedded,device-management,utilities,utilities|system-enhancement,null,ARM 嵌入式开发工具链,适合交叉编译固件 |
| | | ,perplexity,ai-tools,productivity|entertainment|ai-tools,ai-tools,ai.perplexity.mac,AI 搜索和问答入口,适合快速查资料和追来源 |
| | | ,libreoffice-language-pack,office,productivity,productivity|writing,null,学习工具,适合查词、学习、参考或教育场景 |
| | | ,bettertouchtool,device-management|Automation,utilities|system-enhancement,productivity|utilities|system-enhancement,null,macOS 输入增强工具,适合自定义触控板、鼠标和快捷操作 |
| | | ,helium,utilities,browser,utilities,null,Chromium 内核网页浏览器 |
| | | ,termius,network-tools|terminal-tools,utilities,development|utilities,null,SSH 客户端,适合管理服务器连接和远程终端会话 |
| | | ,onyx,system-maintenance,utilities,utilities|system-enhancement,null,macOS 维护工具,适合清理缓存、调整系统选项和排查问题 |
| | | ,ollama-app,ai-tools,development|ai-tools,ai-tools,null,学习工具,适合查词、学习、参考或教育场景 |
| | | ,skim,PDF,writing,writing|utilities,null,PDF 阅读和批注工具,适合看论文和做研究标注 |
| | | ,grandperspective,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,font-meslo-lg-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,rstudio,ide|runtime-sdk,utilities,development,null,R 语言 IDE,统计分析和数据可视化常用 |
| | | ,android-file-transfer,transfer|device-management,file-management|transfer|utilities,transfer|utilities|system-enhancement,null,文件管理工具,适合整理、传输或清理文件 |
| | | ,kicad,3d-cad,productivity|design|utilities|system-enhancement,design,null,开源电路设计工具,画原理图和 PCB 很专业 |
| | | ,onedrive,transfer,productivity|file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,blackhole-16ch,audio|device-management,media|audio|utilities,media|audio|utilities|system-enhancement,null,多通道虚拟音频驱动,适合复杂录音和直播 |
| | | ,clipy,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,t3-code,ai-tools,development|ai-tools,ai-tools,null,把 AI 带进开发流程,适合写代码、调试和自动化 |
| | | ,font-fira-code-nerd-font,Font,development|utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,espanso,Automation,utilities,productivity|system-enhancement,null,文本扩展工具,适合用缩写快速输入常用短语 |
| | | ,chatgpt-atlas,browser|ai-tools,browser|communication|productivity|ai-tools,browser|ai-tools,null,带 AI 助手的浏览器,边看网页边提问、整理和行动 |
| | | ,font-hack-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,darktable,picture-photo,productivity|development|media|picture-photo,media|picture-photo,null,开源 RAW 照片处理工具,适合摄影后期 |
| | | ,font-jetbrains-mono,Font,development|utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,telegram-desktop,communication|security,communication|utilities|security,communication|security,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,handy,Automation,utilities,productivity|system-enhancement,null,语音转文字工具,可通过快捷键听写并自动输入文本 |
| | | ,affinity,picture-photo,design|media|picture-photo,media|picture-photo,null,设计套件入口,适合替代订阅制设计工具 |
| | | ,unnaturalscrollwheels,device-management,utilities,utilities|system-enhancement,null,鼠标滚轮方向反转工具 |
| | | ,appcleaner,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,google-gemini,ai-tools,productivity|ai-tools,ai-tools,null,效率工具,适合文档、记录或日常工作流 |
| | | ,rar,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,codexbar,ai-tools|Automation|terminal-tools,development|utilities|system-enhancement|ai-tools,productivity|development|system-enhancement|ai-tools,null,菜单栏 AI 编码助手入口,把开发提示放到手边 |
| | | ,battery,system-maintenance|terminal-tools,utilities,development|utilities|system-enhancement,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,bambu-studio,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,anythingllm,ai-tools|communication,development|ai-tools,communication|ai-tools,null,把文档和知识库接入 AI 问答,适合私有资料助手 |
| | | ,cleanshot,picture-photo|system-maintenance,media|picture-photo|utilities,media|picture-photo|utilities|system-enhancement,null,截图、录屏和标注工具,做反馈和教程很利索 |
| | | ,aionui,ai-tools|terminal-tools,ai-tools,development|ai-tools,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,keyclu,Automation,utilities|system-enhancement,productivity|system-enhancement,null,专为macOS设计的免费工具,其主要功能是显示当前运行软件的快捷键 |
| | | ,font-symbols-only-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,coconutbattery,device-management|system-maintenance,utilities,utilities|system-enhancement,null,电池监控工具,适合查看 Mac 和 iOS 设备电池健康 |
| | | ,adobe-creative-cloud,video|picture-photo,design|media|video|picture-photo,media|video|picture-photo,null,Adobe 全家桶管理器,装插件和更新设计工具都靠它 |
| | | ,gitkraken,devops,productivity|development,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,yubico-authenticator,security,utilities|security,security,null,安全相关工具,适合隐私保护、访问控制或账号防护 |
| | | ,daisydisk,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,librecad,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,hiddenbar,system-maintenance,utilities,utilities|system-enhancement,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,latest,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,snipaste,picture-photo,media|picture-photo|utilities,media|picture-photo,null,截图加贴图工具,适合把参考内容固定在屏幕上 |
| | | ,capcut,video|audio,design|media|video|picture-photo,media|video|audio,null,轻量视频剪辑工具,做短视频和社媒内容很顺手 |
| | | ,bbedit,ide,development|writing,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,little-snitch,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,charles,network-tools|security,utilities,utilities|security,null,网页抓包代理,调试接口、证书和网络请求很清楚 |
| | | ,gpg-suite,communication|security,communication|utilities|security,communication|security,null,邮件客户端,适合集中收发和管理邮箱 |
| | | ,omnidisksweeper,system-maintenance,utilities,utilities|system-enhancement,null,磁盘空间清理工具,适合找出并删除大文件 |
| | | ,docker-tap-sbx,devops|runtime-sdk,development|utilities|system-enhancement,development,null,容器开发辅助工具,适合本地环境管理 |
| | | ,font-fira-code,Font,development|utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,kap,video,media|video|utilities,media|video,null,开源录屏工具,快速录制屏幕并导出 GIF 或视频 |
| | | ,conductor,ai-tools,development|ai-tools,ai-tools,null,把 AI 带进开发流程,适合写代码、调试和自动化 |
| | | ,zen,browser,browser|utilities|security,browser,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,mockoon,api-tools,utilities,development,null,API 调试工具,适合测试接口、请求和开发流程 |
| | | ,proton-mail,communication,communication|productivity,communication,null,重视隐私的邮件客户端,适合安全收发邮件 |
| | | ,bunch,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,memo,writing,development|writing,writing,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,proton-pass,security,utilities,security,null,密码管理器,适合保存账号、密码和验证码 |
| | | ,visualvm,system-maintenance|runtime-sdk,utilities,development|utilities|system-enhancement,null,Java 性能分析工具,适合监控、分析和调试 JVM 应用 |
| | | ,font-source-code-pro,Font,development|utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,devtoys,ide,productivity|development|design|utilities,development,null,开发者小工具箱,编码转换、哈希和格式化一站解决 |
| | | ,duckduckgo,browser|security,browser|utilities|security,browser|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,plex,video,media|video|entertainment,media|video,null,家庭媒体库中心,把电影、剧集和音乐整理后跨设备播放 |
| | | ,ubersicht,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,textmate,ide,development|writing,development,null,著名的文本编辑器,主要用于编写代码和脚本 |
| | | ,font-sauce-code-pro-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-blex-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,knockknock,security,utilities,security,null,macOS 安全检查工具,适合发现持久化启动项和可疑组件 |
| | | ,virtualbox,devops,development|utilities,development,null,由德国Innotek公司开发的免费开源虚拟机软件,现由Oracle公司维护 |
| | | ,salesforce-cli,terminal-tools|devops,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,font-maple-mono-nf-cn,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,proton-drive,transfer,utilities,transfer|utilities,null,加密云盘客户端,适合同步和保存隐私文件 |
| | | ,downie,video|transfer,transfer|development|media|video|utilities,transfer|media|video|utilities,null,在线视频下载工具,适合保存课程、演讲和公开素材 |
| | | ,font-0xproto-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,jd-gui,terminal-tools,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,finicky,browser,browser|utilities,browser,null,macOS应用程序,能够让用户根据特定规则决定每个网址打开的浏览器 |
| | | ,webex,Meeting,communication|productivity|media|video,communication|productivity,null,企业级视频会议工具,适合正式远程沟通 |
| | | ,barrier,device-management,utilities,utilities|system-enhancement,null,键鼠共享工具,适合在多台电脑间共用键盘和鼠标 |
| | | ,copyq,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,deskflow-tap-deskflow,device-management,utilities,utilities|system-enhancement,null,键鼠共享工具,适合在多台电脑之间共用键盘和鼠标 |
| | | ,youtube-downloader,video|transfer,transfer|media|video|utilities|system-enhancement|entertainment,transfer|media|video|utilities,null,轻量视频下载工具,适合把在线素材保存到本地 |
| | | ,font-caskaydia-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,react-native-debugger,api-tools,utilities,development,null,React Native 调试工具,适合检查应用状态和网络请求 |
| | | ,forklift,transfer,file-management|transfer|utilities,transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,font-droid-sans-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-ubuntu-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,mullvad-browser,browser|security,browser|utilities|security,browser|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,font-go-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,platypus,terminal-tools,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,claudebar,ai-tools,development|utilities|system-enhancement|ai-tools,ai-tools,null,菜单栏 Claude 入口,随手提问和处理文本更快 |
| | | ,cryptomator,security|finance,utilities|finance|security,finance|security,null,给云盘文件加密,敏感资料同步前先锁起来 |
| | | ,reactotron,api-tools,utilities,development,null,应用调试工具,适合调试 React Native 和相关开发流程 |
| | | ,claude-devtools,ai-tools|api-tools,productivity|development|ai-tools,development|ai-tools,null,把 AI 带进开发流程,适合写代码、调试和自动化 |
| | | ,font-comic-shanns-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,adguard,security,utilities,security,null,广告拦截和隐私保护工具,适合过滤网页广告和追踪器 |
| | | ,veracrypt,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,open-webui,ai-tools,development|ai-tools,ai-tools,null,本地 AI 模型网页界面,适合统一管理聊天和模型 |
| | | ,font-inter,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,lidanglesensor,audio|device-management|Automation,media|audio|utilities|system-enhancement,productivity|media|audio|utilities|system-enhancement,null,读取笔记本开合角度的小工具,适合自动化和硬件实验 |
| | | ,cleanmymac,system-maintenance,utilities,utilities|system-enhancement,null,Mac 清理维护工具,适合清理垃圾、卸载应用和优化系统 |
| | | ,repobar,ide,development|utilities|system-enhancement,development,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,zed-preview,ide,development|media|picture-photo|utilities|system,development,null,高性能协作代码编辑器,适合尝鲜新版 Zed 功能 |
| | | ,mattermost,communication,communication|productivity,communication,null,自部署团队聊天工具,适合重视数据控制的团队 |
| | | ,kdiff3,devops,development|utilities,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,linear,ide,productivity|development,development,null,面向产品和研发团队的问题追踪工具 |
| | | ,copyclip,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,轻量剪贴板历史工具,常驻菜单栏保存复制记录 |
| | | ,blackhole-64ch,audio|device-management,media|audio|utilities,media|audio|utilities|system-enhancement,null,高通道虚拟音频驱动,适合专业音频路由 |
| | | ,rectangle-pro,window-management|Automation,utilities|system-enhancement,productivity|utilities|system-enhancement,null,窗口管理工具,适合用快捷键和布局快速整理窗口 |
| | | ,flycut,Automation,productivity|development|utilities|system-enhancement,productivity|system-enhancement,null,开源剪贴板历史工具,复制过的文字随时找回来 |
| | | ,transmit,transfer|network-tools,file-management|transfer|utilities,transfer|utilities,null,经典文件传输客户端,FTP、SFTP 和云端文件管理都很稳 |
| | | ,miro,Notes,productivity,productivity|writing,null,在线白板,适合头脑风暴、流程图和远程共创 |
| | | ,jellyfin-media-player,video,media|video|entertainment,media|video,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,macos-fuse-t-cask-fuse-t,file-management,utilities,file-management|utilities,null,FUSE 文件系统组件,适合让 macOS 挂载和访问扩展文件系统 |
| | | ,jan,ai-tools|communication,communication|productivity|ai-tools,communication|ai-tools,null,本地 AI 聊天工具,把模型运行在自己的电脑上 |
| | | ,wave,terminal-tools,utilities,development,null,终端模拟器,适合命令行开发和日常 Shell 工作 |
| | | ,microsoft-onenote,Notes,productivity|development|writing,productivity|writing,null,微软笔记本,适合课堂记录、项目资料和手写内容 |
| | | ,plex-media-server,video,media|video|entertainment,media|video,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,mqttx,api-tools,utilities,development,null,MQTT 客户端,适合调试、测试和管理 MQTT 消息连接 |
| | | ,logitech-g-hub,device-management|devops,development|utilities,development|utilities|system-enhancement,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,rio,terminal-tools,development|utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,geekbench,system-maintenance,utilities,utilities|system-enhancement,null,跨平台基准测试工具,可测试处理器和内存性能 |
| | | ,apache-directory-studio,database-tools,browser,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,pdf-expert,PDF,writing,writing|utilities,null,PDF 阅读、批注和编辑工具,处理合同论文都方便 |
| | | ,hamed-elfayome-claude-usage-claude-usage-tracker,ai-tools,productivity|ai-tools,ai-tools,null,Claude 相关工具,适合 AI 辅助开发或内容处理 |
| | | ,yaak,network-tools|Automation,utilities,productivity|utilities|system-enhancement,null,API 客户端,适合调试 HTTP 请求和管理接口工作流 |
| | | ,openemu,game,media|video|entertainment|game,entertainment|game,null,复古游戏模拟器,把多平台游戏库统一管理起来 |
| | | ,block-goose,ai-tools,utilities,ai-tools,null,AI 桌面助手,适合在桌面上获得轻量陪伴和提醒 |
| | | ,powershell-preview,terminal-tools,development|media|picture-photo|utilities|system,development,null,跨平台脚本和命令行管理工具预览版 |
| | | ,xbar,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,xmind,Notes,productivity,productivity|writing,null,适合画流程图、结构图或头脑风暴草图 |
| | | ,draw-things,ai-tools|picture-photo,productivity|development|media|picture-photo|ai-tools,media|picture-photo|ai-tools,null,本地 AI 绘图工具,直接在 Mac 上跑图像生成 |
| | | ,imazing,device-management,utilities,utilities|system-enhancement,null,iPhone 管理工具,适合备份、传输和管理 iOS 设备数据 |
| | | ,burp-suite,security,utilities,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,qmk-toolbox,device-management,utilities,utilities|system-enhancement,null,机械键盘固件工具,适合刷写和调试 QMK 固件 |
| | | ,smcfancontrol,device-management|system-maintenance,utilities,utilities|system-enhancement,null,电池或硬件状态工具,适合查看设备状态并辅助维护 |
| | | ,zenmap,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,prismlauncher,game,productivity,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,anytype,security|writing,writing|utilities|security,writing|security,null,本地优先的知识库和资料管理工具,强调隐私和结构化 |
| | | ,font-d2coding,Font,development|utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,ilspy,terminal-tools,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,font-caskaydia-cove-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,suspicious-package,Automation,utilities,productivity|system-enhancement,null,安装包检查工具,适合查看 pkg 安装内容和脚本 |
| | | ,winbox,network-tools|device-management,utilities,utilities|system-enhancement,null,MikroTik 路由器管理工具,适合配置和维护 RouterOS 设备 |
| | | ,cardinal-search,file-management,browser,file-management|utilities,null,文件管理工具,适合整理、传输或清理文件 |
| | | ,electerm,transfer|terminal-tools,file-management|transfer|development|utilities,transfer|development|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,gcenx-wine-game-porting-toolkit,game,utilities|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,gitbutler,Automation|devops,productivity|development,productivity|development|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,elgato-stream-deck,device-management|Automation,utilities,productivity|utilities|system-enhancement,null,快捷控制面板工具,适合直播、剪辑和自动化操作 |
| | | ,firefox-developer-edition,browser,browser|development,browser,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,cameracontroller,device-management,utilities,utilities|system-enhancement,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,blip,transfer,utilities,transfer|utilities,null,跨设备文件传输工具 |
| | | ,hyperkey,Automation,utilities,productivity|system-enhancement,null,快捷键增强工具,适合把 Caps Lock 改造成组合修饰键 |
| | | ,macos-fuse-t-cask-fuse-t-sshfs,file-management,utilities,file-management|utilities,null,FUSE 文件系统组件,适合让 macOS 挂载和访问扩展文件系统 |
| | | ,disk-drill,system-maintenance,utilities,utilities|system-enhancement,null,数据恢复工具,适合扫描和恢复误删文件 |
| | | ,font-monaspace,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,sioyek,education|PDF,design|education,writing|utilities|education,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,flashspace,window-management,utilities,utilities|system-enhancement,null,虚拟工作区管理工具 |
| | | ,google-earth-pro,education,utilities|education,education,null,学习工具,适合教育、参考或知识整理 |
| | | ,istat-menus,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,synology-drive,transfer|device-management,transfer|utilities,transfer|utilities|system-enhancement,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,font-sarasa-gothic,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,sol,Font|ui-prototyping|3d-cad,productivity,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,betterzip,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,coderabbit,ai-tools,development|ai-tools,ai-tools,null,把 AI 带进开发流程,适合写代码、调试和自动化 |
| | | ,popclip,Automation,utilities,productivity|system-enhancement,null,划词快捷操作工具,可对选中文本快速执行搜索、复制、翻译等动作 |
| | | ,font-maple-mono-nf,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,reaper,audio,development|media|audio,media|audio,null,专业数字音频工作站,录音、剪辑、编曲和混音都很灵活 |
| | | ,meshlab,system-maintenance,utilities,utilities|system-enhancement,null,3D 网格处理工具,适合查看、清理和处理三维模型 |
| | | ,tidal,video|audio,media|video|audio|entertainment,media|video|audio,null,高音质流媒体音乐服务,适合认真听歌的人 |
| | | ,marta,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,silicon-labs-vcp-driver,device-management,utilities,utilities|system-enhancement,null, |
| | | ,cool-retro-term,terminal-tools,development|utilities|system-enhancement,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,openlp,office,productivity,productivity|writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,slack-cli,communication,communication|productivity,communication,null,用命令行操作 Slack,适合把团队消息接进脚本流程 |
| | | ,font-iosevka-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,android-ndk,runtime-sdk,development|utilities,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,font-maple-mono,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,home-assistant,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,viber,communication|security,communication|utilities|security,communication|security,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,jdk-mission-control,window-management|runtime-sdk,utilities|system-enhancement,development|utilities|system-enhancement,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,paseo,ai-tools,development|ai-tools,ai-tools,null,AI 辅助开发工具,适合把模型接进代码工作流 |
| | | ,dot,communication,communication|productivity|utilities|system-enhancement,communication,null,菜单栏小工具入口,适合把常用动作收得更近 |
| | | ,dupeguru,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,font-ibm-plex-mono,Font,media|video|utilities|entertainment,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,retroarch,game,browser|media|video|entertainment|game,entertainment|game,null,统一模拟器前端,把复古游戏、核心和手柄配置收一起 |
| | | ,keyboard-maestro,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,postgres-app,database-tools,utilities,development,null,数据库工具,适合连接、查询和管理数据库 |
| | | ,hazel,Automation,utilities|system-enhancement,productivity|system-enhancement,null,为 Mac 设计的自动化文件组织工具 |
| | | ,mediainfo,video|audio,media|video|audio|utilities|system-enhancement,media|video|audio,null,查看媒体文件编码、码率和轨道信息的工具 |
| | | ,font-iosevka,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,macdroid,device-management|transfer,utilities,transfer|utilities|system-enhancement,null,Android 与 Mac 文件传输工具 |
| | | ,shortcutdetective,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,wch-ch34x-usb-serial-driver,device-management,utilities,utilities|system-enhancement,null, |
| | | ,gram,ai-tools,development|ai-tools,ai-tools,null,AI 开发工具,适合把智能能力嵌进产品和流程 |
| | | ,launchcontrol,devops,utilities,development,null,launchd 管理工具,适合创建、编辑和调试启动任务 |
| | | ,font-cascadia-code,Font|3d-cad,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,lyricsx,audio,media|audio|entertainment,media|audio,null,桌面歌词工具,听歌时同步显示歌词很舒服 |
| | | ,font-iosevka-term-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,dynamodb-local,database-tools|devops,utilities,development,null,本地 DynamoDB 环境,适合开发和测试 AWS 数据库应用 |
| | | ,neovide-app,ide,utilities,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,libreoffice-still,office,productivity,productivity|writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,font-fira-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,prince,writing,development|writing|utilities,writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,font-monaspice-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,nrfutil,terminal-tools|runtime-sdk,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,oracle-jdk,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,wpsoffice-cn,office,productivity,productivity|writing,null,效率工具,适合文档、记录或日常工作流 |
| | | ,font-dejavu,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-d2coding-nerd-font,Font,development|utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-roboto,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,wizcli,terminal-tools,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,parallels,devops,development|utilities,development,null,虚拟化或远程连接工具,适合运行系统环境和访问远程电脑 |
| | | ,font-geist-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,wpsoffice,office,productivity,productivity|writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,font-sf-pro,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,longbridge-tap-longbridge-terminal,terminal-tools,development|utilities|system,development,null, |
| | | ,font-hackgen-nerd,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,microsoft-openjdk-17,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,autodesk-fusion,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,font-noto-sans-cjk-sc,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,xld,audio,utilities,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,malwarebytes,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,font-sf-mono-nerd-font-ligaturized,Font,development|utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-noto-sans-cjk,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-noto-sans,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-ubuntu-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-roboto-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,oracle-jdk-25,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,font-geist-mono,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-victor-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,0-ad,game,utilities,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,font-montserrat,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-inconsolata-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-sf-mono,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-dejavu-sans-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-hack,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-source-sans-3,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-roboto-mono,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,floorp,browser|security,browser,browser|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,1password-cli-beta,security,utilities|security,security,null,命令行密钥和凭据管理工具测试版 |
| | | ,pluk-inc-tap-markdown-preview,writing,writing|media|picture-photo|utilities|system,writing,null, |
| | | ,font-code-new-roman-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-eb-garamond,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,notepadexe,ide,writing,development,null,轻量代码编辑器,适合编写和修改代码 |
| | | ,ytmdesktop-youtube-music,video|audio,media|video|audio|entertainment,media|video|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,qqmusic,audio,media|audio|entertainment,media|audio,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,font-zed-mono-nerd-font,Font,development|utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-3270-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-meslo-for-powerlevel10k,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-agave-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,openai-tools-openai,ai-tools|terminal-tools,utilities,development|ai-tools,null,命令行开发工具,适合调用和管理 AI 服务 |
| | | ,font-pretendard,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-mononoki-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-noto-sans-cjk-kr,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,edouard-claude-tap-snip,ai-tools,productivity|ai-tools,ai-tools,null,Claude 相关工具,适合 AI 辅助开发或内容处理 |
| | | ,microsoft-openjdk-25,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,font-lxgw-wenkai,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,ublue-os-tap-antigravity-linux,ai-tools,development|ai-tools,ai-tools,null, |
| | | ,azure-azure-cli-azure-cli-preview,Automation|terminal-tools|devops,media|picture-photo|utilities|system,productivity|development|system-enhancement,null,云资源命令行管理和自动化部署工具预览版 |
| | | ,font-commit-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-open-sans,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,google-cloud-sdk,terminal-tools|devops|runtime-sdk,utilities,development,null,Google Cloud 命令行工具集,适合管理云资源和部署应用 |
| | | ,gureumkim,input-tools,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,font-ibm-plex-sans,Font,media|video|utilities|entertainment,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,1password-tap-1password-cli,security,utilities|security,security,null, |
| | | ,font-terminess-ttf-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-space-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-hackgen,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-noto-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-lilex-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-anonymice-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-source-serif-4,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-noto-sans-cjk-jp,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-lato,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-gohufont-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,fontforge-app,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,font-adwaita-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-cousine-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,microsoft-openjdk-21,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,mhaeuser-mhaeuser-battery-toolkit,device-management|system-maintenance,utilities,utilities|system-enhancement,null,电池或硬件状态工具,适合查看设备状态并辅助维护 |
| | | ,app-cleaner,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,font-fontawesome,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-hasklug-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-bigblue-terminal-nerd-font,Font,development|utilities|system,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,oracle-jdk-21,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,font-fantasque-sans-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-noto-color-emoji,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,shortcat,device-management,utilities,utilities|system-enhancement,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,font-inconsolata,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-powerline-symbols,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-opendyslexic-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-hurmit-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,godot-mono,diagramming,development|entertainment|game,design,null,带 C# 支持的 Godot 版本,适合用 .NET 开发游戏 |
| | | ,font-bitstream-vera-sans-mono-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,font-monofur-nerd-font,Font,utilities,design|utilities,null,字体资源包,适合为编辑器、终端或设计工作补充字体 |
| | | ,android-sdk-platform-tools,device-management|runtime-sdk,development|utilities,development|utilities|system-enhancement,null,Android 开发工具,适合 adb 调试和设备管理 |
| | | ,flutter-sdk,runtime-sdk,utilities,development,null,跨平台应用开发工具包,适合构建移动、桌面和 Web 应用 |
| | | ,android-sdk-command-line-tools,terminal-tools|runtime-sdk,development|utilities,development,null,Android 命令行开发工具,适合构建和调试应用 |
| | | ,eclipse-temurin-21,terminal-tools|ide|runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,brave,browser|security,browser|utilities|security,browser|security,null,网页调试和浏览工具,适合开发者检查页面细节 |
| | | ,eclipse-temurin-8,terminal-tools|ide|runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,telegram-for-macos,communication|security,communication|utilities|security,communication|security,null, |
| | | ,freemacsoft-appcleaner,system-maintenance|ide,development|utilities,development|utilities|system-enhancement,null,应用卸载工具 |
| | | ,etcher,picture-photo,media|picture-photo|utilities,media|picture-photo,null,系统镜像写盘工具,制作启动 U 盘直观可靠 |
| | | ,microsoft-build-of-openjdk,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,emacs,ide,development|writing,development,null,文本编辑器,适合编辑纯文本、配置和轻量写作 |
| | | ,eclipse-temurin-11,terminal-tools|ide|runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,eclipse-temurin-25,terminal-tools|ide|runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,aws-corretto-jdk,devops|runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,mozilla-firefox-developer-edition,browser,browser|development,browser,null,面向开发者的 Firefox,网页调试功能更前沿 |
| | | ,burp-suite-community-edition,security,utilities|security,security,null,Web 安全测试工具包 |
| | | ,prism-launcher,game,productivity|writing|entertainment|game,entertainment|game,null,Minecraft 启动器,管理模组和多个游戏实例很方便 |
| | | ,zed-attack-proxy,api-tools,development|utilities,development,null, |
| | | ,wch-usb-serial-driver-for-ch340-ch341-ch342-ch343-ch344-ch9101-ch9102-ch9103-ch9143,device-management,utilities,utilities|system-enhancement,null, |
| | | ,amazon-corretto-jdk,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,macvim,ide,development|writing,development,null,文本编辑器,适合编辑纯文本、配置和轻量写作 |
| | | ,teleport-tsh,communication,communication|productivity,communication,null,Teleport 命令行入口,适合安全登录服务器和集群 |
| | | ,malwarebytes-for-mac,security,utilities|security,security,null, |
| | | ,floorp-browser,browser,browser|utilities|security,browser,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,youtube-music-desktop-app,audio,media|audio|entertainment,media|audio,null,YouTube Music 桌面封装,听歌时不用一直开浏览器 |
| | | ,opensc,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,sproutcube-shortcat,Automation|device-management,utilities|system-enhancement,productivity|utilities|system-enhancement,null,无需鼠标的界面操作工具 |
| | | ,heroic-games-launcher,game,productivity|entertainment|game,entertainment|game,null,GOG、Epic 等游戏库的开源启动器,跨平台管理更轻 |
| | | ,nektony-app-cleaner-and-uninstaller,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,应用卸载和清理助手 |
| | | ,freetube,security|entertainment,utilities|entertainment|security,entertainment|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,eclipse-memory-analyzer,system-maintenance,utilities,utilities|system-enhancement,null,Java 堆内存分析工具 |
| | | ,adobe-acrobat-pro-dc,writing,design|writing,writing,null, |
| | | ,gpg-suite-without-gpg-mail,communication|security,communication|utilities|security,communication|security,null, |
| | | ,bleunlock,device-management,utilities,utilities|system-enhancement,null,通过蓝牙低功耗设备距离锁定或解锁 Mac 的工具 |
| | | ,segger-j-link-command-line-tools,writing|terminal-tools,writing,development|writing,null, |
| | | ,qutebrowser,browser,browser|development|utilities|system-enhancement,browser,null,键盘驱动的浏览器,适合喜欢 Vim 操作的人 |
| | | ,jumpcut,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,剪贴板管理器,适合保存和找回复制历史 |
| | | ,netron,ai-tools,education,ai-tools,null,学习工具,适合查词、学习、参考或教育场景 |
| | | ,notepad-exe,ide,development|writing,development,null,轻量级代码编辑器 |
| | | ,wifiman-desktop,network-tools,utilities|system-enhancement,utilities,null, |
| | | ,disk-inventory-x,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,磁盘空间分析工具,适合查看和清理空间占用 |
| | | ,ollamac,ai-tools,development|ai-tools,ai-tools,null,Ollama 的 Mac 客户端,管理本地模型和聊天更直观 |
| | | ,neohtop,system-maintenance,utilities,utilities|system-enhancement,null,高级系统监控工具 |
| | | ,dash,writing|api-tools,browser|writing,development|writing,null,API 调试工具,适合测试接口、请求和开发流程 |
| | | ,topnotch,window-management|system-maintenance|ide,utilities|system-enhancement,development|utilities|system-enhancement,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,moom,communication|window-management,communication|productivity|utilities|system-enhancement,communication|utilities|system-enhancement,null,窗口管理工具,快速排列和保存窗口布局 |
| | | ,mountain-duck,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,tower,devops,productivity|development,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,folo,writing,browser,writing,null,效率工具,适合文档、记录或日常工作流 |
| | | ,iterm2-browser-plugin,browser,browser|development,browser,null,网页调试和浏览工具,适合开发者检查页面细节 |
| | | ,ente-auth,security,utilities,security,null,双因素验证码桌面客户端 |
| | | ,ukelele,input-tools,design|utilities|system-enhancement,utilities|system-enhancement,null,键盘布局编辑器,适合自定义输入法和键位 |
| | | ,vimr,ide,development|writing,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,keystore-explorer,terminal-tools,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,plexamp,audio,media|audio|entertainment,media|audio,null,Plex 音乐播放器,适合管理和播放自己的音乐库 |
| | | ,chrome-remote-desktop,network-tools,browser|utilities,utilities,null,通过 Chrome 远程访问其他电脑的工具 |
| | | ,logisim-evolution,Font|ui-prototyping|3d-cad|diagramming,development|design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,logitune,communication|device-management,communication|productivity|development|media|video|utilities|system-enhancement,communication|utilities|system-enhancement,null,管理罗技摄像头和耳机,开会前调设备很方便 |
| | | ,klogg,system-maintenance,utilities,utilities|system-enhancement,null,快速高级日志查看工具 |
| | | ,klayout,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,microsoft-office-businesspro,office,productivity,productivity|writing,null,办公套件,适合处理文档、表格和演示稿 |
| | | ,notion-mail,communication|Notes,productivity|writing,communication|productivity|writing,null,Notion 风格邮件工具,适合把邮件变成可整理的信息流 |
| | | ,gitify,devops,development|utilities|system-enhancement,development,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,clop,video|picture-photo,productivity|media|video|picture-photo|utilities|system-enhancement,media|video|picture-photo,null,自动压缩图片、视频和 PDF,拖进去就能瘦身文件 |
| | | ,weasis,picture-photo,media|picture-photo|utilities|system-enhancement,media|picture-photo,null,医学影像 DICOM 查看器,适合浏览和分析医疗影像 |
| | | ,asset-catalog-tinkerer,picture-photo,media|picture-photo|utilities,media|picture-photo,null,查看和导出 Xcode 资源目录,处理 App 素材很方便 |
| | | ,keybase,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,digikam,picture-photo,development|media|picture-photo,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,affinity-photo-2,picture-photo,design|media|picture-photo,media|picture-photo,null,专业修图工具,适合照片编辑、合成和精细调色 |
| | | ,maczip,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,soulseek,transfer,utilities,transfer|utilities,null,文件分享网络客户端 |
| | | ,keka-external-helper,file-management,utilities,file-management|utilities,null,Keka 压缩工具辅助应用 |
| | | ,timemachineeditor,transfer,transfer|utilities|system,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,teleport-connect,ide,browser|development,development,null,网页调试和浏览工具,适合开发者检查页面细节 |
| | | ,youtube-music,audio,media|audio|entertainment,media|audio,null,YouTube 音乐客户端,适合听歌、歌单和音乐视频 |
| | | ,macpass,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,apache-openoffice,office,productivity,productivity|writing,null, |
| | | ,steermouse,device-management,development|utilities|system-enhancement,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,msty,ai-tools,utilities|ai-tools,ai-tools,null,多模型 AI 客户端,适合统一管理本地和云端模型 |
| | | ,batfi,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,nodebox,Font|ui-prototyping|3d-cad|diagramming,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,playonmac,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,glance,picture-photo,media|picture-photo|utilities,media|picture-photo,null,Quick Look 扩展,让代码、图片和文档预览更好用 |
| | | ,wifi-explorer,network-tools,utilities|system-enhancement,utilities,null,Wi-Fi 扫描、监控和排障工具 |
| | | ,cinebench,device-management|system-maintenance,utilities,utilities|system-enhancement,null,硬件基准测试工具 |
| | | ,veracrypt-fuse-t,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,datadog-agent,security,utilities|system-enhancement|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,easyfind,file-management,utilities,file-management|utilities,null,文件、文件夹和全文搜索工具 |
| | | ,fuse-studio,file-management,utilities,file-management|utilities,null,FUSE 文件系统组件,适合让 macOS 挂载和访问扩展文件系统 |
| | | ,qflipper,device-management,utilities,utilities|system-enhancement,null,Flipper Zero 配套应用 |
| | | ,windterm,transfer|terminal-tools,file-management|transfer|development|utilities,transfer|development|utilities,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,camunda-modeler,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,awa,audio,media|audio|entertainment,media|audio,null,日本流媒体音乐服务,适合听歌和发现日系音乐 |
| | | ,pdfsam-basic,PDF,development|writing|utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,teleport,communication,communication|productivity,communication,null,沟通工具,适合消息、邮件、通话或团队交流 |
| | | ,vysor,network-tools|device-management,utilities,utilities|system-enhancement,null,手机投屏和控制工具 |
| | | ,freeplane,Notes,productivity,productivity|writing,null,效率工具,适合文档、记录或日常工作流 |
| | | ,uninstallpkg,system-maintenance,utilities,utilities|system-enhancement,null,PKG 软件包卸载工具 |
| | | ,clipgrab,video|transfer,transfer|media|video|audio|utilities,transfer|media|video|utilities,null,在线视频下载工具,适合保存公开视频素材 |
| | | ,keeper-password-manager,security,development|utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,opcode,ai-tools,development|ai-tools,ai-tools,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,macsyzones,window-management,utilities,utilities|system-enhancement,null,窗口管理工具 |
| | | ,adobe-digital-editions,devops,development|design,development,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,brave-nightly,browser|security,browser|utilities|security,browser|security,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,brave-beta,browser|security,browser|utilities|security,browser|security,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,openchamber,ai-tools,development|ai-tools,ai-tools,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,androidtool,device-management,utilities,utilities|system-enhancement,null,iOS 和 Android 设备录屏与应用安装工具 |
| | | ,notesnook,security|writing,writing|utilities|security,writing|security,null,适合写作、记录和处理文档 |
| | | ,yandex-cloud-cli,terminal-tools|devops,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,opera-gx,browser|entertainment,browser|entertainment|game,browser|entertainment,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,vibetunnel,terminal-tools,browser|development,development,null,把本地开发服务安全暴露出去,方便远程预览和调试 |
| | | ,lastpass,security,utilities|security,security,null,密码管理器,适合保存账号、密码和敏感信息 |
| | | ,luanti,game,media|audio|entertainment|game,entertainment|game,null,开源方块沙盒游戏平台,适合玩和制作类 Minecraft 世界 |
| | | ,electrum,security|finance,utilities|finance|security,finance|security,null,轻量比特币钱包,适合管理和签署 BTC 交易 |
| | | ,paste,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,box-drive,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,projectlibre,GTD,browser,productivity,null,效率工具,适合文档、记录或日常工作流 |
| | | ,wacom-tablet,device-management,utilities,utilities|system-enhancement,null, |
| | | ,devcleaner,ide,development|utilities,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,cavalry,Font|ui-prototyping|3d-cad|diagramming,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,nrf-command-line-tools,terminal-tools,utilities,development,null, |
| | | ,caido,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,standard-notes,security|writing,writing|utilities|security,writing|security,null,端到端加密笔记工具,适合保存私密文字和资料 |
| | | ,mediahuman-youtube-to-mp3-converter,audio|transfer,transfer|media|audio|utilities|entertainment,transfer|media|audio|utilities,null,把在线视频转成 MP3,适合保存音乐和播客音频 |
| | | ,modrinth-app,game,writing|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,bluetility,device-management,browser,utilities|system-enhancement,null,蓝牙低功耗设备浏览工具 |
| | | ,stash,security,utilities|security,security,null,安全相关工具,适合隐私保护、访问控制或账号防护 |
| | | ,ace-link,video,media|video|utilities|system-enhancement,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,vanilla,window-management|system-maintenance|ide,utilities|system-enhancement,development|utilities|system-enhancement,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,strawberry,audio,browser|media|picture-photo|ai-tools,media|audio,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,utools,Automation,productivity,productivity|system-enhancement,null,高效的工作助手,结合了人工智能技术,为用户提供一个多功能的入口 |
| | | ,spacedrive,file-management,utilities,file-management|utilities,null,开源跨平台文件管理器 |
| | | ,pdf-squeezer,PDF,utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,qobuz,audio,transfer|media|audio|utilities|entertainment,media|audio,null,高解析音乐服务,适合认真听歌和管理高音质曲库 |
| | | ,rustcast,Automation,productivity|utilities,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,kubecontext,Automation|devops,development|utilities|system-enhancement,productivity|development|system-enhancement,null,容器和集群管理工具,适合本地开发、镜像和 Kubernetes 工作流 |
| | | ,swiftdialog,communication|terminal-tools|runtime-sdk,communication|development|utilities,communication|development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,spotmenu,audio|system-maintenance,media|audio|utilities|system-enhancement|entertainment,media|audio|utilities|system-enhancement,null,菜单栏 Spotify 控制器,当前播放和切歌都更顺手 |
| | | ,textsniper,writing|picture-photo,development|writing|media|picture-photo|utilities,writing|media|picture-photo,null,截图识别文字工具,屏幕上的文字可以一键复制 |
| | | ,megacmd,terminal-tools,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,burp-suite-professional,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,prolific-usb-to-serial-cable-driver,device-management,utilities,utilities|system-enhancement,null, |
| | | ,webviewscreensaver,writing,writing|utilities|system-enhancement,writing,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,ea-app,game,productivity|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,rwts-pdfwriter,PDF|Notes,writing|utilities,productivity|writing|utilities,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,open-video-downloader,video|transfer,transfer|media|video|utilities|entertainment,transfer|media|video|utilities,null,开源视频下载器,适合保存公开视频素材 |
| | | ,macpacker,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,keepassx,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,notchi,ai-tools|window-management|system-maintenance,development|utilities|system-enhancement|ai-tools,utilities|system-enhancement|ai-tools,null,刘海区域美化工具,让菜单栏视觉更有趣 |
| | | ,vuescan,device-management,utilities,utilities|system-enhancement,null,扫描仪驱动和扫描软件,常用于支持旧款扫描仪 |
| | | ,finalshell,terminal-tools|devops,development|utilities,development,null,虚拟化或远程连接工具,适合运行系统环境和访问远程电脑 |
| | | ,processing,education,design|education,education,null,学习工具,适合查词、学习、参考或教育场景 |
| | | ,music-presence,video|audio,communication|media|video|audio,media|video|audio,null,把正在播放的音乐同步到状态,适合展示听歌动态 |
| | | ,synology-assistant,device-management,utilities,utilities|system-enhancement,null,局域网 Synology NAS 管理工具 |
| | | ,devonthink,PDF|Notes,writing,productivity|writing|utilities,null,个人知识资料库,适合收纳 PDF、网页和研究材料 |
| | | ,elgato-wave-link,device-management,utilities,utilities|system-enhancement,null,面向内容创作的音频控制软件 |
| | | ,katrain,game,entertainment|game|ai-tools,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,xca,security,utilities,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,graphql-playground,api-tools,productivity|development,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,insta360-link-controller,device-management,utilities,utilities|system-enhancement,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,safari-technology-preview,browser,browser|media|picture-photo,browser,null,网页浏览器,适合日常上网、访问网页和使用 Web 服务 |
| | | ,nordpass,security,utilities|security,security,null,密码管理器,适合保存账号、密码和敏感信息 |
| | | ,zoom-for-it-admins,Meeting,communication|productivity|media|video,communication|productivity,null,给 IT 管理员部署 Zoom,批量配置会议客户端更方便 |
| | | ,ftdi-vcp-driver,device-management,utilities,utilities|system-enhancement,null, |
| | | ,connectmenow,file-management,utilities,file-management|utilities,null,快速挂载网络共享的工具 |
| | | ,enpass,security,utilities|security,security,null,安全相关工具,适合隐私保护、访问控制或账号防护 |
| | | ,heynote,writing,development|writing,writing,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,transnomino,file-management,utilities,file-management|utilities,null,批量重命名工具 |
| | | ,bose-device-updater,device-management,utilities,utilities|system-enhancement,null,Bose 产品固件更新工具 |
| | | ,doxygen,ide|runtime-sdk,development|writing,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,elgato-control-center,device-management,utilities,utilities|system-enhancement,null,Elgato 灯光控制工具 |
| | | ,sunlogin-client,network-tools,utilities|system-enhancement,utilities,null,远程桌面控制和监控工具 |
| | | ,desktoppr,picture-photo|terminal-tools,media|picture-photo,development|media|picture-photo,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,tabula,GTD,utilities,productivity,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,piclist,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,miktex,system,system,utilities|system,null,TeX 发行版管理工具 |
| | | ,a-better-finder-rename,file-management,file-management|media|audio|picture-photo|utilities,file-management|utilities,null,批量重命名工具,整理照片和文件特别省时间 |
| | | ,updf,PDF,utilities,writing|utilities,null,PDF 编辑工具,适合编辑、标注和处理 PDF 文档 |
| | | ,clipbook,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,clockify,GTD,utilities,productivity,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,hp-easy-start,device-management,utilities,utilities|system-enhancement,null,HP 打印机设置工具 |
| | | ,launchie,Automation,utilities,productivity|system-enhancement,null,快速高效的应用启动器,专为macOS用户设计,旨在提升工作流程的效率 |
| | | ,actual,finance,utilities|finance,finance,null,本地优先的预算记账工具,适合认真管理个人现金流 |
| | | ,json-viewer,ide,utilities,development,null,JSON 数据可视化、校验和格式化工具 |
| | | ,shapr3d,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,dropzone,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,plistedit-pro,ide,utilities,development,null,plist 和 JSON 编辑器 |
| | | ,winzip,file-management,utilities,file-management|utilities,null,文件压缩归档工具 |
| | | ,trezor-suite,finance|device-management,utilities|finance,utilities|system-enhancement|finance,null,Trezor 硬件钱包管理器,安全查看和签署交易 |
| | | ,aliyundrive,transfer,file-management|transfer|utilities,transfer|utilities,null,智能云存储客户端 |
| | | ,pocket-casts,audio,media|audio|entertainment,media|audio,null,播客客户端,订阅、收听和同步节目都很顺 |
| | | ,kando,Automation,utilities,productivity|system-enhancement,null,开源环形菜单启动器,用于快速执行应用和系统操作 |
| | | ,min,browser|security,browser|utilities|security,browser|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,qqlive,video,media|video|entertainment,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,t3-code-nightly,ai-tools,development|ai-tools,ai-tools,null,AI 代码智能体轻量图形界面 |
| | | ,contexts,window-management,utilities,utilities|system-enhancement,null,应用窗口切换工具 |
| | | ,whatsize,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,derivative-touchdesigner,ide,development|design,development,null,动态数字艺术创作工具 |
| | | ,vibe-island,ai-tools,utilities|ai-tools,ai-tools,null,动态岛 AI 智能体工具 |
| | | ,elgato-camera-hub,device-management,utilities,utilities|system-enhancement,null, |
| | | ,pieces,picture-photo,productivity|media|picture-photo,media|picture-photo,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,quicksilver,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,enjoyable,device-management,utilities|system-enhancement|entertainment|game,utilities|system-enhancement,null,手柄映射工具,把游戏控制器变成键盘鼠标输入 |
| | | ,tuxera-ntfs,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,nutstore,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,nuclear,audio,media|audio|entertainment,media|audio,null,开源音乐播放器,从多个在线来源聚合音乐 |
| | | ,wox,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,fontbase,Font,utilities,design|utilities,null,适合管理字体、预览字形和整理设计字库 |
| | | ,istat-server,file-management|system-maintenance,file-management|utilities,file-management|utilities|system-enhancement,null,文件管理工具,适合整理、传输或清理文件 |
| | | ,mythic,game,productivity|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,yubiswitch,security,utilities,security,null,Yubikey Nano 开关菜单栏工具 |
| | | ,auto-claude,ai-tools,development|ai-tools,ai-tools,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,lyric-fever,audio,media|audio|entertainment,media|audio,null,动态歌词显示工具,让听歌时的歌词更醒目 |
| | | ,djview,picture-photo,browser,media|picture-photo,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,silentknight,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,nvidia-nsight-systems,ide,utilities,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,shichizip,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,stay,window-management,utilities,utilities|system-enhancement,null, |
| | | ,classicftp,transfer,file-management|transfer|utilities,transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,macx-youtube-downloader,video|transfer,transfer|media|video|utilities|entertainment,transfer|media|video|utilities,null,YouTube 视频下载工具,适合保存公开视频素材 |
| | | ,xcodepilot,ide,productivity|development,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,polypane,browser,browser|development,browser,null,网页调试和浏览工具,适合开发者检查页面细节 |
| | | ,launchbar,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,etrecheck,system-maintenance,utilities,utilities|system-enhancement,null,系统问题检测和修复工具 |
| | | ,fvim,ide,development|writing,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,yandex-disk,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,netiquette,network-tools,utilities|system-enhancement,utilities,null,网络监控工具,适合查看连接状态和排查网络问题 |
| | | ,exifcleaner,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,4k-youtube-to-mp3,audio,entertainment,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,music-decoy,audio|Automation,media|audio|utilities,productivity|media|audio|system-enhancement,null,音乐占位工具,适合配合媒体键和播放状态工作流 |
| | | ,clibor-for-mac,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null, |
| | | ,1clipboard,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,langflow-desktop,ai-tools|GTD,productivity|development|ai-tools,productivity|ai-tools,null,可视化搭建 AI 工作流,把模型、工具和数据连起来 |
| | | ,crosspaste,Automation,utilities,productivity|system-enhancement,null,跨设备通用剪贴板工具 |
| | | ,avg-antivirus-for-mac,security,utilities,security,null, |
| | | ,eltima-cloudmounter,transfer,file-management|transfer|utilities,transfer|utilities,null,将云存储挂载为本地磁盘的工具 |
| | | ,jupyter-notebook-viewer,writing,writing|utilities,writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,butler,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,mumble,communication,communication|entertainment|game,communication,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,yattee,security|entertainment,utilities|entertainment|security,entertainment|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,agentsview,ai-tools,development|ai-tools,ai-tools,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,mac-media-key-forwarder,audio,media|audio|entertainment,media|audio,null,把媒体键转发给指定播放器,控制音乐更稳定 |
| | | ,nimbalyst,ai-tools,development|ai-tools,ai-tools,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,framer,communication|ui-prototyping,communication|productivity|design,communication|design,null,交互原型和网站设计工具,适合把想法快速做成可体验页面 |
| | | ,lunarbar,communication|window-management,communication|productivity|utilities|system-enhancement,communication|utilities|system-enhancement,null,菜单栏月相工具,适合快速查看月亮状态和天文节律 |
| | | ,hapigo,Automation,productivity,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,master-pdf-editor,PDF,utilities,writing|utilities,null,PDF 编辑工具,适合编辑、标注和处理 PDF 文档 |
| | | ,atuin-desktop,terminal-tools,productivity|development,development,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,rive,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,wirecast,video,media|video|entertainment,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,salt,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,au-lab,audio,development|media|audio,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,idevice-pair,device-management,utilities,utilities|system-enhancement,null,iOS 设备配对记录生成工具 |
| | | ,maintenance,system-maintenance,utilities,utilities|system-enhancement,null,系统维护和清理工具 |
| | | ,namechanger,file-management,utilities,file-management|utilities,null,批量文件重命名工具 |
| | | ,snes9x,game,media|video|system|entertainment|game,entertainment|game,null,Super Nintendo 模拟器,适合重温经典主机游戏 |
| | | ,nordlayer,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,qt-design-studio,Font|ui-prototyping|3d-cad,development|design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,stability-matrix,ai-tools|communication,communication|development|ai-tools,communication|ai-tools,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,blockbench,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,siliconmotion-instantview,device-management,utilities,utilities|system-enhancement,null,SM76x 驱动和图形界面 |
| | | ,filen,file-management,utilities,file-management|utilities,null,云存储桌面客户端 |
| | | ,8bitdo-ultimate-software,device-management,utilities,utilities|system-enhancement,null,游戏手柄配置工具 |
| | | ,network-radar,network-tools,utilities|system-enhancement,utilities,null,网络扫描和监控工具 |
| | | ,appvolume,audio,utilities,media|audio,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,ubiquiti-unifi-network-controller,device-management,utilities,utilities|system-enhancement,null, |
| | | ,manus,ai-tools,productivity|ai-tools,ai-tools,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,transfer,transfer,file-management|transfer|utilities,transfer|utilities,null,为Mac设计的多协议文件服务器,现代且可靠 |
| | | ,ubar,window-management,productivity|utilities|system-enhancement,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,browserstack-local-testing,browser|devops|api-tools,browser,browser|development,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,forecast,audio,media|audio|entertainment,media|audio,null,播客章节编辑工具,给音频节目加章节和元数据 |
| | | ,figma-agent,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,pacifist,picture-photo,media|picture-photo|utilities,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,lunacy,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,foxit-pdf-editor,PDF,utilities,writing|utilities,null,PDF 编辑器,适合修改、批注、签署和整理 PDF |
| | | ,pdfify,PDF,utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,focusrite-control,device-management,utilities,utilities|system-enhancement,null,第四代及更新 Focusrite 声卡控制工具 |
| | | ,replacicon,picture-photo,media|picture-photo|utilities,media|picture-photo,null,针对macOS的应用程序,旨在帮助用户轻松找到和更换Mac应用图标 |
| | | ,avast-security,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,qnap-qfinder-pro,file-management|device-management,file-management|utilities,file-management|utilities|system-enhancement,null,NAS 管理工具 |
| | | ,uefitool,picture-photo,media|picture-photo|utilities,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,menial-base,database-tools,development|design,development,null,SQLite 3 数据库创建、设计和浏览工具 |
| | | ,imazing-profile-editor,device-management,utilities,utilities|system-enhancement,null,Apple 设备配置描述文件编辑器 |
| | | ,netflix,video,browser|entertainment,media|video,null,影音流媒体桌面客户端 |
| | | ,textexpander,Automation,utilities,productivity|system-enhancement,null,文本片段扩展工具 |
| | | ,k6-studio,Automation,utilities,productivity|system-enhancement,null,k6 测试脚本生成工具 |
| | | ,cleanmymac-x-chinese,system-maintenance,utilities,utilities|system-enhancement,null,磁盘垃圾清理工具中文版 |
| | | ,dadroit-json-viewer,ide,utilities,development,null,JSON 查看器 |
| | | ,threema,communication|security,communication|utilities|security,communication|security,null,端到端加密即时通讯工具,适合安全聊天 |
| | | ,airdroid,device-management,utilities,utilities|system-enhancement,null,移动设备管理套件 |
| | | ,signal-beta,communication|security,communication|utilities|security,communication|security,null,注重安全的即时通讯应用 |
| | | ,lunar-client,game,writing|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,hovrly,ide,development|utilities|system-enhancement,development,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,brew-services-menubar,window-management|system-maintenance,utilities,utilities|system-enhancement,null, |
| | | ,clamxav,security,utilities,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,container-ps,Automation|devops,development|media|picture-photo|utilities|system-enhancement,productivity|development|system-enhancement,null,容器和集群管理工具,适合本地开发、镜像和 Kubernetes 工作流 |
| | | ,nook,GTD,browser|design,productivity,null,专注式浏览器工作区,适合把网页资料按项目整理 |
| | | ,prettyclean,system-maintenance,utilities,utilities|system-enhancement,null,易用磁盘清理工具 |
| | | ,apptamer,system-maintenance,utilities,utilities|system-enhancement,null,CPU 资源管理工具 |
| | | ,thor,Automation,utilities,productivity|system-enhancement,null,应用快速切换工具 |
| | | ,livebook,writing,development|writing,writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,adobe-creative-cloud-cleaner-tool,file-management,design|utilities,file-management|utilities,null,清理 Adobe 安装残留,修复 Creative Cloud 玄学问题 |
| | | ,fleet,ide,development|writing,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,fldigi,audio,development|media|audio,media|audio,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,fathom,ai-tools|Meeting,communication|productivity|media|video,communication|productivity|ai-tools,null,AI 会议记录工具,自动生成纪要和行动项 |
| | | ,keycue,Automation|device-management,utilities|system-enhancement,productivity|utilities|system-enhancement,null,用于macOS的实用软件,它可以帮助用户更轻松地找到和使用键盘快捷键 |
| | | ,rode-central,device-management,utilities,utilities|system-enhancement,null,RØDE 设备配套应用 |
| | | ,tikzit,Font|ui-prototyping|3d-cad|diagramming,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,qtpass,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,pdf-images,picture-photo|PDF,media|picture-photo,writing|media|picture-photo|utilities,null, |
| | | ,gaphor,ui-prototyping|diagramming,utilities,design,null,设计工具,适合图形、界面或视觉创作 |
| | | ,activedock,window-management,productivity|utilities|system-enhancement,utilities|system-enhancement,null,Dock 替代工具,提供窗口预览和应用管理增强 |
| | | ,gpgfrontend,security|finance,utilities|finance|security,finance|security,null,GPG 图形界面,适合加密、签名和管理密钥 |
| | | ,fontgoggles,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,restic-browser,browser|security,browser|transfer|utilities,browser|security,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,mountmate,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,stoplight-studio,writing,design|writing,writing,null,API 调试工具,适合测试接口、请求和开发流程 |
| | | ,mission-control-plus,window-management,utilities,utilities|system-enhancement,null,Mission Control 窗口管理工具 |
| | | ,sonobus,audio,media|audio|entertainment,media|audio,null,低延迟网络音频工具,远程合奏和实时传声很实用 |
| | | ,yubikey-manager,security,utilities|security,security,null, |
| | | ,fx-cast-bridge,video,browser,media|video,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,izip,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,ibm-semeru-runtime-jdk-8-open-edition,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,oka-unarchiver,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,ios-app-signer,security,utilities,security,null,iOS 应用重签名和打包工具 |
| | | ,scrapp,picture-photo|transfer,file-management|transfer|media|picture-photo|utilities,transfer|media|picture-photo|utilities,null,适合截图、标注、识别文字或制作视觉反馈 |
| | | ,mousepose,device-management,development|utilities|system-enhancement,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,viz,video|picture-photo,media|video|picture-photo|utilities,media|video|picture-photo,null,轻量图像查看工具,适合快速翻看图片素材 |
| | | ,airtable,ide,productivity|development,development,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,mochi-diffusion,ai-tools,development|ai-tools,ai-tools,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,realm-studio,ai-tools|database-tools,development|utilities|ai-tools,development|ai-tools,null,Realm 数据库查看工具,适合调试移动端本地数据 |
| | | ,protopie,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,surge-xt,security,utilities|security,security,null,安全相关工具,适合隐私保护、访问控制或账号防护 |
| | | ,vibeproxy,ai-tools|Automation,development|utilities|system-enhancement|ai-tools,productivity|system-enhancement|ai-tools,null,AI 开发代理工具,适合把模型接进本地工作流 |
| | | ,serverbox,transfer|network-tools|devops,file-management|transfer|development|utilities|system-enhancement,transfer|development|utilities,null,带 SSH、SFTP 和容器管理的服务器监控工具 |
| | | ,wakatime,GTD,utilities,productivity,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,systhist,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,focusrite-control-2,device-management,utilities,utilities|system-enhancement,null, |
| | | ,memory-cleaner,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输或清理文件 |
| | | ,garmin-connect-iq-sdk,runtime-sdk,utilities,development,null,可穿戴设备应用开发工具 |
| | | ,paletro,diagramming,utilities,design,null,macOS 应用,提供快速访问当前使用应用菜单命令的功能 |
| | | ,sidekick,browser,browser|design,browser,null,工作流浏览器,适合把常用 SaaS 和网页应用放一起 |
| | | ,tabtab,transfer,utilities,transfer|utilities,null,专为Mac设计的强大窗口和标签页管理工具,旨在提升用户生产力 |
| | | ,dangerzone,PDF,productivity|writing,writing|utilities,null,把可疑文档转成安全 PDF,适合处理不可信附件 |
| | | ,canon-eos-utility,device-management,utilities,utilities|system-enhancement,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,machoview,ide,browser|file-management|utilities,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,webex-meetings,Meeting,communication|productivity|media|video,communication|productivity,null,Webex 会议客户端,适合企业远程会议和线上沟通 |
| | | ,weka,ai-tools|education,productivity|education,education|ai-tools,null,机器学习教学和实验工具,拖拽就能做数据挖掘 |
| | | ,ff-works,video,development|media|video,media|video,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,vieb,browser,browser|development,browser,null,Vim 风格浏览器,键盘浏览和网页操作效率很高 |
| | | ,neat,ide,productivity|development|utilities|system-enhancement,development,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,cd-to,file-management,file-management|development|utilities,file-management|utilities,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,phoenix,window-management|Automation,utilities,productivity|utilities|system-enhancement,null,可用 JavaScript 脚本化的窗口和应用管理器 |
| | | ,atext,Automation,utilities,productivity|system-enhancement,null,功能强大的文本工具,集文本模板、文本快捷方式、文本宏以及文本自动化于一身 |
| | | ,superkey,Automation,utilities,productivity|system-enhancement,null,屏幕文字搜索和点击工具 |
| | | ,lando,Automation|devops,development|utilities|system-enhancement,productivity|development|system-enhancement,null,容器和集群管理工具,适合本地开发、镜像和 Kubernetes 工作流 |
| | | ,xee3,picture-photo|file-management,browser|file-management|media|picture-photo|utilities,file-management|media|picture-photo|utilities,null, |
| | | ,ibm-semeru-runtime-jdk-21-open-edition,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,aloha-browser,browser|security,browser|utilities|security,browser|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,cpu-info,device-management|system-maintenance,utilities,utilities|system-enhancement,null,设备硬件和软件信息查看工具 |
| | | ,beaver-notes,security|writing,writing|utilities|security,writing|security,null,适合写作、记录和处理文档 |
| | | ,ok-json,Automation,utilities,productivity|system-enhancement,null,可脚本化 JSON 格式化和编辑工具 |
| | | ,zipic,picture-photo,media|picture-photo|utilities,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,franz,communication,communication|productivity,communication,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,inkstitch,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,pareto-security,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,comprehensive-kerbal-archive-network,file-management,utilities,file-management|utilities,null, |
| | | ,hush,browser|security,browser|utilities|security,browser|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,lingon-x,system,system,utilities|system,null,强大的工具,允许用户完全控制系统中程序的自动启动 |
| | | ,structured-log-viewer,system-maintenance,utilities,utilities|system-enhancement,null,MSBuild 结构化日志查看器 |
| | | ,davmail,communication,communication|productivity,communication,null,把 Exchange 服务转成标准协议,方便老客户端接入 |
| | | ,pingplotter,network-tools,utilities|system-enhancement,utilities,null,网络监控工具 |
| | | ,disk-expert,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,yakit,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,oss-browser,browser|security,browser,browser|security,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,yippy,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,mediahuman-youtube-downloader,video|transfer,transfer|media|video|utilities|entertainment,transfer|media|video|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,meta,audio,development|media|audio,media|audio,null,专为macOS设计的智能音乐标签编辑器,旨在简化音频元数据的编辑过程 |
| | | ,dmenu-mac,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,wire,security,utilities|security,security,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,freepdf,PDF|Notes,writing,productivity|writing|utilities,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,box-tools,file-management,browser,file-management|utilities,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,vivaldi-snapshot,browser,browser|communication,browser,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,freeze,transfer,file-management|transfer|utilities,transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,scoot,ide,development|utilities|system-enhancement,development,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,vibe-notch,ai-tools|window-management|system-maintenance,development|utilities|system-enhancement|ai-tools,utilities|system-enhancement|ai-tools,null,把 Mac 刘海变成动态状态区,给桌面加一点趣味 |
| | | ,cad-assistant,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,usb-overdrive,device-management,utilities,utilities|system-enhancement,null,USB 和蓝牙设备驱动工具 |
| | | ,mindwtr,Notes,productivity,productivity|writing,null,效率工具,适合文档、记录或日常工作流 |
| | | ,wiso-steuer-2026,finance,utilities,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,zspace,device-management,utilities,utilities|system-enhancement,null,NAS 客户端 |
| | | ,backuploupe,transfer,transfer|utilities|system,transfer|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,keyguard,security,utilities|security,security,null,安全相关工具,适合隐私保护、访问控制或账号防护 |
| | | ,nvidia-sync,transfer|Automation|devops,transfer|development|utilities,productivity|transfer|development|utilities|system-enhancement,null,容器和集群管理工具,适合本地开发、镜像和 Kubernetes 工作流 |
| | | ,qnap-qsync,transfer|device-management,transfer|utilities,transfer|utilities|system-enhancement,null,自动文件同步工具 |
| | | ,combine-pdfs,PDF,utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,customshortcuts,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,timemachinestatus,system-maintenance,utilities|system|system-enhancement,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,kdrive,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,pikpak,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,1password-nightly,security,utilities|security,security,null,密码管理器 |
| | | ,expandrive,transfer,browser|file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,pastebot,Automation,productivity,productivity|system-enhancement,null,针对频繁使用复制粘贴功能的用户设计的提高工作效率的必备工具 |
| | | ,voov-meeting,Meeting,communication|productivity|media|video,communication|productivity,null,腾讯会议国际版,适合跨地区视频会议和协作 |
| | | ,psst,audio,media|audio|entertainment,media|audio,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,houdahspot,file-management,utilities,file-management|utilities,null,文件搜索工具 |
| | | ,diskspace,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,pdf-reader-pro,picture-photo|PDF,utilities,writing|media|picture-photo|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,chromium-gost,browser|security,browser|finance,browser|security,null,带 GOST 加密支持的 Chromium,适合特定合规浏览需求 |
| | | ,hidock,window-management,development|utilities|system-enhancement,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,zappy,picture-photo|communication,communication|productivity|media|picture-photo,communication|media|picture-photo,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,easyeda,Font|ui-prototyping|3d-cad|diagramming,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,hive,ai-tools,development|ai-tools,ai-tools,null,跨项目并行编码 AI 智能体编排工具 |
| | | ,icanhazshortcut,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,keeweb,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,unpkg,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,radio-silence,security,media|audio|utilities|system-enhancement|security,security,null,出站防火墙工具,阻止 App 悄悄联网 |
| | | ,streamlink-twitch-gui,video,browser|entertainment,media|video,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,anybar,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,bitwig-studio,audio,development|media|audio,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,the-time-machine-mechanic,system,system,utilities|system,null,Time Machine 日志和状态检查工具 |
| | | ,sonixd,audio,media|audio|entertainment,media|audio,null,Subsonic 音乐客户端,适合播放自建音乐库 |
| | | ,bitbar,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,appzapper,system-maintenance,utilities,utilities|system-enhancement,null, |
| | | ,pastenow,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,Mac剪贴板管理工具,支持多设备数据同步和历史数据的重复使用 |
| | | ,tickeys,audio,media|audio|utilities,media|audio,null,给键盘输入加打字音效,让敲字更有仪式感 |
| | | ,reflex,audio,media|audio|entertainment,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,pdf-toolbox,PDF,utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,tag-editor,audio,productivity|media|audio,media|audio,null,电子表格式音频标签编辑器 |
| | | ,multi-mc,game,productivity|writing|entertainment|game,entertainment|game,null,Minecraft 多实例启动器,模组管理更清楚 |
| | | ,jami,communication|transfer,file-management|transfer|utilities,communication|transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,cmd,ai-tools,development|ai-tools,ai-tools,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,telegram-a,communication|security,communication|utilities|security,communication|security,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,sizeup,window-management,utilities,utilities|system-enhancement,null,窗口缩放和定位工具 |
| | | ,drata-agent,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,orka-desktop,picture-photo,media|picture-photo|utilities,media|picture-photo,null,虚拟化或远程连接工具,适合运行系统环境和访问远程电脑 |
| | | ,aquamacs,ide,development|writing,development,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,landrop,transfer,utilities,transfer|utilities,null,局域网跨设备文件传输工具 |
| | | ,sculptor,ai-tools,development|ai-tools,ai-tools,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,softmaker-freeoffice,office,productivity,productivity|writing,null,办公套件,适合处理文档、表格和演示稿 |
| | | ,silicon,system-maintenance,utilities,utilities|system-enhancement,null,Intel-only 应用识别工具 |
| | | ,simplemind,Notes,productivity,productivity|writing,null,效率工具,适合文档、记录或日常工作流 |
| | | ,murus-firewall,security,utilities|security,security,null,防火墙工具 |
| | | ,abbyy-finereader-pdf,picture-photo|PDF,writing,writing|media|picture-photo|utilities,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,gamemaker,game,development|entertainment|game,entertainment|game,null,2D 游戏制作工具,适合快速做原型和发布小游戏 |
| | | ,advanced-renamer,file-management,utilities,file-management|utilities,null,批量文件重命名工具 |
| | | ,ibm-semeru-runtime-jdk-17-open-edition,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,bluej,Font|ui-prototyping|3d-cad|ide,development|design,development|design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,calendar-366-ii,communication|GTD,communication|productivity|utilities|system-enhancement,communication|productivity,null,菜单栏日历和日程工具,适合快速查看安排 |
| | | ,sony-imaging-edge-desktop,picture-photo,browser|media|picture-photo,media|picture-photo,null, |
| | | ,osxfuse,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,neofinder,file-management,file-management|development|utilities,file-management|utilities,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,gpodder,audio,media|audio|entertainment,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,eez-studio,Automation,productivity|development|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,name-mangler,file-management,utilities,file-management|utilities,null,批量文件重命名工具 |
| | | ,assinador-serpro,writing,development|writing,writing,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,defold,game,development|entertainment|game,entertainment|game,null,轻量游戏引擎,适合跨平台 2D 游戏开发 |
| | | ,fido2-1-security-key-management-tool,security,utilities|security,security,null, |
| | | ,propresenter,office,productivity,productivity|writing,null,跨平台(Mac和Windows)的演示软件和现场活动制作应用程序 |
| | | ,anypoint-studio,terminal-tools|ide|runtime-sdk,development|design,development,null,用于设计和测试 Mule 应用的 Eclipse IDE |
| | | ,epic-privacy-browser,browser|security,browser|utilities|security,browser|security,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,wifi-explorer-pro,network-tools,utilities|system-enhancement,utilities,null, |
| | | ,exifrenamer,file-management|picture-photo,development|media|video|audio|picture-photo,file-management|media|picture-photo|utilities,null,按 EXIF 信息批量重命名照片和视频,整理素材更快 |
| | | ,paranoia-file-and-text-encryption,security|finance,utilities|finance|security,finance|security,null,文件和文本加密工具,适合临时保护敏感内容 |
| | | ,protokol,audio,media|audio|utilities|system-enhancement,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,shureplus-motiv,device-management,utilities,utilities|system-enhancement,null,Shure MV7 和 MV88+ 麦克风控制工具 |
| | | ,autodesk-eagle,3d-cad,productivity|file-management|design|utilities|system-enhancement,design,null,电路设计工具,适合画原理图和 PCB |
| | | ,hp-easy-admin,transfer|device-management,transfer|utilities,transfer|utilities|system-enhancement,null,传输工具,适合下载、同步或共享文件 |
| | | ,xprocheck,security,utilities,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,rockbox-utility,audio,development|media|audio|utilities,media|audio,null, |
| | | ,dungeon-crawl-stone-soup,game,media|picture-photo|system|entertainment|game,entertainment|game,null,硬核 Roguelike 地牢游戏,适合喜欢策略探索的人 |
| | | ,solvespace,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,profind,file-management,utilities,file-management|utilities,null,文件搜索应用 |
| | | ,tresorit,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,yggdrasil,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,jbrowse,education,browser,education,null,学习工具,适合教育、参考或知识整理 |
| | | ,macwinzipper,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,pokemon-trading-card-game-live,game,entertainment|game|finance,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,spline,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,mcedit-unified,game,writing|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,presentify,communication|office,communication|productivity|development,communication|productivity|writing,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,script-kit,Automation,utilities,productivity|system-enhancement,null,脚本创建和运行工具 |
| | | ,xmenu,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,glkvm,device-management,utilities,utilities|system-enhancement,null,GL.iNet KVM 设备控制工具 |
| | | ,sherlock,terminal-tools,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,melodics,education,utilities,education,null,学习工具,适合教育、参考或知识整理 |
| | | ,ibm-semeru-runtime-jdk-25-open-edition,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,loupdeck,system,system,utilities|system,null, |
| | | ,aide,ai-tools,development|ai-tools,ai-tools,null, |
| | | ,sigdigger,communication,communication|development,communication,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,tartelet,devops,development|utilities,development,null,虚拟化或远程连接工具,适合运行系统环境和访问远程电脑 |
| | | ,silhouette-studio,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,charmstone,Automation,productivity,productivity|system-enhancement,null,小而强大的生产力工具,能够显著提升用户的工作效率 |
| | | ,label-live,diagramming,design|utilities,design,null,标签设计和打印工具,适合电商、仓储和物流贴纸 |
| | | ,diskcatalogmaker,system-maintenance,utilities,utilities|system-enhancement,null,磁盘管理工具 |
| | | ,sejda-pdf-desktop,PDF,utilities,writing|utilities,null,PDF 编辑器 |
| | | ,spacelauncher,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,mutedeck,Meeting,communication|productivity|media|video,communication|productivity,null,菜单栏会议控制器,静音和摄像头状态一眼可见 |
| | | ,gotomeeting,Meeting,communication|productivity|media|video,communication|productivity,null,在线会议工具,适合远程沟通和商务演示 |
| | | ,fastscripts,Automation,utilities,productivity|system-enhancement,null,快捷脚本运行工具 |
| | | ,visual,education,utilities,education,null,学习工具,适合查词、学习、参考或教育场景 |
| | | ,flykey,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,canon-ufr-ii-ufrii-lt-lipslx-carps2-printer-driver,picture-photo|device-management,productivity|media|picture-photo|utilities,media|picture-photo|utilities|system-enhancement,null,佳能打印驱动包,保证办公打印机在 Mac 上正常工作 |
| | | ,dante-controller,device-management,utilities,utilities|system-enhancement,null, |
| | | ,birdfont,Font,utilities,design|utilities,null,字体编辑工具,适合设计、修改和检查字体 |
| | | ,gpg-suite-pinentry,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,eset-cyber-security,communication|security,communication|utilities|security,communication|security,null,邮件客户端,适合集中收发和管理邮箱 |
| | | ,ringcentral,Meeting,communication|productivity|media|video,communication|productivity,null,企业通信平台,电话、消息和视频会议集中处理 |
| | | ,radar,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,rode-connect,audio,media|audio|entertainment,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,commandpost,video,productivity|media|video,media|video,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,digital,devops,development|design,development,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,atlauncher,game,productivity|writing|entertainment|game,entertainment|game,null,Minecraft 启动器,管理整合包、模组和多个实例 |
| | | ,plasticity,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,freeshow,office,productivity,productivity|writing,null,演示工具,适合制作展示内容或现场演示 |
| | | ,riverside-studio,video|audio,media|video|audio|entertainment,media|video|audio,null,远程录音录像工具,适合播客、访谈和视频节目 |
| | | ,get-iplayer-automator,transfer,transfer|utilities|system,transfer|utilities,null,传输工具,适合下载、同步或共享文件 |
| | | ,nitro-pdf-pro,PDF,utilities,writing|utilities,null,允许用户轻松编辑PDF文件 |
| | | ,typeface,Font,utilities,design|utilities,null,适合管理字体、预览字形和整理设计字库 |
| | | ,opera-developer,browser,browser|development,browser,null,网页调试和浏览工具,适合开发者检查页面细节 |
| | | ,rightfont,picture-photo|transfer|Font,transfer|media|picture-photo|utilities,transfer|design|media|picture-photo|utilities,null,字体管理工具,设计时找字、启用字都更快 |
| | | ,shell360,transfer|terminal-tools,file-management|transfer|development|utilities,transfer|development|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,glyphs,Font,utilities,design|utilities,null,字体编辑工具,适合设计、修改和检查字体 |
| | | ,crypter,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,pdf-converter-master,PDF|Notes,writing,productivity|writing|utilities,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,font-smoothing-adjuster,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,novabench,system-maintenance,utilities,utilities|system-enhancement,null,电脑性能快速基准测试工具 |
| | | ,jottacloud,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,sipgate,communication,file-management|transfer|media|picture-photo|utilities,communication,null,VoIP 电话服务客户端,适合网络电话和商务通信 |
| | | ,plex-htpc,video,media|video|entertainment,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,notesollama,ai-tools|writing,development|writing|ai-tools,writing|ai-tools,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,accessmenubarapps,Automation|window-management,utilities,productivity|utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,wiso-steuer-2025,finance,utilities,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,egnyte,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,pdfpen,PDF,utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,pitch,office,productivity,productivity|writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,cadreader,picture-photo|3d-cad,media|picture-photo,design|media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,gimp-development-version,picture-photo,development|media|picture-photo,media|picture-photo,null,免费开源图像编辑器 |
| | | ,roam,Notes,productivity,productivity|writing,null,效率工具,适合文档、记录或日常工作流 |
| | | ,termius-beta,network-tools|terminal-tools,utilities,development|utilities,null,终端或 SSH 客户端 |
| | | ,pia,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,soundanchor,audio,media|audio|utilities,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,versatility,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,kui,terminal-tools,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,logdna-cli,terminal-tools|devops,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,swiftplantumlapp,diagramming|runtime-sdk,file-management|transfer|development|design|utilities,development|design,null,适合画流程图、结构图或头脑风暴草图 |
| | | ,guitar-pro,audio,media|audio|utilities|system-enhancement,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,archiver,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,boostnote-next,writing,development|writing,writing,null, |
| | | ,keysmith,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,skint,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,pxplay,system,system,utilities|system,null,PlayStation 主机第三方远程游玩客户端 |
| | | ,db-browser-for-sqlcipher-nightly,database-tools,browser|development,development,null,SQLCipher 数据库浏览器,适合查看加密 SQLite 数据 |
| | | ,lazycat,device-management,utilities,utilities|system-enhancement,null,硬件设备客户端 |
| | | ,fuse-for-mac-os-x,file-management,utilities,file-management|utilities,null,FUSE 文件系统组件,适合让 macOS 挂载和访问扩展文件系统 |
| | | ,miniwol,network-tools,utilities|system-enhancement,utilities,null,网络调试工具,适合抓包、代理和排查连接问题 |
| | | ,filomail,ai-tools|communication,communication|design|ai-tools,communication|ai-tools,null,邮件工具,适合集中处理收件箱和通信 |
| | | ,creative,device-management,utilities,utilities|system-enhancement,null,声卡和音频设备控制面板 |
| | | ,iexplorer,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,pinwheel,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,securityspy,security,utilities|security,security,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,ueli,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,endless-sky,game,entertainment|game|finance,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,yellow-dot,security,utilities|security,security,null,隐藏隐私指示点的工具 |
| | | ,ishare,picture-photo,media|picture-photo|utilities,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,sequential,picture-photo,media|picture-photo|utilities|system-enhancement,media|picture-photo,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,unblocked,ai-tools,development|ai-tools,ai-tools,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,colorwell,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,adobe-air,game,development|design|entertainment|game,entertainment|game,null,运行 AIR 应用的运行时,常见于旧游戏和跨平台桌面工具 |
| | | ,autogram,security,utilities,security,null,电子签名应用 |
| | | ,specter,finance|device-management|Automation,utilities|finance,productivity|utilities|system-enhancement|finance,null,比特币钱包管理工具,适合多签和硬件钱包工作流 |
| | | ,ulaa-browser,browser,browser|utilities|security,browser,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,tourbox-console,system,system,utilities|system,null,TourBox 设备配置工具 |
| | | ,ibm-semeru-runtime-jdk-11-open-edition,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,padloc,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,doughnut,audio,media|audio|entertainment,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,epson-print-layout,picture-photo|device-management,design|media|picture-photo|utilities,media|picture-photo|utilities|system-enhancement,null,爱普生照片打印排版工具,适合控制纸张和色彩输出 |
| | | ,visual-paradigm,ui-prototyping|diagramming,utilities,design,null,设计工具,适合图形、界面或视觉创作 |
| | | ,ibm-semeru-runtime-jdk-open-edition,runtime-sdk,utilities,development,null,Java JDK/运行时组件,适合开发或运行 Java 应用 |
| | | ,musaicfm-screensaver,audio,media|audio|utilities|system-enhancement|entertainment,media|audio,null,把音乐信息做成屏保,闲置时也能展示正在播放 |
| | | ,mindforger,ide,development|writing,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,power-manager,Automation,productivity|utilities,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,4k-image-compressor,picture-photo,media|picture-photo|utilities,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,lunatask,security|GTD|Notes,productivity|writing|utilities|security,productivity|writing|security,null,把任务、习惯和笔记放一起的个人效率系统 |
| | | ,file-juicer,picture-photo,productivity|media|picture-photo|utilities,media|picture-photo,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,sipgate-softphone,communication,file-management|transfer|media|picture-photo|utilities,communication,null,软电话客户端,直接在 Mac 上拨打和接听 VoIP |
| | | ,touch-portal,network-tools|Automation,utilities,productivity|utilities|system-enhancement,null,宏命令远程控制工具 |
| | | ,slidepilot,office,productivity,productivity|writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,trimmy,file-management,productivity|development|utilities|system-enhancement,file-management|utilities,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,dropdmg,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,elgato-capture-device-utility,device-management,utilities,utilities|system-enhancement,null,Elgato 采集设备更新和配置工具 |
| | | ,synthesia,writing|education,writing,writing|education,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,direqual,file-management,utilities,file-management|utilities,null,目录比较工具 |
| | | ,renamer,file-management,utilities,file-management|utilities,null,批量文件重命名工具 |
| | | ,avtouchbar,audio,media|audio|utilities|system-enhancement,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,disk-diet,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,macOS上最初的磁盘清理应用程序,首次发布于2011年,并不断进行改进 |
| | | ,gpg-suite-nightly,communication|security,communication|utilities|security,communication|security,null,邮件和文件加密保护工具 |
| | | ,yubihsm-2-sdk,runtime-sdk,utilities,development,null, |
| | | ,showmeyourhotkeys,Automation|system-maintenance,utilities|system-enhancement,productivity|utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,captain,Automation|devops,development|utilities|system-enhancement,productivity|development|system-enhancement,null,容器和集群管理工具,适合本地开发、镜像和 Kubernetes 工作流 |
| | | ,manico,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,nostalgiapp,game,productivity|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,usage,system-maintenance,utilities,utilities|system-enhancement,null,应用使用情况追踪工具 |
| | | ,spundle,file-management,utilities,file-management|utilities,null,稀疏包创建、调整和压缩工具 |
| | | ,electrum-ltc,security|finance,utilities|finance|security,finance|security,null,莱特币轻钱包,适合管理和签署 LTC 交易 |
| | | ,scrolla,device-management,development|utilities|system-enhancement,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,blisk-browser,browser,browser|development,browser,null,网页调试和浏览工具,适合开发者检查页面细节 |
| | | ,doxie,device-management,utilities,utilities|system-enhancement,null,扫描仪硬件配套应用 |
| | | ,cisdem-data-recovery,system-maintenance,utilities,utilities|system-enhancement,null,数据恢复工具 |
| | | ,pdfshaver,PDF,utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,retroarch-metal-nightly,game,media|video|entertainment|game,entertainment|game,null,RetroArch 的 Metal 测试版,适合尝鲜复古模拟性能 |
| | | ,swisscom-mycloud-desktop,transfer,file-management|transfer|utilities,transfer|utilities,null,Swisscom myCloud 桌面客户端 |
| | | ,rocket-typist,Automation,utilities,productivity|system-enhancement,null,常用短语文本扩展工具 |
| | | ,xtool-studio,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,google-web-designer,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,jumpcloud-password-manager,security,utilities|security,security,null,安全相关工具,适合隐私保护、访问控制或账号防护 |
| | | ,mater,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,q-light-controller,device-management,utilities,utilities|system-enhancement,null,DMX 和模拟灯光控制工具 |
| | | ,logitech-presentation,devops,productivity|development,development,null,演示工具,适合制作展示内容或现场演示 |
| | | ,parallels-virtualization-sdk,devops|runtime-sdk,development|utilities,development,null,虚拟化或远程连接工具,适合运行系统环境和访问远程电脑 |
| | | ,gitee,devops,development|utilities,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,change-vision-astah-uml,Notes|diagramming,productivity|design,productivity|design|writing,null,适合画流程图、结构图或头脑风暴草图 |
| | | ,mcreator,game,writing|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,rodecaster-app,device-management,utilities,utilities|system-enhancement,null, |
| | | ,leocad,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,the-archive,file-management|writing,writing|utilities,file-management|writing|utilities,null,文件管理工具,适合整理、传输或清理文件 |
| | | ,zoo-design-studio,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,crushftp,transfer,file-management|transfer|utilities,transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,hdrmerge,picture-photo,development|media|picture-photo,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,steinberg-library-manager,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,anka-virtualization,terminal-tools|devops,utilities,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,treesheets,Notes,productivity,productivity|writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,gdevelop,game,design|entertainment|game,entertainment|game,null,无代码游戏制作工具,适合快速做 2D 游戏原型 |
| | | ,batteries,device-management|system-maintenance,utilities,utilities|system-enhancement,null,多设备电量追踪工具 |
| | | ,elgato-game-capture-hd,game,media|video|entertainment|game,entertainment|game,null,游戏采集工具,录制和直播主机画面很方便 |
| | | ,swiftpm-catalog,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输或清理文件 |
| | | ,actual-odbc-driver-pack,finance|device-management,utilities|finance,utilities|system-enhancement|finance,null,Actual 的 ODBC 驱动包,方便旧数据库接入 Mac 应用 |
| | | ,findergo,file-management,file-management|development|utilities,file-management|utilities,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,macro-recorder,Automation,utilities|system-enhancement,productivity|system-enhancement,null,鼠标和键盘操作录制工具 |
| | | ,archiveweb-page,writing,writing|utilities,writing,null,网页浏览时手动归档为 WARC 或 WACZ 的工具 |
| | | ,roboform,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,katalon-studio,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,nanoleaf-desktop,device-management,utilities,utilities|system-enhancement,null,Nanoleaf 灯光控制工具 |
| | | ,synology-surveillance-station-client,device-management,utilities,utilities|system-enhancement,null,Synology 监控站桌面客户端 |
| | | ,ulbow,ide,browser,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,lyn,picture-photo,browser,media|picture-photo,null,轻量媒体浏览器,适合摄影和设计素材查看 |
| | | ,pdf-over,PDF,development,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,gitdock,devops,development|utilities|system-enhancement,development,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,password-gorilla,security|database-tools,development|utilities|security,development|security,null,数据库工具,适合连接、查询和管理数据库 |
| | | ,unraid-usb-creator,picture-photo,media|picture-photo|utilities,media|picture-photo,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,browser-actions,browser,browser|utilities|system-enhancement,browser,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,bcut,video,media|video|entertainment,media|video,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,intiface-central,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,elgato-studio,device-management,utilities,utilities|system-enhancement,null,内容创作设备采集和管理工具 |
| | | ,godspeed,GTD,productivity|utilities|system-enhancement,productivity,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,spotify-now-playing,audio,media|audio|entertainment,media|audio,null, |
| | | ,chatgpt-for-mac,ai-tools|communication,communication|utilities|system-enhancement|ai-tools,communication|ai-tools,null, |
| | | ,clipaste,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,filepane,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,go64,system-maintenance,utilities,utilities|system-enhancement,null,32 位应用扫描工具 |
| | | ,flying-carpet,transfer,file-management|transfer|utilities,transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,airy,video|transfer,transfer|media|video|utilities|entertainment,transfer|media|video|utilities,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,coverload,video|audio,transfer|media|video|audio|utilities,media|video|audio,null,媒体封面下载工具,适合整理影视和音乐资料 |
| | | ,react-proto,Font|ui-prototyping|3d-cad,development|design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,post-haste,GTD,productivity|development,productivity,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,trojanx,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,polyphone,audio,design|media|audio,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,wordservice,Automation,utilities,productivity|system-enhancement,null,选中文本处理命令工具 |
| | | ,appgrid,window-management,development|utilities|system-enhancement,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,onyx-beta,system-maintenance,utilities,utilities|system-enhancement,null,系统文件结构验证和维护工具 |
| | | ,seam,window-management,productivity|utilities|system-enhancement,utilities|system-enhancement,null,刘海屏动态岛效率工具 |
| | | ,audius,audio,media|audio|entertainment,media|audio,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,clock-signal,communication|security,communication|utilities|security,communication|security,null,安全相关工具,适合隐私保护、访问控制或账号防护 |
| | | ,finbar,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,motu-m-series,audio,media|audio|utilities,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,bankid-security-application-sweden,security|finance|education,utilities|finance|education|security,finance|education|security,null,瑞典 BankID 安全组件,用来完成银行和身份认证 |
| | | ,bookletcreator,PDF,utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,moneydance,security|finance,utilities|finance|security,finance|security,null,适合管理钱包、资产或安全相关的金融操作 |
| | | ,letter-opener,communication,communication|utilities|system-enhancement,communication,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,x32-edit,audio,media|audio|system,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,live-home-3d,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,muse,audio,media|audio|entertainment,media|audio,null,思维画布应用,适合整理灵感和团队协作 |
| | | ,webplotdigitizer,picture-photo|devops,development|media|picture-photo|utilities,development|media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,macgamestore,game,transfer|utilities|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,db-browser-for-sqlite-nightly,database-tools,browser|development,development,null,SQLite 数据库浏览器测试版,适合查看和编辑本地库 |
| | | ,headset,audio,media|audio|entertainment,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,wasabi-wallet,security|finance|Automation,utilities|finance|security,productivity|system-enhancement|finance|security,null,重视隐私的比特币钱包,适合 CoinJoin 工作流 |
| | | ,ifunbox,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,cisdem-pdf-converter-ocr,picture-photo|PDF,utilities,writing|media|picture-photo|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,imagealpha,picture-photo,media|picture-photo|utilities,media|picture-photo,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,cleaneronepro,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,heaven-benchmark,device-management|system-maintenance,utilities,utilities|system-enhancement,null,硬件性能和稳定性测试工具 |
| | | ,avast-secure-browser,browser|security,browser|utilities|security,browser|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,badlion-client,game,productivity|writing|entertainment|game,entertainment|game,null,Minecraft PvP 客户端,内置性能优化和竞技辅助 |
| | | ,edrawmind,picture-photo|Notes,productivity|media|picture-photo,productivity|writing|media|picture-photo,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,goldenpassport,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,sony-imaging-edge-webcam,video,browser,media|video,null, |
| | | ,cerebro,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,subtools,transfer,utilities,transfer|utilities,null, |
| | | ,flirc,device-management,utilities,utilities|system-enhancement,null,红外 USB 接收器配置工具 |
| | | ,vallum,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,disk-arbitrator,system-maintenance,utilities,utilities|system-enhancement,null, |
| | | ,swifty,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,quo,communication,communication|productivity,communication,null,沟通工具,适合消息、邮件、通话或团队交流 |
| | | ,sena-bluetooth-device-manager,device-management,utilities,utilities|system-enhancement,null,SENA 设备管理工具 |
| | | ,aware,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,sakuralauncher,Automation,productivity,productivity|system-enhancement,null,SakuraFrp 启动器 |
| | | ,spaceradar,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,teensy,device-management,utilities,utilities|system-enhancement,null,固件刷写工具 |
| | | ,adobe-connect,Meeting,communication|productivity|design,communication|productivity,null,企业线上会议和课堂工具,适合培训、会议和网络研讨会 |
| | | ,lyrics-finder,transfer,file-management|transfer|utilities,transfer|utilities,null,歌词查找和下载工具 |
| | | ,thumbsup,picture-photo,media|picture-photo|utilities,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,dcp-o-matic,video|audio,development|design|media|video|audio,media|video|audio,null,把影片、字幕和音频打包成影院放映用的 DCP |
| | | ,kiwi-for-gmail,communication,communication|productivity,communication,null,沟通工具,适合消息、邮件、通话或团队交流 |
| | | ,mcloud,file-management,utilities,file-management|utilities,null,中国移动云盘客户端 |
| | | ,robofont,Font,utilities,design|utilities,null,字体编辑工具,适合设计、修改和检查字体 |
| | | ,origami-studio,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,energiza-pro,system-maintenance,utilities,utilities|system-enhancement,null,用于控制MacBook电池充电的应用程序 |
| | | ,kameleo,browser|security,browser,browser|security,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,connect-fonts,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,simsim,file-management,file-management|development|utilities,file-management|utilities,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,wd-security,security,development|utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,ultdata,system-maintenance,utilities,utilities|system-enhancement,null,iPhone 数据恢复工具 |
| | | ,volume-control,audio,media|audio|utilities|system-enhancement|entertainment,media|audio,null,音量控制工具,适合更细地管理系统声音输出 |
| | | ,eclipse-modeling-tools,device-management,utilities,utilities|system-enhancement,null,模型驱动应用开发工具和运行时 |
| | | ,odrive,security|transfer,file-management|transfer|utilities|security,transfer|utilities|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,enclave,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,lock-rattler,security,utilities|security,security,null,系统安全检查工具 |
| | | ,fake,browser,browser|productivity|utilities|system-enhancement,browser,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,textgrabber2,picture-photo,media|picture-photo|utilities|system-enhancement,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,multifirefox,browser,browser|productivity|utilities,browser,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,bria,communication|transfer,file-management|transfer|utilities,communication|transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,psi,communication,communication|design,communication,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,vram-pro,system-maintenance,utilities,utilities|system-enhancement,null,统一内存 VRAM 分配控制工具 |
| | | ,spacesaver,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,trackerzapper,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,diagnostics,system-maintenance,utilities,utilities|system-enhancement,null,崩溃诊断报告查看器 |
| | | ,nethlink,ide,utilities,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,the-archive-browser,browser,browser|utilities,browser,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,exactscan,writing|device-management,writing|utilities,writing|utilities|system-enhancement,null,支持多种专业文档扫描仪的现代扫描解决方案,能够帮助用户实现无纸化办公 |
| | | ,adobe-photoshop-patterns-quicklook-plugin,picture-photo,design|media|picture-photo,media|picture-photo,null,给 Photoshop 图案文件加预览,找素材更快 |
| | | ,bitbox,finance|device-management,utilities|finance,utilities|system-enhancement|finance,null,硬件钱包套件,适合安全管理加密资产 |
| | | ,gopass-ui,communication|security,communication|productivity|utilities|security,communication|security,null,gopass 密码库图形界面,适合安全管理团队密钥 |
| | | ,keycombiner,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,poi,utilities,browser,utilities,null, |
| | | ,caldigit-thunderbolt-station-usb-charging-and-superdrive-support-driver,device-management|devops,development|utilities,development|utilities|system-enhancement,null,Apple 设备支持驱动 |
| | | ,cloudnet-for-mac-client,security,utilities|security,security,null, |
| | | ,tiddlywiki,Notes,browser,productivity|writing,null, |
| | | ,m32-edit,audio,media|audio|system,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,xiaomi-cloud,picture-photo|transfer,communication|transfer|media|picture-photo|utilities,transfer|media|picture-photo|utilities,null,小米云服务入口,适合同步和管理小米生态资料 |
| | | ,cuda-z,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,ripcord,communication,communication|productivity,communication,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,todotxtmac,GTD,productivity|utilities|system-enhancement,productivity,null, |
| | | ,canon-pixma-driver,device-management,utilities,utilities|system-enhancement,null, |
| | | ,dmg-canvas,picture-photo,design|media|picture-photo,media|picture-photo,null,DMG 安装包设计工具,适合做漂亮的 Mac 分发镜像 |
| | | ,universal-password-manager,security,utilities|security,security,null, |
| | | ,4k-video-to-mp3,video|audio,media|video,media|video|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,fetch,transfer,file-management|transfer|utilities,transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,arctic,video,media|video|utilities|system-enhancement,media|video,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,ipa-palette,diagramming,utilities,design,null, |
| | | ,juice,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,beardie,writing,writing|media|video|utilities|system-enhancement,writing,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,playdate-mirror,game|video,media|video|audio|entertainment|game,media|video|entertainment|game,null,把 Playdate 掌机画面镜像到 Mac,录制演示更方便 |
| | | ,blocs,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,clickcharts,Font|ui-prototyping|3d-cad|diagramming,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,deadbolt,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,pages-data-merge,writing|communication,communication|development|writing,communication|writing,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,apptivate,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,feed-the-beast,game,transfer|writing|utilities|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,replayweb-page,file-management,utilities,file-management|utilities,null,WARC 和 WACZ 网页归档查看器 |
| | | ,affinity-photo,picture-photo,design|media|picture-photo,media|picture-photo,null,一次性买断的专业修图工具,照片编辑和合成都很强 |
| | | ,mindmanager,Notes,productivity,productivity|writing,null,思维导图工具 |
| | | ,tyme,GTD,utilities,productivity,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,brisync,transfer,transfer|utilities|system-enhancement,transfer|utilities,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,textbuddy,Automation,utilities,productivity|system-enhancement,null,文本转换、过滤、排序和处理工具 |
| | | ,gauntlet,Automation,productivity,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,recents,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,kunkun,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,paparazzi,picture-photo|writing,writing|media|picture-photo|utilities,writing|media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,polymail,communication,communication|productivity,communication,null,邮件客户端,适合集中收发和管理邮箱 |
| | | ,alfaview,video|audio,communication|media|video|audio,media|video|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,idagio,audio,media|audio|entertainment,media|audio,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,bathyscaphe,communication,browser,communication,null,沟通工具,适合消息、邮件、通话或团队交流 |
| | | ,musictube,audio,media|audio|entertainment,media|audio,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,nexon-plug,game,productivity|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,keymanager,security,utilities,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,lofi,audio,media|audio|entertainment,media|audio,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,audiocupcake,audio,media|audio|entertainment,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,fabfilter-pro-mb,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,gdlauncher,game,productivity|writing|entertainment|game,entertainment|game,null,Minecraft 启动器,安装和切换模组包很方便 |
| | | ,id3-editor,audio,utilities,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,objektiv,picture-photo,browser|utilities,media|picture-photo,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,pdf-pals,ai-tools|communication|PDF,communication|ai-tools,communication|writing|utilities|ai-tools,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,jdiskreport,file-management|system-maintenance,utilities,file-management|utilities|system-enhancement,null,磁盘空间分析工具,适合查看和清理空间占用 |
| | | ,lightproxy,security,browser,security,null,网络调试工具,适合抓包、代理和排查连接问题 |
| | | ,olive,video,productivity|media|video,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,ua-midi-control,audio,media|audio|system,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,buildsettingextractor,ide,development|utilities,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,signet,security,utilities,security,null,应用签名扫描和检查工具 |
| | | ,bobhelper,Font|ui-prototyping|3d-cad,design|utilities|system-enhancement,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,ecamm-live,video,media|video|entertainment,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,lehreroffice,education|office,productivity|education,productivity|writing|education,null,教师办公工具,适合管理班级、成绩和教学资料 |
| | | ,spotify4bigsur,audio,media|audio|entertainment,media|audio,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,textbar,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,lockdown,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,openpht,video,media|video|entertainment,media|video,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,space-capsule,window-management,utilities,utilities|system-enhancement,null,桌面空间管理工具 |
| | | ,zoho-workdrive,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,fabfilter-pro-c,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,codeexpander,writing|input-tools,productivity|media|picture-photo|utilities|system-enhancement,writing|utilities|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,wacom-inkspace,device-management,utilities,utilities|system-enhancement,null, |
| | | ,coin-wallet,finance,development|finance,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,pile,Notes,development|writing,productivity|writing,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,monofocus,GTD,productivity|utilities|system-enhancement,productivity,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,flame,ide,browser,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,xact,audio,media|audio|utilities,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,cumulus,audio,media|audio|utilities|system-enhancement,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,elpass,security,utilities|security,security,null,密码管理器,适合保存账号、密码和敏感信息 |
| | | ,mmhmm-desktop,video|Meeting,productivity|media|video,communication|productivity|media|video,null, |
| | | ,silnite,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,snapmotion,video|picture-photo,media|video|picture-photo|utilities,media|video|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,mimecast-for-mac,communication,communication|utilities,communication,null, |
| | | ,olympus,game,media|video|entertainment|game,entertainment|game,null,游戏模组管理工具,适合管理 Celeste 等游戏内容 |
| | | ,nkoda,audio,development|media|audio,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,novation-components,device-management,utilities,utilities|system-enhancement,null,Novation 硬件管理和更新工具 |
| | | ,powder-player,video,transfer|media|video|utilities|entertainment,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,ballast,audio,media|audio|utilities,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,iridium-browser,browser,browser|utilities|security,browser,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,anka-build-cloud-controller,device-management|devops|api-tools,utilities,development|utilities|system-enhancement,null,API 调试工具,适合测试接口、请求和开发流程 |
| | | ,overflow,GTD|Automation,productivity,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,semulov,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,loading,network-tools|system-maintenance,utilities|system|system-enhancement,utilities|system-enhancement,null,菜单栏网络监控工具,可显示正在使用网络的应用 |
| | | ,brightness-sync,transfer,transfer|utilities|system-enhancement,transfer|utilities,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,amadine,Font|ui-prototyping|3d-cad|diagramming,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,gitkraken-serverless,devops,productivity|development,development,null,高效 Git 客户端 |
| | | ,hp-prime,device-management,utilities,utilities|system-enhancement,null, |
| | | ,skyfonts,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,turbotax-2024,finance,utilities,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,feem,transfer,file-management|transfer|utilities,transfer|utilities,null,完整功能的多平台共享软件,可以在多手机多电脑之间直接传送文本和文件 |
| | | ,postbox,communication|security,communication|utilities|security,communication|security,null,邮件客户端,适合集中收发和管理邮箱 |
| | | ,astro-command-center,device-management,utilities,utilities|system-enhancement,null,ASTRO 设备设置配置工具 |
| | | ,cernbox-client,transfer,file-management|transfer|utilities,transfer|utilities,null, |
| | | ,softorino-youtube-converter,video|transfer,transfer|utilities|entertainment,transfer|media|video|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,yoda,video|transfer,transfer|media|video|utilities|entertainment,transfer|media|video|utilities,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,opensong,office,productivity,productivity|writing,null,演示工具,适合制作展示内容或现场演示 |
| | | ,overbridge,audio|device-management,media|audio|utilities,media|audio|utilities|system-enhancement,null,Elektron 硬件与音乐软件集成工具 |
| | | ,deep-hiarcs-chess-explorer,game,development|entertainment|game,entertainment|game,null,国际象棋数据库和分析工具,适合研究棋局与开局 |
| | | ,flic,device-management,utilities,utilities|system-enhancement,null,蓝牙按钮驱动工具 |
| | | ,locu,GTD,utilities,productivity,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,prizmo,picture-photo,utilities,media|picture-photo,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,wiso-steuer-2024,finance,utilities,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,cmdtap,Automation,productivity,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,konica-minolta-bizhub-c750i-c650i-c360i-c287i-c286i-c4050i-c4000i-c3320i-printer-driver,device-management,utilities,utilities|system-enhancement,null, |
| | | ,weektodo,security|GTD,productivity|utilities|security,productivity|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,apptrap,system-maintenance,utilities,utilities|system-enhancement,null,应用卸载辅助工具,会在删除应用时提示清理相关偏好和残留文件 |
| | | ,flanders-ip-remote-utility,device-management,utilities,utilities|system-enhancement,null,Flanders Scientific 硬件管理工具 |
| | | ,nitroshare,transfer,file-management|transfer|utilities,transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,sysdig-inspect,security|devops,development|utilities|security,development|security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,toptracker,finance|GTD,utilities,productivity|finance,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,msgfiler,communication,communication|utilities|system-enhancement,communication,null,邮件客户端,适合集中收发和管理邮箱 |
| | | ,securesafe,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,anchor-wallet,security|finance,utilities|finance|security,finance|security,null,EOS 系钱包客户端,适合管理账号和签署交易 |
| | | ,dcp-o-matic-player,video,development|design,media|video,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,font-finagler,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,logic-sniffer,device-management,utilities,utilities|system-enhancement,null, |
| | | ,nuclino,writing,utilities,writing,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,safeincloud-password-manager,security,utilities|security,security,null,账号安全工具,适合管理密码、验证码和通行密钥 |
| | | ,pdfkey-pro,security,utilities|security,security,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,fastmarks,browser|Automation,browser,browser|productivity|system-enhancement,null,网页浏览器,适合日常上网和访问 Web 服务 |
| | | ,white-rabbit,picture-photo,media|picture-photo|utilities,media|picture-photo,null,媒体工具,适合处理图片、音频或视频内容 |
| | | ,wiso-steuer-2022,finance,utilities,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,vocaster-hub,device-management,utilities,utilities|system-enhancement,null,Focusrite Vocaster 声卡控制工具 |
| | | ,ppduck,picture-photo,media|picture-photo|utilities,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,taccy,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,boxcryptor,security|file-management,file-management|transfer|utilities|finance|security,file-management|utilities|security,null,云盘文件加密工具,同步前先给敏感资料上锁 |
| | | ,clion-eap,terminal-tools|ide,utilities,development,null,CLion 早期访问版 IDE |
| | | ,pdfpenpro,PDF,utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,preferencecleaner,GTD,productivity|utilities,productivity,null,学习工具,适合查词、学习、参考或教育场景 |
| | | ,dcp-o-matic-kdm-creator,video|audio,development|design|media|video|audio,media|video|audio,null,为 DCP 生成影院密钥,适合数字电影发行流程 |
| | | ,ithoughtsx,Notes,productivity,productivity|writing,null,效率工具,适合文档、记录或日常工作流 |
| | | ,loginputmac,device-management,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,parsehub,api-tools,utilities,development,null,API 调试工具,适合测试接口、请求和开发流程 |
| | | ,thebrain,Notes,productivity,productivity|writing,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,attachecase,security,utilities|security,security,null,安全工具,适合保护隐私、控制访问或加密数据 |
| | | ,hp-printer-drivers,device-management,utilities,utilities|system-enhancement,null, |
| | | ,mindmaster,Notes,productivity,productivity|writing,null,思维导图软件 |
| | | ,cloud189,transfer,file-management|transfer|utilities,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,carbide-create,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,ankama-launcher,game,productivity|media|video|entertainment|game,entertainment|game,null,Ankama 游戏启动器,管理 Dofus 等游戏和账号 |
| | | ,valley-benchmark,system-maintenance,utilities,utilities|system-enhancement,null, |
| | | ,honer,picture-photo,media|picture-photo|utilities,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,katana,picture-photo,media|picture-photo|utilities,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,vimy,devops,development|utilities,development,null,虚拟化或远程连接工具,适合运行系统环境和访问远程电脑 |
| | | ,volt,communication,communication|productivity,communication,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,wintertime,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,bestres,window-management,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,halion-sonic,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,northern-softworks-cache-cleaner,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输或清理文件 |
| | | ,now-tv-player,video,media|video|entertainment,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,roaringapps,system-maintenance,utilities,utilities|system-enhancement,null,已安装应用兼容性查看工具 |
| | | ,bfxr,game,media|audio|entertainment|game,entertainment|game,null,复古游戏音效生成器,快速做 8-bit 风格声音 |
| | | ,mjolnir,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,worldpainter,game,writing|entertainment|game,entertainment|game,null,游戏,适合休闲娱乐和沉浸式体验 |
| | | ,fontlab,Font|ui-prototyping|3d-cad,utilities,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,i1profiler,picture-photo,productivity|design|media|picture-photo|utilities|system-enhancement,media|picture-photo,null,显示器和打印色彩校准工具,适合严肃影像工作流 |
| | | ,kogiqa,Automation,productivity|utilities|system-enhancement,productivity|system-enhancement,null,效率增强工具,适合快速启动、自动化或管理常用操作 |
| | | ,tdr-molotok,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,airtrash,transfer,file-management|transfer|utilities,transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,command-pad,terminal-tools,utilities|system-enhancement,development,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,fontra-pak,Font|ui-prototyping|3d-cad,browser,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,kkbox,audio,media|audio|entertainment,media|audio,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,labymod-launcher,game,productivity|writing|entertainment|game,entertainment|game,null,LabyMod 启动器,管理 Minecraft 模组和服务器体验 |
| | | ,space-saver,transfer,transfer|utilities|system,transfer|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,btcpayserver-vault,finance|device-management|transfer,utilities|finance,transfer|utilities|system-enhancement|finance,null,BTCPay 硬件钱包桥接工具,帮助安全签署付款 |
| | | ,fontcreator,Font,utilities,design|utilities,null,字体编辑工具,适合设计、修改和检查字体 |
| | | ,niftyman,writing,writing|utilities|system-enhancement,writing,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,crypto-native-app-ng,security|finance,browser|utilities|finance|security,finance|security,null,加密资产工具入口,适合处理钱包和链上操作 |
| | | ,dcp-o-matic-disk-writer,video,development|design|media|video|audio,media|video,null,把 DCP 写入放映介质,适合影院交付前检查 |
| | | ,express-scribe-transcription-software,audio,development|media|audio,media|audio,null,脚踏控制的转录音频播放器 |
| | | ,nault,finance,utilities|finance,finance,null,Nano 钱包客户端,适合管理和发送 Nano 资产 |
| | | ,droidid,device-management,utilities,utilities|system-enhancement,null,用 Android 设备指纹解锁 Mac 的工具 |
| | | ,moose,transfer,utilities,transfer|utilities,null,开源的 bT 下载客户端,支持 macOS 与 Linux 系统 |
| | | ,nimblenote,writing,writing|utilities|system-enhancement,writing,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,pynsource,diagramming|ide,development,development|design,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,ripx,audio,media|audio|utilities,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,toshiba-colormfp-drivers,device-management,utilities,utilities|system-enhancement,null, |
| | | ,hides,ide,utilities,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,wrkspace,Automation|devops,development|utilities|system-enhancement,productivity|development|system-enhancement,null,容器和集群管理工具,适合本地开发、镜像和 Kubernetes 工作流 |
| | | ,preference-manager,system-maintenance,transfer|writing|media|video|utilities,utilities|system-enhancement,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,apple-store-time-machine,ide,development|system,development,null,Apple Store 开业日 3D 重建浏览工具 |
| | | ,timeular,GTD,utilities,productivity,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,warsaw,security|finance|education,utilities|finance|education|security,finance|education|security,null,银行安全组件,常见于巴西网银登录和交易保护 |
| | | ,wiso-steuer-2023,finance,utilities,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,yealink-meeting,Meeting,communication|productivity|media|video,communication|productivity,null,亿联会议客户端,适合连接会议室设备和远程会议 |
| | | ,desktoputility,Automation,productivity|utilities,productivity|system-enhancement,null,效率工具,适合文档、记录或日常工作流 |
| | | ,keypad-layout,ui-prototyping,design|utilities,design,null,设计工具,适合图形、界面或视觉创作 |
| | | ,sizzy,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,baritone,audio,media|audio|utilities|system-enhancement|entertainment,media|audio,null,Minecraft 自动寻路工具,适合研究和辅助复杂移动 |
| | | ,brightauthor-connected,device-management,utilities,utilities|system-enhancement,null,BrightSign 设备配置和管理工具 |
| | | ,livebook-nightly,writing,development|writing,writing,null,Elixir 开发者代码笔记本 |
| | | ,trezor-bridge,security,browser,security,null,沟通工具,适合聊天、邮件、通话或团队交流 |
| | | ,dcp-o-matic-playlist-editor,video,development|design|media|video|audio,media|video,null,编辑 DCP 放映列表,整理影院播放顺序更清楚 |
| | | ,icon-shelf,picture-photo,development|media|picture-photo,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,netxms-management-console,system-maintenance,utilities|system|system-enhancement,utilities|system-enhancement,null,网络和基础设施监控管理系统 |
| | | ,autumn,ide,development|utilities|system-enhancement,development,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,dcp-o-matic-batch-converter,video|audio,development|design|media|video|audio,media|video|audio,null,批量转换影片到 DCP,处理多条片源时很省事 |
| | | ,dcp-o-matic-encode-server,video|audio,development|design|media|video|audio,media|video|audio,null,分担 DCP 编码任务,让电影打包速度更快 |
| | | ,rode-virtual-channels,device-management,utilities,utilities|system-enhancement,null, |
| | | ,threema-work,communication|security,communication|utilities|security,communication|security,null,端到端加密即时通讯工具,适合安全聊天 |
| | | ,poker-copilot,finance,finance|ai-tools,finance,null,财务工具,适合账务、预算或资产相关管理 |
| | | ,vimcal,communication|GTD,communication|productivity|development,communication|productivity,null,效率管理工具,适合安排任务、日程或跟踪时间 |
| | | ,f-bar,system-maintenance,utilities,utilities|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,ivideon-client,video|security,browser|media|video,media|video|security,null,Ivideon 账号监控视频查看工具 |
| | | ,kactus,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,uncrustifyx,runtime-sdk,browser|writing|utilities,development,null,写作和笔记工具,适合记录、编辑和整理文本内容 |
| | | ,vimediamanager,video,development|media|video,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,cisco-proximity,Meeting,communication|productivity|media|video,communication|productivity,null,连接会议室设备共享屏幕,适合企业会议和演示 |
| | | ,dcp-o-matic-combiner,video,development|design|media|video|audio,media|video,null,视频工具,适合播放、录制、剪辑或转换视频 |
| | | ,free-podcast-transcription,audio,media|audio|entertainment,media|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,trivial,transfer,file-management|transfer|utilities,transfer|utilities,null,传输工具,适合下载、同步或在设备间传文件 |
| | | ,agisoft-metashape-standard-edition,picture-photo,development|media|picture-photo,media|picture-photo,null,数字图像处理和 3D 空间数据生成工具 |
| | | ,batchoutput-pdf,PDF,utilities,writing|utilities,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,bonita-studio-community-edition,GTD,productivity|utilities|system-enhancement,productivity,null, |
| | | ,ipepresenter,office,productivity,productivity|writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,mozregression-gui,ide,browser|file-management|utilities,development,null,开发相关工具,适合编程、调试或管理开发环境 |
| | | ,pdfelement-express,PDF,utilities,writing|utilities,null,PDF 编辑工具,适合编辑、标注和处理 PDF 文档 |
| | | ,podcastmenu,audio|system-maintenance,media|audio|utilities|system-enhancement|entertainment,media|audio|utilities|system-enhancement,null,菜单栏播客工具,不打开主应用也能收听节目 |
| | | ,ringcentral-meetings,Meeting,communication|productivity|media|video,communication|productivity,null,RingCentral 会议客户端,适合远程视频沟通 |
| | | ,genesys-cloud-for-macos,Meeting,browser,communication|productivity,null, |
| | | ,mockuuups-studio,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,paragon-camptune,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,provideoplayer,video,productivity|media|video,media|video,null,演示工具,适合制作展示内容或现场演示 |
| | | ,focusrite-saffire-mixcontrol,device-management,utilities,utilities|system-enhancement,null, |
| | | ,wing-personal,ide,development|design,development,null,编程开发工具,适合编写、阅读和维护代码 |
| | | ,output-factory,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,splitshow,office,productivity,productivity|writing,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,utterly,video|audio,communication|media|video|audio,media|video|audio,null,音频工具,适合播放、制作、编辑或管理声音内容 |
| | | ,wiso-steuer-2021,finance,utilities,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,qnap-qudedup-extract-tool,device-management,utilities,utilities|system-enhancement,null, |
| | | ,tune-instructor,audio,media|audio|utilities|system-enhancement,media|audio,null,Apple Music 菜单栏控制工具 |
| | | ,shortcutor,Automation,utilities|system-enhancement,productivity|system-enhancement,null,系统增强工具,适合优化窗口、菜单栏、输入或设备状态 |
| | | ,wiso-steuer-2020,finance,utilities,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,convert3dgui,picture-photo|terminal-tools,media|picture-photo,development|media|picture-photo,null,开发者工具,适合命令行、构建、调试或工程管理 |
| | | ,ethui,finance,development|finance,finance,null,财务工具,适合记账、发票、资产或交易管理 |
| | | ,mockplus,Font|ui-prototyping|3d-cad,design,design|utilities,null,设计工具,适合图形、界面、字体或建模相关工作 |
| | | ,mmhmm-studio,video|Meeting,productivity|media|video,communication|productivity|media|video,null,办公文档工具,适合阅读、编辑或管理文档资料 |
| | | ,photozoom-pro,picture-photo,development|media|picture-photo,media|picture-photo,null,图片工具,适合浏览、编辑、转换或管理图片 |
| | | ,screenfocus,window-management,utilities,utilities|system-enhancement,null,多屏幕管理工具 |
| | | ,shearwater-cloud,system-maintenance,utilities,utilities|system-enhancement,null,潜水日志查看、编辑和分享工具 |
| | | ,arkiwi,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,betwixt,security,browser,security,null,网络调试工具,适合抓包、代理和排查连接问题 |
| | | ,cashnotify,finance|system-maintenance,utilities|finance,utilities|system-enhancement|finance,null,菜单栏收款提醒工具,适合关注支付和收入动态 |
| | | ,iit-certification-signature,security,browser,security,null,乌克兰税务电子签名浏览器组件 |
| | | ,machacha,file-management,utilities,file-management|utilities,null,文件管理工具,适合整理、传输、清理或备份文件 |
| | | ,xliff-editor,system-maintenance,utilities,utilities|system-enhancement,null,加载迅速、使用简便且内存占用低的编辑工具,专为处理XLIFF文件而设计 |
| | | ,criptext,communication|security,communication|utilities|security,communication|security,null,邮件客户端,适合集中收发和管理邮箱 |
| New file |
| | |
| | | # Smart Start Ultimate Default Catalog Report |
| | | |
| | | Generated: 2026-05-19T20:08:23.394Z |
| | | |
| | | ## Inputs |
| | | |
| | | - curated CSV: `Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog.csv` |
| | | - curated rows: 5223 |
| | | - curated rows after alias dedupe: 5223 |
| | | - alias duplicates removed: 0 |
| | | - unknown tager tokens: 0 |
| | | |
| | | ## Outputs |
| | | |
| | | - Review CSV: `Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog.csv` |
| | | - Runtime JSON: `Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog.json` |
| | | - Duplicate review: `Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_DuplicateReview.csv` |
| | | - Translation QA: `Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_TranslationQA.md` |
| | | |
| | | ## Summary |
| | | |
| | | - Final rows: 5223 |
| | | - Rows with Chinese default notes: 4423 |
| | | - Rows with source Chinese notes from curated CSV: 4423 |
| | | - Rows with Apple note fallback attached: 0 |
| | | - Invalid tag rows: 0 |
| | | - Empty normalizedName rows: 0 |
| | | - Exact `other` rows: 0 |
| | | - Mixed `other` rows after cleanup: 0 |
| | | - Tag changes vs previous runtime JSON: 0 |
| | | - Chinese note changes vs previous runtime JSON: 0 |
| | | - Bundle identifier changes vs previous runtime JSON: 0 |
| | | - Unknown tager tokens: 0 |
| | | - Note quality issues: 0 |
| | | |
| | | ## Tag Distribution |
| | | |
| | | - browser: 115 |
| | | - communication: 261 |
| | | - productivity: 324 |
| | | - file-management: 129 |
| | | - transfer: 219 |
| | | - development: 678 |
| | | - design: 223 |
| | | - writing: 301 |
| | | - media: 718 |
| | | - video: 217 |
| | | - audio: 291 |
| | | - picture-photo: 272 |
| | | - utilities: 2498 |
| | | - system: 19 |
| | | - system-enhancement: 594 |
| | | - entertainment: 383 |
| | | - game: 347 |
| | | - finance: 94 |
| | | - education: 71 |
| | | - ai-tools: 185 |
| | | - security: 218 |
| | | |
| | | ## Notes |
| | | |
| | | - Runtime tags are generated from the curated CSV `tager` column, not the legacy `defaultTag` column. |
| | | - Runtime notes are generated only from real source notes. The generator must not synthesize notes from app names or category labels. |
| | | - Missing translations are intentionally omitted until a real translation pipeline or reviewed translation table provides them. |
| New file |
| | |
| | | # Smart Start Ultimate Default Catalog Translation QA |
| | | |
| | | Generated: 2026-05-19T20:08:23.394Z |
| | | |
| | | ## Summary |
| | | |
| | | - Supported languages: 29 |
| | | - Rows with source Chinese notes: 4423 |
| | | - Source notes: 4423 |
| | | - Required machine/reviewed translations: 123844 |
| | | - Generated placeholder translations: 0 |
| | | - Note quality issues: 0 |
| | | - Note limit: 80 |
| | | |
| | | ## Issue Sample |
| | | |
| | | - None |
| New file |
| | |
| | | **请按以下规则改** |
| | | |
| | | | 字段 | 允许的匹配 | 禁止的匹配 | |
| | | | ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------- | |
| | | | App 显示名 | exact, prefix, substring, acronym-prefix, subsequence fuzzy | 不允许对拼音进行subsequence fuzzy或substring fuzzy | |
| | | | Tag | exact, prefix, substring, pinyin-prefix, pinyin-initials-prefix,subsequence fuzzy,substring fuzzy | 不允许对拼音进行subsequence fuzzy或substring fuzzy | |
| | | | Note | exact, prefix, substring,subsequence fuzzy,中文原文直搜,允许对拼音进行 substring fuzzy , | 不允许对拼音进行 subsequence fuzzy | |
| | | | Bundle Identifier | exact, prefix | substring fuzzy;subsequence fuzzy | |
| | | | 内部 bundle 名如 CFBundleName | exact, prefix | substring fuzzy;subsequence fuzzy | |
| | | |
| | | **5 条验收用例** |
| | | |
| | | - 输入 sex 时,不应该再出现 News / Siri / FindMy / Stocks / Journal / Freeform / 无影云电脑 |
| | | - 输入 不背、news、find、journal 这类真实前缀,仍然要正常命中 |
| | | - 输入中文备注原文关键词,比如“新闻”“助手”“股票”,仍然可以通过 note 命中 |
| | | - 输入备注中中文词的拼音前缀,比如备注含“压缩”时输入 yasuo,仍然可以通过 note 命中 |
| | | - 不背单词 不应该再因为 LangEasyLexis 被 sex 这种短词带出来 |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | subsequence fuzzy 按顺序跳跃找字母,找到就算 |
| | | |
| | | - 可以理解成:**用户输入的字符,只要按顺序出现在目标文本里,中间允许隔着别的字符,也算匹配。** |
| | | - 输入PS,就能匹配photoshop |
| | | |
| | | |
| | | |
| | | substring fuzzy 要求字符是**连续出现**--但是不要去从头开始 |
| | | |
| | | - 只要作为一段连续文本出现就算匹配,不管是不是从开头匹配的 |
| | | - 输入shop,就能匹配photoshop |
| New file |
| | |
| | | |
| | | |
| | | **请开发按这套规则改就是保守搜索方案** |
| | | |
| | | 直接定成这张规则表,不要再模糊: |
| | | |
| | | | 字段 | 允许的匹配 | 禁止的匹配 | |
| | | | --------------------------- | --------------------------------------------------------------- | --------------------------------- | |
| | | | App 显示名 | exact, prefix, substring, acronym-prefix | 对 3 字母以内查询做 subsequence fuzzy | |
| | | | Tag | exact, prefix, substring, pinyin-prefix, pinyin-initials-prefix | subsequence fuzzy | |
| | | | Note | exact, prefix, substring,中文原文直搜 | note 的拼音匹配;subsequence fuzzy | |
| | | | Bundle Identifier | exact, prefix | substring fuzzy;subsequence fuzzy | |
| | | | 内部 bundle 名如 `CFBundleName` | 最好直接不搜;如果一定要搜,只允许 exact/prefix | substring fuzzy;subsequence fuzzy | |
| | | |
| | | 对应到代码,开发可以这样改: |
| | | |
| | | 1. 在 [QuickSearch.swift](/Users/ar/Projects/Apptag/Apptag/QuickSearch.swift:382) 里把 `noteFields` 的 |
| | | `pinyinCandidates: pinyinCandidates(for: document.note)` |
| | | 改成 |
| | | `pinyinCandidates: []` |
| | | |
| | | 2. 在 [QuickSearch.swift](/Users/ar/Projects/Apptag/Apptag/QuickSearch.swift:577) 里收缩 `localizedNames(for:)`: |
| | | 不要把 `CFBundleName` 这种内部工程名默认放进搜索名集合。 |
| | | 最稳妥做法是只保留: |
| | | - `CFBundleDisplayName` |
| | | - Finder 显示名 |
| | | - 必要时 `CFBundleName` 作为低优先级 alias,但只能 exact/prefix |
| | | |
| | | 3. 改 [QuickSearch.swift](/Users/ar/Projects/Apptag/Apptag/QuickSearch.swift:436) 的 `matchCandidate` 逻辑: |
| | | `isSubsequence` 不要做全局默认规则,必须按字段开关。 |
| | | |
| | | 建议改成类似: |
| | | |
| | | ```swift |
| | | if allowFuzzySubsequence && token.count >= 4 && isSubsequence(token, of: normalized) { |
| | | return (.fuzzy, 10) |
| | | } |
| | | ``` |
| | | |
| | | 然后: |
| | | |
| | | - `name` 才允许 `allowFuzzySubsequence = true` |
| | | - `tag / note / bundleIdentifier / internalName` 一律 `false` |
| | | |
| | | 4. 对拼音候选单独限流。 |
| | | 在 [QuickSearch.swift](/Users/ar/Projects/Apptag/Apptag/QuickSearch.swift:415) 里处理 `field.pinyinCandidates` 时,只允许: |
| | | - exact |
| | | - prefix |
| | | - 首字母 prefix |
| | | 不允许: |
| | | - substring |
| | | - subsequence fuzzy |
| | | |
| | | |
| | | |
| | | ** 4 条验收QA** |
| | | |
| | | - 输入 `sex` 时,不应该再出现 `News / Siri / FindMy / Stocks / Journal / Freeform / 无影云电脑` |
| | | - 输入 `不背`、`news`、`find`、`journal` 这类真实前缀,仍然要正常命中 |
| | | - 输入中文备注原文关键词,比如“新闻”“助手”“股票”,仍然可以通过 `note` 命中 |
| | | - `不背单词` 不应该再因为 `LangEasyLexis` 被 `sex` 这种短词带出来 |
| | | |
| New file |
| | |
| | | # APP 标签与备注规则沉淀 |
| | | |
| | | 更新时间:2026-05-19 14:27:47 |
| | | |
| | | ## 总原则 |
| | | |
| | | - 标签描述 APP 的核心用途,不描述品牌、热度、平台来源或运营感觉。 |
| | | - 一个 APP 通常给 1 到 4 个标签;宁可少而准,不堆砌。 |
| | | - 优先使用大众、清晰、可复用的词;避免生僻词、内部黑话和过度抽象词。 |
| | | - 不确定用途时先查资料;仍不确定就保守处理,不强行补标签或备注。 |
| | | - 标签服务于用户筛选场景:看到标签后,应能判断“它大概是干什么的”。 |
| | | |
| | | ## 标签判断 |
| | | |
| | | - 先判断主功能,再判断高频使用场景,最后才考虑技术实现。 |
| | | - APP 同时覆盖多个稳定场景时可以多标签;只是附带能力时不要加。 |
| | | - 标签应贴近用户心智,而不是开发者实现细节。 |
| | | - 同一类 APP 使用同一套标签,不因名称差异制造新词。 |
| | | - 新标签只有在能覆盖一批 APP、且比旧标签更有辨识度时才值得新增。 |
| | | |
| | | ## 泛标签处理 |
| | | |
| | | - `utilities` 太宽泛,应尽量拆到具体用途。 |
| | | - `system-enhancement` 类泛标签,应拆成 `window-management`、`device-management`、`Automation`、`system-maintenance`、`input-tools` 等。 |
| | | - `productivity` 应拆成 `PDF`、`GTD`、`Notes`、`Meeting`、`office`、`Automation`。 |
| | | - `design` 应拆成 `Font`、`ui-prototyping`、`3d-cad`、`diagramming`。 |
| | | - `development` 应拆成 `database-tools`、`terminal-tools`、`devops`、`api-tools`、`ide`、`runtime-sdk`。 |
| | | - `media` 不应单独承载大类意义;已有 `audio`、`video`、`picture-photo` 时去掉 `media`。 |
| | | |
| | | ## 父子标签去重 |
| | | |
| | | - 已有更具体标签时,删除更上一级的泛标签。 |
| | | - `game` 已足够明确,不再保留 `entertainment`。 |
| | | - `audio`、`video`、`picture-photo` 已足够明确,不再保留 `media`。 |
| | | - `Meeting` 已足够明确,不再保留 `communication`。 |
| | | - `Notes`、`PDF`、`ide` 已足够明确时,不再保留 `writing`。 |
| | | - `input-tools` 已足够明确时,不再保留 `device-management`。 |
| | | - `database-tools`、`api-tools` 已足够明确时,不再保留 `ide`。 |
| | | - `transfer` 明确表达传输场景时,不再保留泛化的 `file-management`。 |
| | | - `system` 只用于系统原生入口;已有具体系统功能标签时应删除。 |
| | | |
| | | ## 互补标签保留 |
| | | |
| | | - 不是所有多标签都要删;只有明确父子关系才去重。 |
| | | - `security|browser` 是互补关系,可以保留。 |
| | | - `ai-tools|ide` 是互补关系,可以保留。 |
| | | - `communication|entertainment` 是互补关系,可以保留。 |
| | | - `game|ide` 可用于游戏引擎等创作工具,可以保留。 |
| | | - `file-management|system-maintenance` 可能分别表达文件清理和系统维护,可以保留。 |
| | | |
| | | ## 典型拆分口径 |
| | | |
| | | - 启动器、快捷键、脚本、工作流、剪贴板增强:`Automation`。 |
| | | - 窗口排列、显示器、分屏、桌面空间:`window-management`。 |
| | | - 鼠标、键盘、触控板、外设、设备同步:`device-management`。 |
| | | - 输入法、键盘布局、文本扩展:`input-tools`。 |
| | | - 菜单栏监控、清理、电池、风扇、进程、日志:`system-maintenance`。 |
| | | - 终端、Shell、CLI 工作台:`terminal-tools`。 |
| | | - 容器、云、部署、虚拟机、Git 工作流:`devops`。 |
| | | - API 调试、接口测试、Webhook、GraphQL、代理调试:`api-tools`。 |
| | | - 代码编辑器和集成开发环境:`ide`。 |
| | | - SDK、运行时、编译器、语言环境、包管理:`runtime-sdk`。 |
| | | - 数据库连接、查询、建模、管理:`database-tools`。 |
| | | |
| | | ## 备注写法 |
| | | |
| | | - `defaultNote-ZH` 是一句话说明,不是介绍文章。 |
| | | - 备注要极简,中文不超过 80 字;其他语种也按同等长度控制。 |
| | | - 不重复 APP 名称,尤其不要以 APP 名称开头。 |
| | | - 句子直接说明“做什么、适合什么场景”。 |
| | | - 避免空泛模板,如“功能强大的工具”“适合日常使用”。 |
| | | - 避免照搬官网营销话术,改成用户能理解的实际用途。 |
| | | - 不了解 APP 时宁可留空,不编造。 |
| | | |
| | | ## 备注质量标准 |
| | | |
| | | - 好备注:能让用户在 3 秒内知道用途。 |
| | | - 好备注:不用软件名也成立。 |
| | | - 好备注:短、具体、可验证。 |
| | | - 坏备注:只是翻译软件名。 |
| | | - 坏备注:重复标签名,没有新增信息。 |
| | | - 坏备注:过长、堆功能、像官网宣传语。 |
| | | |
| | | ## 执行校验 |
| | | |
| | | - 每次批量改表后检查是否只改了目标列。 |
| | | - 检查是否存在空标签、重复标签、超过 4 个标签。 |
| | | - 检查旧泛标签是否真正清零。 |
| | | - 抽样查看头部、长尾和边界 APP,防止规则误伤。 |
| | | - 对自动规则产生的结果,要看样例;样例不合理就收紧规则。 |
| | | - 保存修改前备份,便于发现误伤后回滚重做。 |
| New file |
| | |
| | | # Apptag 文件总索引 |
| | | |
| | | 生成日期:2026-05-20 |
| | | 范围:`/Users/ar/Projects/Apptag` 当前文件夹下所有文件,排除 `.git` 目录。 |
| | | |
| | | ## Git 未跟踪文档文件 |
| | | |
| | | 以下文件当前处于 Git 未跟踪状态,且属于文档或文档型产物。后续如果要保留,需要单独纳入版本管理。 |
| | | |
| | | - [aaaindex.markdown](aaaindex.markdown) |
| | | - [Docs/PRD/TagLauncher_QuickSearch_CurrentRules_Snapshot.md](Docs/PRD/TagLauncher_QuickSearch_CurrentRules_Snapshot.md) |
| | | - [Docs/PRD/TagLauncher_QuickSearch_PRD_7.5_PMD_Rewrite_ZH.md](Docs/PRD/TagLauncher_QuickSearch_PRD_7.5_PMD_Rewrite_ZH.md) |
| | | - [Docs/PRD/TagLauncher_QuickSuggestions_PRD_7.5.md](Docs/PRD/TagLauncher_QuickSuggestions_PRD_7.5.md) |
| | | - [Docs/PRD/X-存档/TagLauncher_QuickSearch_PRD_7.5.md](Docs/PRD/X-存档/TagLauncher_QuickSearch_PRD_7.5.md) |
| | | - [Docs/PRD/X-存档/TagLauncher_QuickSearch_PRD_7.5_PMD_Rewrite.md](Docs/PRD/X-存档/TagLauncher_QuickSearch_PRD_7.5_PMD_Rewrite.md) |
| | | - [Docs/ProjectManagement/Apptag_Development_Workflow_Standard_v1.0.md](Docs/ProjectManagement/Apptag_Development_Workflow_Standard_v1.0.md) |
| | | - [Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_Report.md](Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_Report.md) |
| | | - [Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_TranslationQA.md](Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_TranslationQA.md) |
| | | - [Research/quick search/quicksearch-匹配规则C版-简化版-范围大大缩小.md](Research/quick%20search/quicksearch-匹配规则C版-简化版-范围大大缩小.md) |
| | | - [Research/quick search/搜索方案-保守版.md](Research/quick%20search/搜索方案-保守版.md) |
| | | - [X-KM/tager-20260519_142747.markdown](X-KM/tager-20260519_142747.markdown) |
| | | |
| | | ## Git 未跟踪的其他文件 |
| | | |
| | | 这些文件当前也未被 Git 跟踪,但不是 Markdown 文档。 |
| | | |
| | | - [Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_DuplicateReview.csv](Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_DuplicateReview.csv) |
| | | |
| | | ## 根目录 |
| | | |
| | | - [.DS_Store](.DS_Store) |
| | | - [.gitignore](.gitignore) |
| | | - [.hermes.md](.hermes.md) |
| | | - [AppStore_Submission.md](AppStore_Submission.md) |
| | | - [AppStore_TODO_7.3.5_744.md](AppStore_TODO_7.3.5_744.md) |
| | | - [CHANGELOG.md](CHANGELOG.md) |
| | | - [Decisions.md](Decisions.md) |
| | | - [SmartStart_GTD.md](SmartStart_GTD.md) |
| | | - [SmartStart_ProjectPlan.md](SmartStart_ProjectPlan.md) |
| | | - [aaaindex.markdown](aaaindex.markdown) |
| | | - [build.sh](build.sh) |
| | | - [generate_icon.py](generate_icon.py) |
| | | - [icon-icns.icns](icon-icns.icns) |
| | | - [make_dmg.sh](make_dmg.sh) |
| | | - [plan-deepthink.md](plan-deepthink.md) |
| | | |
| | | ## .hermes |
| | | |
| | | - [.hermes/plans/2026-05-05_124500-apptag-design.md](.hermes/plans/2026-05-05_124500-apptag-design.md) |
| | | |
| | | ## Apptag |
| | | |
| | | - [Apptag/.DS_Store](Apptag/.DS_Store) |
| | | - [Apptag/AppDefaults.swift](Apptag/AppDefaults.swift) |
| | | - [Apptag/AppDragCoordinator.swift](Apptag/AppDragCoordinator.swift) |
| | | - [Apptag/AppGridItem.swift](Apptag/AppGridItem.swift) |
| | | - [Apptag/AppleDefaultAppNotes.swift](Apptag/AppleDefaultAppNotes.swift) |
| | | - [Apptag/ApptagApp.swift](Apptag/ApptagApp.swift) |
| | | - [Apptag/ContentView.swift](Apptag/ContentView.swift) |
| | | - [Apptag/DataLayer.swift](Apptag/DataLayer.swift) |
| | | - [Apptag/EditModeViews.swift](Apptag/EditModeViews.swift) |
| | | - [Apptag/Info.plist](Apptag/Info.plist) |
| | | - [Apptag/L10n.swift](Apptag/L10n.swift) |
| | | - [Apptag/PreferencesView.swift](Apptag/PreferencesView.swift) |
| | | - [Apptag/QuickSearch.swift](Apptag/QuickSearch.swift) |
| | | - [Apptag/TagEditorView.swift](Apptag/TagEditorView.swift) |
| | | - [Apptag/TagGroupView.swift](Apptag/TagGroupView.swift) |
| | | - [Apptag/TagLauncher.entitlements](Apptag/TagLauncher.entitlements) |
| | | |
| | | ## Apptag/Assets.xcassets/AppIcon.appiconset |
| | | |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_1024_preview.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_1024_preview.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512.png) |
| | | - [Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png](Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png) |
| | | |
| | | ## Apptag/Localization |
| | | |
| | | - [Apptag/Localization/ar-Najdi.json](Apptag/Localization/ar-Najdi.json) |
| | | - [Apptag/Localization/ar.json](Apptag/Localization/ar.json) |
| | | - [Apptag/Localization/cs.json](Apptag/Localization/cs.json) |
| | | - [Apptag/Localization/da.json](Apptag/Localization/da.json) |
| | | - [Apptag/Localization/de.json](Apptag/Localization/de.json) |
| | | - [Apptag/Localization/en.json](Apptag/Localization/en.json) |
| | | - [Apptag/Localization/es.json](Apptag/Localization/es.json) |
| | | - [Apptag/Localization/fr.json](Apptag/Localization/fr.json) |
| | | - [Apptag/Localization/id.json](Apptag/Localization/id.json) |
| | | - [Apptag/Localization/it.json](Apptag/Localization/it.json) |
| | | - [Apptag/Localization/ja.json](Apptag/Localization/ja.json) |
| | | - [Apptag/Localization/ko.json](Apptag/Localization/ko.json) |
| | | - [Apptag/Localization/ms.json](Apptag/Localization/ms.json) |
| | | - [Apptag/Localization/nb.json](Apptag/Localization/nb.json) |
| | | - [Apptag/Localization/nl.json](Apptag/Localization/nl.json) |
| | | - [Apptag/Localization/nn.json](Apptag/Localization/nn.json) |
| | | - [Apptag/Localization/no.json](Apptag/Localization/no.json) |
| | | - [Apptag/Localization/pl.json](Apptag/Localization/pl.json) |
| | | - [Apptag/Localization/pt-BR.json](Apptag/Localization/pt-BR.json) |
| | | - [Apptag/Localization/ro.json](Apptag/Localization/ro.json) |
| | | - [Apptag/Localization/ru.json](Apptag/Localization/ru.json) |
| | | - [Apptag/Localization/sr-Cyrl.json](Apptag/Localization/sr-Cyrl.json) |
| | | - [Apptag/Localization/sv.json](Apptag/Localization/sv.json) |
| | | - [Apptag/Localization/th.json](Apptag/Localization/th.json) |
| | | - [Apptag/Localization/tr.json](Apptag/Localization/tr.json) |
| | | - [Apptag/Localization/uk.json](Apptag/Localization/uk.json) |
| | | - [Apptag/Localization/vi.json](Apptag/Localization/vi.json) |
| | | - [Apptag/Localization/zh-Hans.json](Apptag/Localization/zh-Hans.json) |
| | | - [Apptag/Localization/zh-Hant.json](Apptag/Localization/zh-Hant.json) |
| | | |
| | | ## Apptag/SmartCategorization |
| | | |
| | | - [Apptag/SmartCategorization/SmartCategorizationDraft.swift](Apptag/SmartCategorization/SmartCategorizationDraft.swift) |
| | | - [Apptag/SmartCategorization/SmartCategory.swift](Apptag/SmartCategorization/SmartCategory.swift) |
| | | - [Apptag/SmartCategorization/SmartStartService.swift](Apptag/SmartCategorization/SmartStartService.swift) |
| | | |
| | | ## CatalogOps |
| | | |
| | | - [CatalogOps/Candidates/.gitkeep](CatalogOps/Candidates/.gitkeep) |
| | | - [CatalogOps/Promoted/.gitkeep](CatalogOps/Promoted/.gitkeep) |
| | | - [CatalogOps/README.md](CatalogOps/README.md) |
| | | - [CatalogOps/Reports/.gitkeep](CatalogOps/Reports/.gitkeep) |
| | | - [CatalogOps/Runs/.gitkeep](CatalogOps/Runs/.gitkeep) |
| | | - [CatalogOps/Scripts/.gitkeep](CatalogOps/Scripts/.gitkeep) |
| | | - [CatalogOps/Sources/.gitkeep](CatalogOps/Sources/.gitkeep) |
| | | |
| | | ## Docs |
| | | |
| | | - [Docs/.DS_Store](Docs/.DS_Store) |
| | | |
| | | ## Docs/PRD |
| | | |
| | | - [Docs/PRD/.DS_Store](Docs/PRD/.DS_Store) |
| | | - [Docs/PRD/InitialDefaults_PRD.md](Docs/PRD/InitialDefaults_PRD.md) |
| | | - [Docs/PRD/SmartStart_PRD_UltimateDefaultCatalog.md](Docs/PRD/SmartStart_PRD_UltimateDefaultCatalog.md) |
| | | - [Docs/PRD/TagLauncher_QuickSearch_CurrentRules_Snapshot.md](Docs/PRD/TagLauncher_QuickSearch_CurrentRules_Snapshot.md) |
| | | - [Docs/PRD/TagLauncher_QuickSearch_PRD_7.5_PMD_Rewrite_ZH.md](Docs/PRD/TagLauncher_QuickSearch_PRD_7.5_PMD_Rewrite_ZH.md) |
| | | - [Docs/PRD/TagLauncher_QuickSuggestions_PRD_7.5.md](Docs/PRD/TagLauncher_QuickSuggestions_PRD_7.5.md) |
| | | |
| | | ## Docs/PRD/X-存档 |
| | | |
| | | - [Docs/PRD/X-存档/TagLauncher_QuickSearch_PRD_7.5.md](Docs/PRD/X-存档/TagLauncher_QuickSearch_PRD_7.5.md) |
| | | - [Docs/PRD/X-存档/TagLauncher_QuickSearch_PRD_7.5_PMD_Rewrite.md](Docs/PRD/X-存档/TagLauncher_QuickSearch_PRD_7.5_PMD_Rewrite.md) |
| | | |
| | | ## Docs/ProjectManagement |
| | | |
| | | - [Docs/ProjectManagement/Apptag_Development_Workflow_Standard_v1.0.md](Docs/ProjectManagement/Apptag_Development_Workflow_Standard_v1.0.md) |
| | | - [Docs/ProjectManagement/SmartStart_UltimateDefaultCatalog_ImplementationPlan.md](Docs/ProjectManagement/SmartStart_UltimateDefaultCatalog_ImplementationPlan.md) |
| | | |
| | | ## Docs/QA |
| | | |
| | | - [Docs/QA/InitialDefaults_TestCases.md](Docs/QA/InitialDefaults_TestCases.md) |
| | | - [Docs/QA/SmartStart_TestCases_UltimateDefaultCatalog.md](Docs/QA/SmartStart_TestCases_UltimateDefaultCatalog.md) |
| | | |
| | | ## Research |
| | | |
| | | - [Research/.DS_Store](Research/.DS_Store) |
| | | |
| | | ## Research/SmartStart |
| | | |
| | | - [Research/SmartStart/.DS_Store](Research/SmartStart/.DS_Store) |
| | | - [Research/SmartStart/AppDefaultTags_Review.csv](Research/SmartStart/AppDefaultTags_Review.csv) |
| | | |
| | | ## Research/SmartStart/Scripts |
| | | |
| | | - [Research/SmartStart/Scripts/build-default-tag-review-table.mjs](Research/SmartStart/Scripts/build-default-tag-review-table.mjs) |
| | | - [Research/SmartStart/Scripts/build-expanded-candidate-library.mjs](Research/SmartStart/Scripts/build-expanded-candidate-library.mjs) |
| | | - [Research/SmartStart/Scripts/build-persona-app-notes.mjs](Research/SmartStart/Scripts/build-persona-app-notes.mjs) |
| | | - [Research/SmartStart/Scripts/build-persona-top-apps.mjs](Research/SmartStart/Scripts/build-persona-top-apps.mjs) |
| | | - [Research/SmartStart/Scripts/build-ultimate-default-catalog.mjs](Research/SmartStart/Scripts/build-ultimate-default-catalog.mjs) |
| | | |
| | | ## Research/SmartStart/UltimateDefaultCatalog |
| | | |
| | | - [Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog.csv](Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog.csv) |
| | | - [Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog.json](Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog.json) |
| | | - [Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_DuplicateReview.csv](Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_DuplicateReview.csv) |
| | | - [Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_Report.md](Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_Report.md) |
| | | - [Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_TranslationQA.md](Research/SmartStart/UltimateDefaultCatalog/SmartStart_UltimateDefaultCatalog_TranslationQA.md) |
| | | |
| | | ## Research/logo |
| | | |
| | | - [Research/logo/TagLauncherMenuBarIcon_v2_light.svg](Research/logo/TagLauncherMenuBarIcon_v2_light.svg) |
| | | |
| | | ## Research/quick search |
| | | |
| | | - [Research/quick search/quicksearch-匹配规则C版-简化版-范围大大缩小.md](Research/quick%20search/quicksearch-匹配规则C版-简化版-范围大大缩小.md) |
| | | - [Research/quick search/搜索方案-保守版.md](Research/quick%20search/搜索方案-保守版.md) |
| | | |
| | | ## X-KM |
| | | |
| | | - [X-KM/tager-20260519_142747.markdown](X-KM/tager-20260519_142747.markdown) |
| | | |
| | | ## build/TagLauncher.app/Contents |
| | | |
| | | - [build/TagLauncher.app/Contents/Info.plist](build/TagLauncher.app/Contents/Info.plist) |
| | | - [build/TagLauncher.app/Contents/MacOS/TagLauncher](build/TagLauncher.app/Contents/MacOS/TagLauncher) |
| | | - [build/TagLauncher.app/Contents/PkgInfo](build/TagLauncher.app/Contents/PkgInfo) |
| | | |
| | | ## build/TagLauncher.app/Contents/Resources |
| | | |
| | | - [build/TagLauncher.app/Contents/Resources/AppIcon.icns](build/TagLauncher.app/Contents/Resources/AppIcon.icns) |
| | | - [build/TagLauncher.app/Contents/Resources/SmartStartAppDefaultTags.csv](build/TagLauncher.app/Contents/Resources/SmartStartAppDefaultTags.csv) |
| | | - [build/TagLauncher.app/Contents/Resources/SmartStartUltimateDefaultCatalog.csv](build/TagLauncher.app/Contents/Resources/SmartStartUltimateDefaultCatalog.csv) |
| | | - [build/TagLauncher.app/Contents/Resources/SmartStartUltimateDefaultCatalog.json](build/TagLauncher.app/Contents/Resources/SmartStartUltimateDefaultCatalog.json) |
| | | - [build/TagLauncher.app/Contents/Resources/TagLauncherMenuBarIcon.svg](build/TagLauncher.app/Contents/Resources/TagLauncherMenuBarIcon.svg) |
| | | |
| | | ## build/TagLauncher.app/Contents/Resources/Localization |
| | | |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/ar-Najdi.json](build/TagLauncher.app/Contents/Resources/Localization/ar-Najdi.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/ar.json](build/TagLauncher.app/Contents/Resources/Localization/ar.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/cs.json](build/TagLauncher.app/Contents/Resources/Localization/cs.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/da.json](build/TagLauncher.app/Contents/Resources/Localization/da.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/de.json](build/TagLauncher.app/Contents/Resources/Localization/de.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/en.json](build/TagLauncher.app/Contents/Resources/Localization/en.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/es.json](build/TagLauncher.app/Contents/Resources/Localization/es.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/fr.json](build/TagLauncher.app/Contents/Resources/Localization/fr.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/id.json](build/TagLauncher.app/Contents/Resources/Localization/id.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/it.json](build/TagLauncher.app/Contents/Resources/Localization/it.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/ja.json](build/TagLauncher.app/Contents/Resources/Localization/ja.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/ko.json](build/TagLauncher.app/Contents/Resources/Localization/ko.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/ms.json](build/TagLauncher.app/Contents/Resources/Localization/ms.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/nb.json](build/TagLauncher.app/Contents/Resources/Localization/nb.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/nl.json](build/TagLauncher.app/Contents/Resources/Localization/nl.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/nn.json](build/TagLauncher.app/Contents/Resources/Localization/nn.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/no.json](build/TagLauncher.app/Contents/Resources/Localization/no.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/pl.json](build/TagLauncher.app/Contents/Resources/Localization/pl.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/pt-BR.json](build/TagLauncher.app/Contents/Resources/Localization/pt-BR.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/ro.json](build/TagLauncher.app/Contents/Resources/Localization/ro.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/ru.json](build/TagLauncher.app/Contents/Resources/Localization/ru.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/sr-Cyrl.json](build/TagLauncher.app/Contents/Resources/Localization/sr-Cyrl.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/sv.json](build/TagLauncher.app/Contents/Resources/Localization/sv.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/th.json](build/TagLauncher.app/Contents/Resources/Localization/th.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/tr.json](build/TagLauncher.app/Contents/Resources/Localization/tr.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/uk.json](build/TagLauncher.app/Contents/Resources/Localization/uk.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/vi.json](build/TagLauncher.app/Contents/Resources/Localization/vi.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/zh-Hans.json](build/TagLauncher.app/Contents/Resources/Localization/zh-Hans.json) |
| | | - [build/TagLauncher.app/Contents/Resources/Localization/zh-Hant.json](build/TagLauncher.app/Contents/Resources/Localization/zh-Hant.json) |
| | | |
| | | ## build/TagLauncher.app/Contents/_CodeSignature |
| | | |
| | | - [build/TagLauncher.app/Contents/_CodeSignature/CodeResources](build/TagLauncher.app/Contents/_CodeSignature/CodeResources) |
| | | |
| | |
| | | PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" |
| | | BUILD_DIR="$PROJECT_DIR/build" |
| | | APP_BUNDLE="$BUILD_DIR/$APP_NAME.app" |
| | | APP_INFO_PLIST="$APP_BUNDLE/Contents/Info.plist" |
| | | MACOS_DIR="$APP_BUNDLE/Contents/MacOS" |
| | | RESOURCES_DIR="$APP_BUNDLE/Contents/Resources" |
| | | SWIFT_DIR="$PROJECT_DIR/Apptag" |
| | |
| | | TARGET="arm64-apple-macosx15.0" |
| | | |
| | | APP_VERSION=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$INFO_PLIST") |
| | | APP_BUILD=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$INFO_PLIST") |
| | | if [ -z "$APP_VERSION" ] || ! [[ "$APP_BUILD" =~ ^[0-9]+$ ]]; then |
| | | APP_BUILD="${APP_BUILD:-$(date '+%Y%m%d.%H%M')}" |
| | | SOURCE_INFO_PLIST_HASH_BEFORE=$(shasum -a 256 "$INFO_PLIST" | awk '{print $1}') |
| | | if [ -z "$APP_VERSION" ] || ! [[ "$APP_BUILD" =~ ^[0-9]{8}\.[0-9]{4}$ ]]; then |
| | | echo "❌ Invalid version metadata in $INFO_PLIST: version='$APP_VERSION' build='$APP_BUILD'" |
| | | exit 1 |
| | | fi |
| | |
| | | "${SWIFT_FILES[@]}" |
| | | |
| | | echo "==> Copying Info.plist..." |
| | | cp "$INFO_PLIST" "$APP_BUNDLE/Contents/Info.plist" |
| | | cp "$INFO_PLIST" "$APP_INFO_PLIST" |
| | | /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $APP_BUILD" "$APP_INFO_PLIST" |
| | | |
| | | echo "==> Copying AppIcon.icns..." |
| | | if [ -f "$PROJECT_DIR/icon-icns.icns" ]; then |
| | |
| | | codesign --force --deep --sign - "$APP_BUNDLE" |
| | | fi |
| | | |
| | | echo "==> Verifying source Info.plist was not modified..." |
| | | SOURCE_INFO_PLIST_HASH_AFTER=$(shasum -a 256 "$INFO_PLIST" | awk '{print $1}') |
| | | if [ "$SOURCE_INFO_PLIST_HASH_BEFORE" != "$SOURCE_INFO_PLIST_HASH_AFTER" ]; then |
| | | echo "❌ Build mutated tracked source file: $INFO_PLIST" |
| | | exit 1 |
| | | fi |
| | | |
| | | echo "" |
| | | echo "✅ App built at: $APP_BUNDLE" |
| | | echo " Run: open $APP_BUNDLE" |