From 9d6f138e40a5322ee731f8096eaa3332c94a6532 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 18 May 2026 17:54:35 +0800
Subject: [PATCH] Speed up repeated app list opens

---
 Apptag/DataLayer.swift |   41 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 40 insertions(+), 1 deletions(-)

diff --git a/Apptag/DataLayer.swift b/Apptag/DataLayer.swift
index 6b0f69a..779beac 100644
--- a/Apptag/DataLayer.swift
+++ b/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] = []
 

--
Gitblit v1.9.3