| Apptag/ApptagApp.swift | ●●●●● patch | view | raw | blame | history | |
| Apptag/ContentView.swift | ●●●●● patch | view | raw | blame | history | |
| Apptag/DataLayer.swift | ●●●●● patch | view | raw | blame | history | |
| Apptag/Info.plist | ●●●●● patch | view | raw | blame | history | |
| Apptag/PreferencesView.swift | ●●●●● patch | view | raw | blame | history | |
| CHANGELOG.md | ●●●●● patch | view | raw | blame | history |
Apptag/ApptagApp.swift
@@ -499,15 +499,22 @@ NSMouseInRect(mousePoint, $0.frame, false) }) ?? NSScreen.main ?? NSScreen.screens.first else { return } overlayWindow?.orderOut(nil) overlayWindow = makeOverlayWindow(on: screen) overlayWindow?.setFrame(screen.frame, display: true) overlayWindow?.level = isEditingAppNote ? Self.overlayTextInputLevel : Self.overlayDefaultLevel let window: NSWindow if let existingWindow = overlayWindow { window = existingWindow } else { window = makeOverlayWindow(on: screen) overlayWindow = window } window.setFrame(screen.frame, display: true) window.level = isEditingAppNote ? Self.overlayTextInputLevel : Self.overlayDefaultLevel installOverlayKeyMonitor() overlayWindow?.makeKeyAndOrderFront(nil) overlayWindow?.orderFrontRegardless() window.makeKeyAndOrderFront(nil) window.orderFrontRegardless() NotificationCenter.default.post(name: .tagLauncherOverlayDidShow, object: nil) } private func installOverlayKeyMonitor() { Apptag/ContentView.swift
@@ -9,6 +9,7 @@ static let tagLauncherAppNoteEditingChanged = Notification.Name("TagLauncherAppNoteEditingChanged") static let tagLauncherDataDidChange = Notification.Name("TagLauncherDataDidChange") static let tagLauncherOpenPreferencesRequested = Notification.Name("TagLauncherOpenPreferencesRequested") static let tagLauncherOverlayDidShow = Notification.Name("TagLauncherOverlayDidShow") } // MARK: - Edit Phase @@ -483,14 +484,15 @@ } } .onAppear { let mousePoint = NSEvent.mouseLocation let activeScreen = NSScreen.screens.first(where: { NSMouseInRect(mousePoint, $0.frame, false) }) ?? NSScreen.main notchHeight = activeScreen?.safeAreaInsets.top ?? 0 refreshNotchHeight() refreshApps() } .onReceive(NotificationCenter.default.publisher(for: .tagLauncherOverlayDidShow)) { _ in refreshNotchHeight() refreshApps() } .onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in guard allApps.isEmpty, !refreshInProgress else { return } refreshApps() } .onReceive(NotificationCenter.default.publisher(for: .tagLauncherDataDidChange)) { _ in @@ -1853,6 +1855,14 @@ // MARK: - Actions private func refreshNotchHeight() { let mousePoint = NSEvent.mouseLocation let activeScreen = NSScreen.screens.first(where: { NSMouseInRect(mousePoint, $0.frame, false) }) ?? NSScreen.main notchHeight = activeScreen?.safeAreaInsets.top ?? 0 } private func handleBubbleHover(app: AppInfo, frame: CGRect, hovering: Bool) { guard !appBubbleDisabled else { clearAppBubbleState() @@ -2222,8 +2232,10 @@ func refreshApps(forceLayoutRefresh: Bool = false) { guard !refreshInProgress else { if forceLayoutRefresh { refreshAgainAfterCurrent = true refreshAgainForceLayout = refreshAgainForceLayout || forceLayoutRefresh refreshAgainForceLayout = true } return } Apptag/DataLayer.swift
@@ -51,6 +51,10 @@ // MARK: - App Scanner enum AppIndexer { private static let scanCacheLock = NSLock() private static var cachedScanApps: [AppInfo]? = nil private static var cachedScanAt: Date? = nil private static let scanCacheTTL: TimeInterval = 1800 static let searchPaths: [URL] = [ URL(fileURLWithPath: "/Applications"), @@ -72,7 +76,42 @@ } /// Scan all standard locations. Tags are annotated from TagDatabase by the caller. static func scan() -> [AppInfo] { static func scan(useCache: Bool = true) -> [AppInfo] { if useCache, let cached = cachedScanIfFresh() { return cached } let apps = performScan() updateScanCache(apps) return apps } static func invalidateScanCache() { scanCacheLock.lock() cachedScanApps = nil cachedScanAt = nil scanCacheLock.unlock() } private static func cachedScanIfFresh() -> [AppInfo]? { scanCacheLock.lock() defer { scanCacheLock.unlock() } guard let cachedScanApps, let cachedScanAt, Date().timeIntervalSince(cachedScanAt) < scanCacheTTL else { return nil } return cachedScanApps } private static func updateScanCache(_ apps: [AppInfo]) { scanCacheLock.lock() cachedScanApps = apps cachedScanAt = Date() scanCacheLock.unlock() } private static func performScan() -> [AppInfo] { var seenResolvedPaths = Set<String>() var apps: [AppInfo] = [] Apptag/Info.plist
@@ -19,9 +19,9 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>7.3.3</string> <string>7.3.4</string> <key>CFBundleVersion</key> <string>742</string> <string>743</string> <key>LSMinimumSystemVersion</key> <string>15.0</string> <key>NSHighResolutionCapable</key> Apptag/PreferencesView.swift
@@ -140,7 +140,7 @@ isApplyingSystemScheme = true DispatchQueue.global(qos: .userInitiated).async { let scannedApps = AppIndexer.scan() let scannedApps = AppIndexer.scan(useCache: false) let result = SmartStartService.applySystemInitialScheme(apps: scannedApps) let store = result.store let apps = TagEditor.annotate(apps: scannedApps, store: store) CHANGELOG.md
@@ -1,5 +1,12 @@ # Apptag Changelog ## [7.3.4] — 2026-05-18 - 优化应用列表打开速度:覆盖层窗口不再每次显示都销毁重建,减少重复初始化 - App 扫描增加会话缓存,避免短时间内反复加载全部应用图标导致每次打开都长时间等待 - 避免应用激活通知和首次显示同时触发重复全量刷新;刷新进行中时只保留必要的强制刷新请求 - 版本号更新为 `7.3.4`,Build 更新为 `743` ## [7.3.3] — 2026-05-18 - 拖拽 App 时会立即关闭并禁用 App 用途气泡,避免拖向目标容器时旧气泡继续遮挡视线