From c992a5929562434a8b0482ec7389cb7f70d20bb7 Mon Sep 17 00:00:00 2001
From: Ariver <ar@MacBook-Air.local>
Date: Wed, 06 May 2026 18:49:16 +0800
Subject: [PATCH] checkpoint: v3.1.5 — 第一二行间距加大12px
---
Apptag/ApptagApp.swift | 102 ++++++++++++++++++++++++++++++++++++++------------
1 files changed, 77 insertions(+), 25 deletions(-)
diff --git a/Apptag/ApptagApp.swift b/Apptag/ApptagApp.swift
index b93e706..d931a67 100644
--- a/Apptag/ApptagApp.swift
+++ b/Apptag/ApptagApp.swift
@@ -1,6 +1,7 @@
import SwiftUI
import AppKit
import Carbon
+import ServiceManagement
// MARK: - Application Entry Point
@@ -24,17 +25,47 @@
private var isInEditMode = false // Suppress auto-dismiss during editing
func applicationDidFinishLaunching(_ notification: Notification) {
- // Use .accessory so the app appears in Force Quit (unlike LSUIElement)
- NSApp.setActivationPolicy(.accessory)
+ L10n.setup()
+ let showDock = UserDefaults.standard.bool(forKey: "showDockIcon")
+ NSApp.setActivationPolicy(showDock ? .regular : .accessory)
setupMenuBar()
registerHotkey()
observeOtherWindows()
observeEditMode()
+ observeDockSetting()
+ setupLaunchAtLogin()
+ }
+
+ /// Observe Show in Dock changes so it takes effect immediately.
+ private func observeDockSetting() {
+ NotificationCenter.default.addObserver(
+ forName: UserDefaults.didChangeNotification,
+ object: nil, queue: .main
+ ) { _ in
+ let show = UserDefaults.standard.bool(forKey: "showDockIcon")
+ NSApp.setActivationPolicy(show ? .regular : .accessory)
+ }
+ }
+
+ /// Enable launch at login by default; prompt user if disabled.
+ private func setupLaunchAtLogin() {
+ let key = "launchAtLogin"
+ if UserDefaults.standard.object(forKey: key) == nil {
+ // First launch: enable by default
+ UserDefaults.standard.set(true, forKey: key)
+ try? SMAppService.mainApp.register()
+ } else if UserDefaults.standard.bool(forKey: key) {
+ try? SMAppService.mainApp.register()
+ }
}
// MARK: - Menu Bar
private func setupMenuBar() {
+ // Remove old status item if re-creating (language switch, etc.)
+ if let existing = statusItem {
+ NSStatusBar.system.removeStatusItem(existing)
+ }
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
if let button = statusItem.button {
@@ -50,7 +81,7 @@
let menu = NSMenu()
menu.addItem(
NSMenuItem(
- title: "Show Apptag",
+ title: tr("menu.show"),
action: #selector(toggleOverlay),
keyEquivalent: ""
)
@@ -61,7 +92,7 @@
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "?"
let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "?"
let versionItem = NSMenuItem(
- title: "Version \(appVersion) (\(buildNumber))",
+ title: "\(tr("menu.version")) \(appVersion) (\(buildNumber))",
action: nil,
keyEquivalent: ""
)
@@ -70,16 +101,31 @@
menu.addItem(.separator())
let prefsItem = NSMenuItem(
- title: "Preferences...",
+ title: tr("menu.preferences"),
action: #selector(openPreferences),
keyEquivalent: ","
)
prefsItem.keyEquivalentModifierMask = .command
menu.addItem(prefsItem)
menu.addItem(.separator())
+
+ // Language submenu
+ let langMenu = NSMenu()
+ let currentLang = L10n.currentCode
+ for (code, name) in L10n.supported {
+ let item = NSMenuItem(title: name, action: #selector(switchLanguage(_:)), keyEquivalent: "")
+ item.representedObject = code
+ item.state = (code == currentLang) ? .on : .off
+ langMenu.addItem(item)
+ }
+ let langItem = NSMenuItem(title: tr("menu.language"), action: nil, keyEquivalent: "")
+ langItem.submenu = langMenu
+ menu.addItem(langItem)
+
+ menu.addItem(.separator())
menu.addItem(
NSMenuItem(
- title: "Quit",
+ title: tr("menu.quit"),
action: #selector(NSApplication.terminate(_:)),
keyEquivalent: "q"
)
@@ -237,6 +283,13 @@
hideOverlay()
NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
}
+
+ @objc private func switchLanguage(_ sender: NSMenuItem) {
+ guard let code = sender.representedObject as? String else { return }
+ L10n.switchTo(code)
+ // Rebuild menu to update checkmarks
+ setupMenuBar()
+ }
}
// MARK: - NSView-level backdrop dismiss (works even if SwiftUI rendering is slow)
@@ -321,6 +374,8 @@
@AppStorage("defaultGroupName") private var defaultGroupName = "Other"
@AppStorage("displayMode") private var displayMode = "flat"
@AppStorage("hideAppNames") private var hideAppNames = false
+ @AppStorage("showDockIcon") private var showDockIcon = false
+ @AppStorage("launchAtLogin") private var launchAtLogin = true
@State private var allApps: [AppInfo] = []
@State private var tagColors: [String: Int] = [:]
@@ -387,6 +442,22 @@
// Tab 1: General
Form {
Section {
+ HStack(spacing: 20) {
+ Toggle("Launch at login", isOn: $launchAtLogin)
+ .onChange(of: launchAtLogin) { _, enabled in
+ if enabled {
+ try? SMAppService.mainApp.register()
+ } else {
+ try? SMAppService.mainApp.unregister()
+ }
+ }
+ Toggle("Show in Dock", isOn: $showDockIcon)
+ Toggle("Hide app names", isOn: $hideAppNames)
+ }
+ }
+ .padding(.bottom, 12)
+
+ Section {
LabeledContent("App list style:") {
Picker("", selection: $displayMode) {
Text("Flat").tag("flat")
@@ -444,10 +515,6 @@
.font(.caption)
.foregroundStyle(.secondary)
}
-
- Section {
- Toggle("Hide app names", isOn: $hideAppNames)
- }
}
.tabItem { Label("General", systemImage: "gearshape") }
.padding()
@@ -465,21 +532,6 @@
// Tab 3: Data
Form {
- Section {
- HStack {
- Button("Re-index Now") {
- NotificationCenter.default.post(name: .apptagReindex, object: nil)
- }
- .buttonStyle(.borderedProminent)
-
- Text("Re-scan all app directories and refresh the tag database.")
- .font(.caption)
- .foregroundStyle(.secondary)
- }
- } header: {
- Text("Index Management")
- }
-
Section {
HStack(spacing: 12) {
Button("Export Tags…") { exportTags() }
--
Gitblit v1.9.3