| | |
| | | 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") |
| | |
| | | func applicationDidFinishLaunching(_ notification: Notification) { |
| | | AppDefaults.register() |
| | | L10n.setup() |
| | | ProEntitlementCenter.shared.start() |
| | | migrateDefaultGroupName() |
| | | TagDatabase.seedDefaultTags() |
| | | _ = TagDatabase.relocalizeSystemTagsForCurrentLanguage() |
| | | syncChromeSettings(force: true) |
| | | observeHotkeyStatusChanges() |
| | | registerConfiguredHotkeys() |
| | |
| | | versionItem.isEnabled = false |
| | | menu.addItem(versionItem) |
| | | |
| | | let proStatusItem = makeProStatusMenuItem() |
| | | menu.addItem(proStatusItem) |
| | | |
| | | menu.addItem(.separator()) |
| | | let prefsItem = NSMenuItem( |
| | | title: tr("menu.preferences"), |
| | |
| | | } |
| | | |
| | | func menuWillOpen(_ menu: NSMenu) { |
| | | configureProStatusMenuItem(in: menu) |
| | | statusMenuScreenForNextOverlay = overlayController.screenContainingCurrentPointer() |
| | | ?? statusItem?.button?.window?.screen |
| | | ?? NSScreen.main |
| | |
| | | |
| | | 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 |
| | | } |
| | | |
| | |
| | | openPreferences(targetTab: nil) |
| | | } |
| | | |
| | | @objc private func openProStatusFromStatusMenu(_ sender: NSMenuItem) { |
| | | openPreferences(targetTab: SettingsTabTarget.about) |
| | | } |
| | | |
| | | private func openPreferences(targetTab: String?) { |
| | | dismissQuickSearchIfNeeded() |
| | | TagDatabase.flushPendingCategorySchemeBackupBatch() |