Ariver
2026-06-27 28be00ea53666fd5500a702a3c187c0e27dd90ad
src/Apptag/ApptagApp.swift
@@ -34,6 +34,7 @@
    private static let statusItemButtonIdentifier = NSUserInterfaceItemIdentifier("TagLauncherStatusItemButton")
    private static let statusItemAccessibilityLabel = AppIdentity.displayName
    private static let showAppListMenuItemIdentifier = NSUserInterfaceItemIdentifier("TagLauncherShowAppListMenuItem")
    private static let proStatusMenuItemIdentifier = NSUserInterfaceItemIdentifier("TagLauncherProStatusMenuItem")
    private static let helpMenuItemIdentifier = NSUserInterfaceItemIdentifier("TagLauncherHelpMenu")
    private static let downloadHelpMenuItemIdentifier = NSUserInterfaceItemIdentifier("TagLauncherDownloadHelpMenuItem")
    private static let externalActivationNotification = Notification.Name("TagLauncherExternalActivationRequested")
@@ -193,6 +194,7 @@
    func applicationDidFinishLaunching(_ notification: Notification) {
        AppDefaults.register()
        L10n.setup()
        ProEntitlementCenter.shared.start()
        migrateDefaultGroupName()
        TagDatabase.seedDefaultTags()
        _ = TagDatabase.relocalizeSystemTagsForCurrentLanguage()
@@ -660,6 +662,9 @@
        versionItem.isEnabled = false
        menu.addItem(versionItem)
        let proStatusItem = makeProStatusMenuItem()
        menu.addItem(proStatusItem)
        menu.addItem(.separator())
        let prefsItem = NSMenuItem(
            title: tr("menu.preferences"),
@@ -696,6 +701,7 @@
    }
    func menuWillOpen(_ menu: NSMenu) {
        configureProStatusMenuItem(in: menu)
        statusMenuScreenForNextOverlay = overlayController.screenContainingCurrentPointer()
            ?? statusItem?.button?.window?.screen
            ?? NSScreen.main
@@ -765,6 +771,53 @@
        image.isTemplate = true
        image.accessibilityDescription = "TagLauncher"
        return image
    }
    private func makeProStatusMenuItem() -> NSMenuItem {
        let item = NSMenuItem(
            title: "",
            action: #selector(openProStatusFromStatusMenu(_:)),
            keyEquivalent: ""
        )
        item.identifier = Self.proStatusMenuItemIdentifier
        item.target = self
        configureProStatusMenuItem(item)
        return item
    }
    private func configureProStatusMenuItem(in menu: NSMenu) {
        guard let item = menu.items.first(where: { $0.identifier == Self.proStatusMenuItemIdentifier }) else {
            return
        }
        configureProStatusMenuItem(item)
    }
    private func configureProStatusMenuItem(_ item: NSMenuItem) {
        let isUnlocked = ProEntitlementPolicy.accessState().isUnlocked
        item.title = tr(isUnlocked ? "menu.proStatus.unlocked" : "menu.proStatus.free")
        item.action = #selector(openProStatusFromStatusMenu(_:))
        item.target = self
        item.isEnabled = true
        item.image = isUnlocked ? makeProStatusMenuIcon() : nil
    }
    private func makeProStatusMenuIcon() -> NSImage? {
        guard let symbol = NSImage(systemSymbolName: "crown.fill", accessibilityDescription: "Pro") else {
            return nil
        }
        let configuration = NSImage.SymbolConfiguration(pointSize: 13, weight: .semibold)
        let configuredSymbol = symbol.withSymbolConfiguration(configuration) ?? symbol
        let image = NSImage(size: NSSize(width: 16, height: 16))
        image.lockFocus()
        NSColor(red: 0.96, green: 0.63, blue: 0.10, alpha: 1.0).set()
        let iconRect = NSRect(x: 1.5, y: 1.5, width: 13, height: 13)
        configuredSymbol.draw(in: iconRect, from: .zero, operation: .sourceOver, fraction: 1.0)
        NSColor(red: 0.96, green: 0.63, blue: 0.10, alpha: 1.0).set()
        iconRect.fill(using: .sourceAtop)
        image.unlockFocus()
        image.isTemplate = false
        image.accessibilityDescription = "Pro"
        return image
    }
@@ -1699,6 +1752,10 @@
        openPreferences(targetTab: nil)
    }
    @objc private func openProStatusFromStatusMenu(_ sender: NSMenuItem) {
        openPreferences(targetTab: SettingsTabTarget.about)
    }
    private func openPreferences(targetTab: String?) {
        dismissQuickSearchIfNeeded()
        TagDatabase.flushPendingCategorySchemeBackupBatch()