From eeb97e9c41b6939b29fd42402aa5c4d3f97663e9 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Fri, 05 Jun 2026 01:42:07 +0800
Subject: [PATCH] Add 7.8.14 App Store candidate package

---
 Apptag/SmartCategorization/SmartStartService.swift |  484 ++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 360 insertions(+), 124 deletions(-)

diff --git a/Apptag/SmartCategorization/SmartStartService.swift b/Apptag/SmartCategorization/SmartStartService.swift
index 97016f4..15bc507 100644
--- a/Apptag/SmartCategorization/SmartStartService.swift
+++ b/Apptag/SmartCategorization/SmartStartService.swift
@@ -1,3 +1,4 @@
+import Compression
 import Foundation
 
 // MARK: - Smart Start Catalog Runtime
@@ -23,33 +24,84 @@
 }
 
 private struct SmartStartCatalogEntry {
+    let entryID: String
     let rank: Int
     let name: String
     let normalizedName: String
     let bundleIdentifier: String?
     let categoryIDs: [SmartCategoryID]
-    let localizedNote: String?
-    let notes: [String: String]?
+    let localizedNote: SmartStartLocalizedNote?
     let sourceEvidence: [String]
 }
 
-private struct SmartStartRuntimeCatalog: Decodable {
-    let version: Int
-    let entries: [SmartStartRuntimeCatalogEntry]
+private struct SmartStartLocalizedNote {
+    let note: String
+    let languageCode: String
+    let provenance: SmartDefaultNoteProvenance
 }
 
-private struct SmartStartRuntimeCatalogEntry: Decodable {
+private struct SmartStartBaseCatalog: Decodable {
+    let resourceFormatVersion: Int
+    let catalogContentVersion: Int
+    let noteLimit: Int?
+    let supportedLanguages: [String]
+    let fallbackLanguages: [String]
+    let entries: [SmartStartBaseCatalogEntry]
+}
+
+private struct SmartStartBaseCatalogEntry: Decodable {
+    let entryID: String
     let rank: Int?
     let name: String
     let normalizedName: String?
     let bundleIdentifier: String?
     let defaultTag: [String]
-    let notes: [String: String]?
     let sourceEvidence: [String]?
+}
+
+private struct SmartStartNotesCatalog: Decodable {
+    let resourceFormatVersion: Int
+    let catalogContentVersion: Int
+    let notesVersion: Int
+    let language: String
+    let entries: [SmartStartNoteEntry]
+}
+
+private struct SmartStartNoteEntry: Decodable {
+    let entryID: String
+    let note: String
+}
+
+private struct SmartStartBaseSnapshot {
+    let catalogContentVersion: Int
+    let supportedLanguages: [String]
+    let fallbackLanguages: [String]
+    let entries: [SmartStartBaseCatalogEntry]
+    let bundleIndex: [String: SmartStartBaseCatalogEntry]
+    let nameIndex: [String: SmartStartBaseCatalogEntry]
+    let entryIndex: [String: SmartStartBaseCatalogEntry]
+}
+
+private struct SmartStartNotesSnapshot {
+    let languageCode: String
+    let notesVersion: Int
+    let notes: [String: String]
+}
+
+private struct SmartStartCatalogSnapshot {
+    let entries: [SmartStartCatalogEntry]
+    let bundleIndex: [String: SmartStartCatalogEntry]
+    let nameIndex: [String: SmartStartCatalogEntry]
+    let entryIndex: [String: SmartStartCatalogEntry]
 }
 
 enum SmartStartService {
     static let catalogVersion = 2
+    private static let catalogCacheLock = NSLock()
+    private static var cachedBaseSnapshot: SmartStartBaseSnapshot?
+    private static var cachedCatalogSnapshots: [String: SmartStartCatalogSnapshot] = [:]
+    private static var cachedNotesSnapshots: [String: SmartStartNotesSnapshot] = [:]
+
     static let systemInitialSchemeCreatedAt: Date = {
         var components = DateComponents()
         components.calendar = Calendar(identifier: .gregorian)
@@ -146,45 +198,30 @@
 
     @discardableResult
     static func relocalizeDefaultNotesForCurrentLanguage(apps: [AppInfo]) -> Bool {
-        let catalog = loadCatalog()
-        guard !catalog.isEmpty else { return false }
-
-        var bundleIndex: [String: SmartStartCatalogEntry] = [:]
-        for entry in catalog {
-            guard let bundleIdentifier = entry.bundleIdentifier?.lowercased(), !bundleIdentifier.isEmpty else {
-                continue
-            }
-            if let existing = bundleIndex[bundleIdentifier], existing.rank <= entry.rank {
-                continue
-            }
-            bundleIndex[bundleIdentifier] = entry
-        }
-
-        let nameIndex = Dictionary(
-            grouping: catalog,
-            by: { $0.normalizedName }
-        ).compactMapValues { entries in
-            entries.sorted { $0.rank < $1.rank }.first
-        }
+        let catalog = loadCatalogSnapshot()
+        guard !catalog.entries.isEmpty else { return false }
 
         var store = TagDatabase.load()
         var changed = false
+        let appPaths = Set(apps.map { $0.path.path })
 
-        for app in apps {
-            let path = app.path.path
+        for path in appPaths {
             guard let currentNote = normalizedNote(store.appNotes[path]) else { continue }
-            guard let matched = match(app: app, bundleIndex: bundleIndex, nameIndex: nameIndex),
-                  let notes = matched.notes,
-                  !notes.isEmpty
+            guard let metadata = store.appNoteMetadata[path],
+                  metadata.origin == .catalogDefault,
+                  let currentCatalog = metadata.catalog,
+                  currentCatalog.noteFingerprint == TagDatabase.noteFingerprint(currentNote),
+                  let matched = catalog.entryIndex[currentCatalog.entryID],
+                  let localizedNote = matched.localizedNote,
+                  localizedNote.note != currentNote
             else { continue }
 
-            let knownDefaultNotes = Set(notes.values.compactMap(normalizedNote))
-            guard knownDefaultNotes.contains(currentNote),
-                  let localizedNote = localizedNote(from: notes),
-                  localizedNote != currentNote
-            else { continue }
-
-            store.appNotes[path] = localizedNote
+            store.appNotes[path] = localizedNote.note
+            store.appNoteMetadata[path] = TagDatabase.AppNoteMetadata(
+                origin: .catalogDefault,
+                catalog: localizedNote.provenance,
+                noteFingerprint: localizedNote.provenance.noteFingerprint
+            )
             changed = true
         }
 
@@ -215,30 +252,18 @@
     }
 
     static func makeDraft(apps: [AppInfo]) -> SmartCategorizationDraft {
-        let catalog = loadCatalog()
-        var bundleIndex: [String: SmartStartCatalogEntry] = [:]
-        for entry in catalog {
-            guard let bundleIdentifier = entry.bundleIdentifier?.lowercased(), !bundleIdentifier.isEmpty else {
-                continue
-            }
-            if let existing = bundleIndex[bundleIdentifier], existing.rank <= entry.rank {
-                continue
-            }
-            bundleIndex[bundleIdentifier] = entry
-        }
-        let nameIndex = Dictionary(
-            grouping: catalog,
-            by: { $0.normalizedName }
-        ).compactMapValues { entries in
-            entries.sorted { $0.rank < $1.rank }.first
-        }
+        let catalog = loadCatalogSnapshot()
 
         var seenAssignments = Set<String>()
         var assignments: [SmartAppCategorizationAssignment] = []
         var unassigned: [SmartUnassignedApp] = []
 
         for app in apps {
-            let matched = match(app: app, bundleIndex: bundleIndex, nameIndex: nameIndex)
+            let matched = match(
+                app: app,
+                bundleIndex: catalog.bundleIndex,
+                nameIndex: catalog.nameIndex
+            )
             guard let matched else {
                 unassigned.append(SmartUnassignedApp(
                     appName: app.name,
@@ -261,7 +286,9 @@
                 source: .localCatalog,
                 reason: "Matched Smart Start catalog entry: \(matched.name)",
                 provenance: matched.sourceEvidence,
-                defaultNote: matched.localizedNote
+                defaultNote: matched.localizedNote?.note,
+                defaultNoteCandidates: matched.localizedNote.map { [$0.note] } ?? [],
+                defaultNoteProvenance: matched.localizedNote?.provenance
             ))
         }
 
@@ -314,6 +341,10 @@
                 continue
             }
             if let result = TagDatabase.ensureSystemTag(for: categoryID, in: &store) {
+                if var tagDef = store.tags[result.name] {
+                    tagDef.color = categoryID.defaultColorIndex
+                    store.tags[result.name] = tagDef
+                }
                 if result.created {
                     createdTagCount += 1
                 }
@@ -348,12 +379,32 @@
             }
 
             if let defaultNote = assignment.defaultNote?.trimmingCharacters(in: .whitespacesAndNewlines),
-               !defaultNote.isEmpty,
-               store.appNotes[path]?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty != false {
-                store.appNotes[path] = String(defaultNote.prefix(TagDatabase.maxAppNoteLength))
-                uncommonPaths.insert(path)
-                if store.uncommonSources[path] == nil {
-                    store.uncommonSources[path] = .auto
+               !defaultNote.isEmpty {
+                let currentNote = store.appNotes[path]?.trimmingCharacters(in: .whitespacesAndNewlines)
+                let normalizedCurrentNote = normalizedNote(currentNote)
+                let existingMetadata = store.appNoteMetadata[path]
+                let currentMatchesCatalogDefault = existingMetadata?.origin == .catalogDefault
+                    && normalizedCurrentNote.map { TagDatabase.noteFingerprint($0) } == existingMetadata?.catalog?.noteFingerprint
+                let knownDefaultNotes = Set(assignment.defaultNoteCandidates.compactMap(normalizedNote))
+                let shouldSeedNote = currentNote?.isEmpty != false
+                    || currentMatchesCatalogDefault
+                    || normalizedCurrentNote.map { knownDefaultNotes.contains($0) } == true
+
+                if shouldSeedNote {
+                    store.appNotes[path] = String(defaultNote.prefix(TagDatabase.maxAppNoteLength))
+                    if let provenance = assignment.defaultNoteProvenance {
+                        store.appNoteMetadata[path] = TagDatabase.AppNoteMetadata(
+                            origin: .catalogDefault,
+                            catalog: provenance,
+                            noteFingerprint: provenance.noteFingerprint
+                        )
+                    }
+                    if currentNote?.isEmpty != false {
+                        uncommonPaths.insert(path)
+                        if store.uncommonSources[path] == nil {
+                            store.uncommonSources[path] = .auto
+                        }
+                    }
                 }
             }
         }
@@ -413,26 +464,45 @@
         return 0.68
     }
 
-    private static func loadCatalog() -> [SmartStartCatalogEntry] {
-        if let catalog = loadRuntimeCatalog() {
-            return catalog
+    private static func loadCatalogSnapshot() -> SmartStartCatalogSnapshot {
+        let languageCode = L10n.currentCode
+        catalogCacheLock.lock()
+        if let snapshot = cachedCatalogSnapshots[languageCode] {
+            catalogCacheLock.unlock()
+            return snapshot
         }
-        return loadLegacyCSVCatalog()
+        catalogCacheLock.unlock()
+
+        guard let base = loadBaseSnapshot() else {
+            return SmartStartCatalogSnapshot(entries: [], bundleIndex: [:], nameIndex: [:], entryIndex: [:])
+        }
+        let snapshot = makeCatalogSnapshot(base: base, languageCode: languageCode)
+
+        catalogCacheLock.lock()
+        if let cached = cachedCatalogSnapshots[languageCode] {
+            catalogCacheLock.unlock()
+            return cached
+        }
+        cachedCatalogSnapshots[languageCode] = snapshot
+        catalogCacheLock.unlock()
+        return snapshot
     }
 
-    private static func loadRuntimeCatalog() -> [SmartStartCatalogEntry]? {
-        guard let url = Bundle.main.url(forResource: "SmartStartUltimateDefaultCatalog", withExtension: "json"),
-              let data = try? Data(contentsOf: url),
-              let catalog = try? JSONDecoder().decode(SmartStartRuntimeCatalog.self, from: data)
-        else { return nil }
-
-        return catalog.entries.compactMap { entry in
+    private static func makeCatalogSnapshot(
+        base: SmartStartBaseSnapshot,
+        languageCode: String
+    ) -> SmartStartCatalogSnapshot {
+        let localizedNotes = loadLocalizedNotes(
+            for: languageFallbacks(preferredCode: languageCode, base: base)
+        )
+        let entries = base.entries.compactMap { entry -> SmartStartCatalogEntry? in
             let tagIDs = entry.defaultTag
                 .compactMap { SmartCategoryID(rawValue: $0) }
                 .filter { $0 != .other }
             guard !tagIDs.isEmpty else { return nil }
 
             return SmartStartCatalogEntry(
+                entryID: entry.entryID,
                 rank: entry.rank ?? Int.max,
                 name: entry.name,
                 normalizedName: entry.normalizedName.flatMap {
@@ -440,64 +510,230 @@
                 } ?? normalizedName(entry.name),
                 bundleIdentifier: normalizedBundleIdentifier(entry.bundleIdentifier),
                 categoryIDs: uniqueOrdered(tagIDs),
-                localizedNote: localizedNote(from: entry.notes),
-                notes: entry.notes,
+                localizedNote: localizedNotes[entry.entryID],
                 sourceEvidence: entry.sourceEvidence ?? []
             )
         }
-    }
 
-    private static func loadLegacyCSVCatalog() -> [SmartStartCatalogEntry] {
-        guard let url = Bundle.main.url(forResource: "SmartStartAppDefaultTags", withExtension: "csv"),
-              let csv = try? String(contentsOf: url, encoding: .utf8)
-        else { return [] }
+        var bundleIndex: [String: SmartStartCatalogEntry] = [:]
+        var nameIndex: [String: SmartStartCatalogEntry] = [:]
+        var entryIndex: [String: SmartStartCatalogEntry] = [:]
 
-        let rows = parseCSV(csv)
-        guard let header = rows.first else { return [] }
-        let dataRows = rows.dropFirst()
+        for entry in entries {
+            entryIndex[entry.entryID] = entry
+            if let bundleIdentifier = entry.bundleIdentifier?.lowercased(), !bundleIdentifier.isEmpty {
+                if bundleIndex[bundleIdentifier].map({ $0.rank <= entry.rank }) != true {
+                    bundleIndex[bundleIdentifier] = entry
+                }
+            }
 
-        return dataRows.compactMap { row in
-            let values = Dictionary(uniqueKeysWithValues: header.enumerated().map { index, key in
-                (key, index < row.count ? row[index] : "")
-            })
-            let tagIDs = splitPipe(values["defaultTagIDs"] ?? "")
-                .compactMap { SmartCategoryID(rawValue: $0) }
-                .filter { $0 != .other }
-            guard !tagIDs.isEmpty else { return nil }
-
-            return SmartStartCatalogEntry(
-                rank: Int(values["rank"] ?? "") ?? Int.max,
-                name: values["name"] ?? "",
-                normalizedName: values["normalizedName"].flatMap {
-                    $0.isEmpty ? nil : $0
-                } ?? normalizedName(values["name"] ?? ""),
-                bundleIdentifier: normalizedBundleIdentifier(values["bundleIdentifier"]),
-                categoryIDs: uniqueOrdered(tagIDs),
-                localizedNote: nil,
-                notes: nil,
-                sourceEvidence: splitPipe(values["sourceEvidence"] ?? "")
-            )
-        }
-    }
-
-    private static func localizedNote(from notes: [String: String]?, preferredCode: String = L10n.currentCode) -> String? {
-        guard let notes, !notes.isEmpty else { return nil }
-        let preferredCodes = [
-            preferredCode,
-            "en",
-            "zh-Hans",
-            "zh-Hant"
-        ]
-
-        for code in preferredCodes {
-            if let note = normalizedNote(notes[code]) {
-                return note
+            if nameIndex[entry.normalizedName].map({ $0.rank <= entry.rank }) != true {
+                nameIndex[entry.normalizedName] = entry
             }
         }
 
-        return notes.values
-            .compactMap(normalizedNote)
-            .first
+        return SmartStartCatalogSnapshot(
+            entries: entries,
+            bundleIndex: bundleIndex,
+            nameIndex: nameIndex,
+            entryIndex: entryIndex
+        )
+    }
+
+    private static func loadBaseSnapshot() -> SmartStartBaseSnapshot? {
+        catalogCacheLock.lock()
+        if let snapshot = cachedBaseSnapshot {
+            catalogCacheLock.unlock()
+            return snapshot
+        }
+        catalogCacheLock.unlock()
+
+        guard let url = Bundle.main.url(
+            forResource: "SmartStartUltimateDefaultCatalog.base",
+            withExtension: "json"
+        ),
+              let data = try? Data(contentsOf: url),
+              let catalog = try? JSONDecoder().decode(SmartStartBaseCatalog.self, from: data),
+              catalog.resourceFormatVersion == 1
+        else { return nil }
+
+        var bundleIndex: [String: SmartStartBaseCatalogEntry] = [:]
+        var nameIndex: [String: SmartStartBaseCatalogEntry] = [:]
+        var entryIndex: [String: SmartStartBaseCatalogEntry] = [:]
+        for entry in catalog.entries {
+            entryIndex[entry.entryID] = entry
+            if let bundleIdentifier = normalizedBundleIdentifier(entry.bundleIdentifier)?.lowercased(),
+               !bundleIdentifier.isEmpty,
+               bundleIndex[bundleIdentifier].map({ ($0.rank ?? Int.max) <= (entry.rank ?? Int.max) }) != true {
+                bundleIndex[bundleIdentifier] = entry
+            }
+            let name = entry.normalizedName.flatMap { $0.isEmpty ? nil : $0 } ?? normalizedName(entry.name)
+            if nameIndex[name].map({ ($0.rank ?? Int.max) <= (entry.rank ?? Int.max) }) != true {
+                nameIndex[name] = entry
+            }
+        }
+
+        let snapshot = SmartStartBaseSnapshot(
+            catalogContentVersion: catalog.catalogContentVersion,
+            supportedLanguages: catalog.supportedLanguages,
+            fallbackLanguages: catalog.fallbackLanguages,
+            entries: catalog.entries,
+            bundleIndex: bundleIndex,
+            nameIndex: nameIndex,
+            entryIndex: entryIndex
+        )
+
+        catalogCacheLock.lock()
+        if let cached = cachedBaseSnapshot {
+            catalogCacheLock.unlock()
+            return cached
+        }
+        cachedBaseSnapshot = snapshot
+        catalogCacheLock.unlock()
+        return snapshot
+    }
+
+    private static func loadLocalizedNotes(for languageCodes: [String]) -> [String: SmartStartLocalizedNote] {
+        var result: [String: SmartStartLocalizedNote] = [:]
+        for languageCode in languageCodes {
+            guard let notes = loadNotesSnapshot(languageCode: languageCode) else { continue }
+            for (entryID, note) in notes.notes where result[entryID] == nil {
+                let fingerprint = TagDatabase.noteFingerprint(note)
+                result[entryID] = SmartStartLocalizedNote(
+                    note: note,
+                    languageCode: notes.languageCode,
+                    provenance: SmartDefaultNoteProvenance(
+                        entryID: entryID,
+                        languageCode: notes.languageCode,
+                        notesVersion: notes.notesVersion,
+                        noteFingerprint: fingerprint
+                    )
+                )
+            }
+        }
+        return result
+    }
+
+    private static func loadNotesSnapshot(languageCode: String) -> SmartStartNotesSnapshot? {
+        catalogCacheLock.lock()
+        if let snapshot = cachedNotesSnapshots[languageCode] {
+            catalogCacheLock.unlock()
+            return snapshot
+        }
+        catalogCacheLock.unlock()
+
+        guard let data = loadNotesCatalogData(languageCode: languageCode),
+              let catalog = try? JSONDecoder().decode(SmartStartNotesCatalog.self, from: data),
+              catalog.resourceFormatVersion == 1
+        else { return nil }
+
+        let notes = Dictionary(uniqueKeysWithValues: catalog.entries.compactMap { entry in
+            normalizedNote(entry.note).map { (entry.entryID, $0) }
+        })
+        let snapshot = SmartStartNotesSnapshot(
+            languageCode: catalog.language,
+            notesVersion: catalog.notesVersion,
+            notes: notes
+        )
+
+        catalogCacheLock.lock()
+        if let cached = cachedNotesSnapshots[languageCode] {
+            catalogCacheLock.unlock()
+            return cached
+        }
+        cachedNotesSnapshots[languageCode] = snapshot
+        catalogCacheLock.unlock()
+        return snapshot
+    }
+
+    private static func loadNotesCatalogData(languageCode: String) -> Data? {
+        let resourceName = "SmartStartUltimateDefaultCatalog.notes.\(languageCode)"
+
+        if let url = Bundle.main.url(forResource: resourceName, withExtension: "json.deflate"),
+           let compressedData = try? Data(contentsOf: url),
+           let data = inflatedDeflateData(from: compressedData) {
+            return data
+        }
+
+        guard let url = Bundle.main.url(forResource: resourceName, withExtension: "json") else {
+            return nil
+        }
+        return try? Data(contentsOf: url)
+    }
+
+    private static func inflatedDeflateData(from compressedData: Data) -> Data? {
+        guard !compressedData.isEmpty else { return Data() }
+
+        let maxOutputSize = 16 * 1024 * 1024
+        var outputSize = max(compressedData.count * 8, 64 * 1024)
+
+        while outputSize <= maxOutputSize {
+            let decoded = compressedData.withUnsafeBytes { sourceBuffer -> Data? in
+                guard let sourcePointer = sourceBuffer.bindMemory(to: UInt8.self).baseAddress else {
+                    return nil
+                }
+
+                let destinationPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: outputSize)
+                defer { destinationPointer.deallocate() }
+
+                let decodedCount = compression_decode_buffer(
+                    destinationPointer,
+                    outputSize,
+                    sourcePointer,
+                    compressedData.count,
+                    nil,
+                    COMPRESSION_ZLIB
+                )
+
+                guard decodedCount > 0 else { return nil }
+                return Data(bytes: destinationPointer, count: decodedCount)
+            }
+
+            if let decoded {
+                return decoded
+            }
+            outputSize *= 2
+        }
+
+        return nil
+    }
+
+    private static func languageFallbacks(
+        preferredCode: String,
+        base: SmartStartBaseSnapshot
+    ) -> [String] {
+        var codes: [String] = []
+        func append(_ code: String) {
+            guard !code.isEmpty,
+                  base.supportedLanguages.contains(code),
+                  !codes.contains(code)
+            else { return }
+            codes.append(code)
+        }
+
+        append(preferredCode)
+        switch preferredCode {
+        case "ar-Najdi":
+            append("ar")
+        case "nn":
+            append("nb")
+            append("no")
+        case "no":
+            append("nb")
+            append("nn")
+        case "nb":
+            append("no")
+            append("nn")
+        default:
+            break
+        }
+        for code in base.fallbackLanguages {
+            append(code)
+        }
+        append("en")
+        append("zh-Hans")
+        append("zh-Hant")
+        return codes
     }
 
     private static func normalizedNote(_ value: String?) -> String? {

--
Gitblit v1.9.3