From 0badb998147135c75187a0c48f926b665af734c5 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sun, 28 Jun 2026 02:53:51 +0800
Subject: [PATCH] Release 8.1.6 build 20260628.0230
---
src/Apptag/ApptagApp.swift | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 163 insertions(+), 10 deletions(-)
diff --git a/src/Apptag/ApptagApp.swift b/src/Apptag/ApptagApp.swift
index bb6b32b..53dfb40 100644
--- a/src/Apptag/ApptagApp.swift
+++ b/src/Apptag/ApptagApp.swift
@@ -39,7 +39,10 @@
private static let downloadHelpMenuItemIdentifier = NSUserInterfaceItemIdentifier("TagLauncherDownloadHelpMenuItem")
private static let externalActivationNotification = Notification.Name("TagLauncherExternalActivationRequested")
private static let externalActivationObject = AppIdentity.bundleIdentifier
+ private static let externalInvocationScheme = "taglauncher"
+ private static let externalInvocationShowHost = "show"
private static let duplicateLaunchSuppressReopenKey = "duplicateLaunchSuppressReopenAt"
+ private static let overlaySpaceHotkeyID: UInt32 = 3
private static let launcherOverlayLevel = NSWindow.Level(rawValue: NSWindow.Level.mainMenu.rawValue - 1)
private static let overlayDefaultLevel = launcherOverlayLevel
private static let overlayTextInputLevel = launcherOverlayLevel
@@ -50,8 +53,10 @@
private var quickSearchLocalMouseMonitor: Any?
private var quickSearchExternalMouseMonitor: Any?
private var settingsWindow: NSWindow? // Track Settings window to keep it above overlay
+ private var explicitPreferencesOpenRequestedAt = Date.distantPast
private var mainHotkeyRef: EventHotKeyRef?
private var quickSearchHotkeyRef: EventHotKeyRef?
+ private var overlaySpaceHotkeyRef: EventHotKeyRef?
private var hotkeyEventHandlerInstalled = false
private var isQuickSearchOpen = false
private var quickSearchShouldHideOverlayOnClose = false
@@ -65,6 +70,8 @@
private var statusMenuScreenForNextOverlay: NSScreen?
private var suppressReopenUntil = Date.distantPast
private var overlayOpenedByQuickSearchOnly = false
+ private var didFinishLaunching = false
+ private var pendingShowOverlayInvocation = false
private lazy var overlayController = OverlayWindowController(
dependencies: OverlayWindowController.Dependencies(
@@ -127,14 +134,16 @@
refreshChromeState: { [weak self] activate, avoidSpaceSwitch in
self?.refreshLauncherChromeState(activate: activate, avoidSpaceSwitch: avoidSpaceSwitch)
},
- onWillHide: {
+ onWillHide: { [weak self] in
+ self?.unregisterOverlaySpaceHotkey()
TagDatabase.flushPendingCategorySchemeBackupBatch()
},
onDidHide: { [weak self] in
self?.overlayOpenedByQuickSearchOnly = false
NotificationCenter.default.post(name: .tagLauncherOverlayDidHide, object: nil)
},
- onDidShow: {
+ onDidShow: { [weak self] in
+ self?.refreshOverlaySpaceHotkeyRegistration()
NotificationCenter.default.post(name: .tagLauncherOverlayDidShow, object: nil)
}
)
@@ -213,6 +222,9 @@
observeLanguageChanges()
setupLaunchAtLogin()
suppressReopenUntil = Date().addingTimeInterval(1.0)
+ didFinishLaunching = true
+ closeRestoredPreferencesWindowsDuringLaunch()
+ consumePendingShowOverlayInvocationIfNeeded()
configureApplicationMenuWhenAvailable(retries: 200)
warmAppIndexInBackground()
relocalizeDefaultAppNotesForCurrentLanguageAsync()
@@ -243,6 +255,54 @@
guard isRecentUserClickNearDockArea() else { return false }
showOrFocusOverlay()
return false // Suppress default "unhide all windows" behavior
+ }
+
+ func application(_ application: NSApplication, open urls: [URL]) {
+ for url in urls {
+ handleExternalInvocationURL(url)
+ }
+ }
+
+ private enum ExternalInvocationRoute {
+ case showOverlay
+ }
+
+ private func handleExternalInvocationURL(_ url: URL) {
+ guard externalInvocationRoute(for: url) == .showOverlay else {
+ Diagnostics.log("app.externalInvocation.ignored", [
+ "url": url.absoluteString
+ ])
+ return
+ }
+ requestShowOverlayFromExternalInvocation()
+ }
+
+ private func externalInvocationRoute(for url: URL) -> ExternalInvocationRoute? {
+ guard url.scheme?.lowercased() == Self.externalInvocationScheme else {
+ return nil
+ }
+ let host = url.host?.lowercased()
+ let path = url.path
+ if host == Self.externalInvocationShowHost, path.isEmpty || path == "/" {
+ return .showOverlay
+ }
+ return nil
+ }
+
+ private func requestShowOverlayFromExternalInvocation() {
+ guard didFinishLaunching else {
+ pendingShowOverlayInvocation = true
+ return
+ }
+ pendingShowOverlayInvocation = false
+ suppressReopenUntil = Date().addingTimeInterval(1.0)
+ dismissQuickSearchIfNeeded()
+ showOrFocusOverlay()
+ }
+
+ private func consumePendingShowOverlayInvocationIfNeeded() {
+ guard pendingShowOverlayInvocation else { return }
+ requestShowOverlayFromExternalInvocation()
}
private func isRecentUserClickNearDockArea() -> Bool {
@@ -293,6 +353,7 @@
hideOverlay(force: true, discardWindow: true)
unregisterHotkey(for: .main)
unregisterHotkey(for: .quickSearch)
+ unregisterOverlaySpaceHotkey()
TagDatabase.flushPendingCategorySchemeBackupBatch()
removeOverlayKeyMonitor()
removeQuickSearchExternalMouseMonitor()
@@ -480,14 +541,17 @@
if activate && requiresForegroundOwnership
&& !shouldStayAccessoryForCurrentFullscreenSpace
- && !shouldStayAccessoryForHiddenDockChrome
&& !shouldStayAccessoryForQuickOnlySearch {
let keyWindow = isSettingsVisible ? settingsWindow : (isOverlayVisible ? overlayWindow : nil)
- claimLauncherForeground(
- keyWindow: keyWindow,
- retries: isOverlayVisible && !isSettingsVisible ? 5 : 0,
- overlayGeneration: isOverlayVisible ? overlayGeneration : nil
- )
+ if shouldStayAccessoryForHiddenDockChrome {
+ beginLauncherForegroundOwnership(activate: true, keyWindow: keyWindow)
+ } else {
+ claimLauncherForeground(
+ keyWindow: keyWindow,
+ retries: isOverlayVisible && !isSettingsVisible ? 5 : 0,
+ overlayGeneration: isOverlayVisible ? overlayGeneration : nil
+ )
+ }
}
}
@@ -1298,9 +1362,27 @@
])
if id == LauncherHotkeyKind.quickSearch.eventID {
showQuickSearchFromGlobalHotkey()
+ } else if id == Self.overlaySpaceHotkeyID {
+ handleOverlaySpaceHotkey()
} else {
performToggleOverlay(preferredScreen: nil)
}
+ }
+
+ private func handleOverlaySpaceHotkey() {
+ guard canUseOverlaySpaceHotkey else { return }
+ unregisterOverlaySpaceHotkey()
+ requestQuickSearch(source: QuickSearchOpenSource.mainOverlay)
+ }
+
+ private var canUseOverlaySpaceHotkey: Bool {
+ overlayWindow?.isVisible == true
+ && !isSettingsVisible
+ && !isQuickSearchOpen
+ && !quickSearchOnlyOverlaySession
+ && !isInEditMode
+ && !isEditingAppNote
+ && !isModalInteractionActive
}
private func showQuickSearchFromGlobalHotkey() {
@@ -1358,6 +1440,46 @@
}
}
+ private func refreshOverlaySpaceHotkeyRegistration() {
+ if canUseOverlaySpaceHotkey {
+ registerOverlaySpaceHotkeyIfNeeded()
+ } else {
+ unregisterOverlaySpaceHotkey()
+ }
+ }
+
+ private func registerOverlaySpaceHotkeyIfNeeded() {
+ guard overlaySpaceHotkeyRef == nil else { return }
+
+ var hotkeyID = EventHotKeyID()
+ hotkeyID.signature = OSType(0x41505447) // 'APTG'
+ hotkeyID.id = Self.overlaySpaceHotkeyID
+
+ var newRef: EventHotKeyRef?
+ let status = RegisterEventHotKey(
+ UInt32(kVK_Space),
+ 0,
+ hotkeyID,
+ GetApplicationEventTarget(),
+ 0,
+ &newRef
+ )
+
+ if status == noErr, let newRef {
+ overlaySpaceHotkeyRef = newRef
+ } else {
+ overlaySpaceHotkeyRef = nil
+ Diagnostics.log("app.overlay.spaceHotkey.failed", ["status": status])
+ }
+ }
+
+ private func unregisterOverlaySpaceHotkey() {
+ if let overlaySpaceHotkeyRef {
+ UnregisterEventHotKey(overlaySpaceHotkeyRef)
+ self.overlaySpaceHotkeyRef = nil
+ }
+ }
+
// MARK: - Preferences
/// Hide overlay when any other window becomes key (catches Cmd+, via SwiftUI Settings).
@@ -1409,6 +1531,9 @@
forContentRect: NSRect(origin: .zero, size: settingsSize)
).size
window.identifier = NSUserInterfaceItemIdentifier("TagLauncherPreferencesWindow")
+ window.isRestorable = false
+ window.restorationClass = nil
+ _ = window.setFrameAutosaveName("")
window.contentMinSize = settingsSize
window.contentMaxSize = settingsSize
window.minSize = settingsFrameSize
@@ -1441,6 +1566,7 @@
window.makeKeyAndOrderFront(nil)
window.orderFrontRegardless()
settingsWindow = window
+ refreshOverlaySpaceHotkeyRegistration()
refreshLauncherChromeState(
activate: !overlayAvoidsSpaceSwitch,
avoidSpaceSwitch: overlayAvoidsSpaceSwitch
@@ -1545,6 +1671,7 @@
activate: shouldRefocusOverlay && !self.overlayAvoidsSpaceSwitch,
avoidSpaceSwitch: self.overlayAvoidsSpaceSwitch
)
+ self.refreshOverlaySpaceHotkeyRegistration()
guard shouldRefocusOverlay else { return }
DispatchQueue.main.asyncAfter(deadline: .now() + 0.12) { [weak self] in
self?.showOrFocusOverlay(preferredScreen: preferredScreen)
@@ -1559,7 +1686,9 @@
object: nil,
queue: .main
) { [weak self] notification in
- self?.isInEditMode = (notification.userInfo?["active"] as? Bool) ?? false
+ guard let self else { return }
+ self.isInEditMode = (notification.userInfo?["active"] as? Bool) ?? false
+ self.refreshOverlaySpaceHotkeyRegistration()
}
}
@@ -1576,6 +1705,7 @@
self.promoteOverlayToForegroundInput()
}
self.updateOverlayLevelForTextInput()
+ self.refreshOverlaySpaceHotkeyRegistration()
}
}
@@ -1642,6 +1772,7 @@
self.hideOverlay(force: true, discardWindow: wasQuickSearchOnlyOverlay)
}
}
+ self.refreshOverlaySpaceHotkeyRegistration()
}
NotificationCenter.default.addObserver(
@@ -1649,7 +1780,9 @@
object: nil,
queue: .main
) { [weak self] notification in
- self?.isModalInteractionActive = (notification.userInfo?["active"] as? Bool) ?? false
+ guard let self else { return }
+ self.isModalInteractionActive = (notification.userInfo?["active"] as? Bool) ?? false
+ self.refreshOverlaySpaceHotkeyRegistration()
}
NotificationCenter.default.addObserver(
@@ -1757,6 +1890,7 @@
}
private func openPreferences(targetTab: String?) {
+ explicitPreferencesOpenRequestedAt = Date()
dismissQuickSearchIfNeeded()
TagDatabase.flushPendingCategorySchemeBackupBatch()
if overlayAvoidsSpaceSwitch {
@@ -1789,6 +1923,25 @@
prepareSettingsWindow(window)
}
+ private func closeRestoredPreferencesWindowsDuringLaunch() {
+ for delay in [0.25, 0.8, 1.6, 2.6] {
+ DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
+ self?.closeRestoredPreferencesWindowIfNeeded()
+ }
+ }
+ }
+
+ private func closeRestoredPreferencesWindowIfNeeded() {
+ guard Date().timeIntervalSince(explicitPreferencesOpenRequestedAt) > 3.0 else { return }
+ for window in NSApp.windows where isSettingsWindowCandidate(window) {
+ detachSettingsWindow(window)
+ window.close()
+ if settingsWindow == window {
+ settingsWindow = nil
+ }
+ }
+ }
+
private func requestPreferencesTabSelection(_ targetTab: String?) {
guard let targetTab else { return }
NotificationCenter.default.post(
--
Gitblit v1.9.3