Full Code of p0deje/Maccy for AI

master 4cd1f979bdf5 cached
502 files
31.3 MB
243.7k tokens
1 requests
Download .txt
Showing preview only (848K chars total). Download the full file or copy to clipboard to get everything.
Repository: p0deje/Maccy
Branch: master
Commit: 4cd1f979bdf5
Files: 502
Total size: 31.3 MB

Directory structure:
gitextract_l43svsy0/

├── .bartycrouch.toml
├── .github/
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       ├── bug_report.yml
│       ├── config.yml
│       └── feature_request.yml
├── .gitignore
├── .periphery.yml
├── .swiftlint.yml
├── Designs/
│   ├── App-Store/
│   │   ├── 01-Main.pxd
│   │   ├── 02-Types.pxd
│   │   ├── 03-Search.pxd
│   │   ├── 04-Pin.pxd
│   │   ├── 05-Shortcuts.pxd
│   │   ├── 06-Languages.pxd
│   │   └── Promo/
│   │       └── Maccy_1527619437_20240124_MacAppStore_SupportingImagery.psd
│   ├── Copies.txt
│   ├── Icons.sketch
│   ├── Instructions.pxd/
│   │   ├── QuickLook/
│   │   │   ├── Icon.tiff
│   │   │   └── Thumbnail.tiff
│   │   ├── data/
│   │   │   ├── CAE20F62-9DFC-4BD2-AE79-BE620A2ADE55
│   │   │   ├── DF48A8C2-D105-49EF-BF24-87B87BAECAC7-OriginalContentSource
│   │   │   └── selectionForContentTransform/
│   │   │       ├── meta
│   │   │       └── shapeSelection/
│   │   │           ├── meta
│   │   │           └── path
│   │   └── metadata.info
│   └── Storage-Types.pxd/
│       ├── QuickLook/
│       │   ├── Icon.tiff
│       │   └── Thumbnail.tiff
│       ├── data/
│       │   ├── 460814B1-E0F9-4E2C-B4CA-32C0CD866260-OriginalContentSource
│       │   ├── A2CD8EA6-822D-4757-B972-8653B2AABD6B
│       │   ├── selection/
│       │   │   ├── meta
│       │   │   └── shapeSelection/
│       │   │       ├── meta
│       │   │       └── path
│       │   └── selectionForContentTransform/
│       │       ├── meta
│       │       └── shapeSelection/
│       │           ├── meta
│       │           └── path
│       └── metadata.info
├── LICENSE
├── Maccy/
│   ├── About.swift
│   ├── Accessibility.swift
│   ├── AppDelegate.swift
│   ├── AppStoreReview.swift
│   ├── ApplicationImage.swift
│   ├── ApplicationImageCache.swift
│   ├── Assets.xcassets/
│   │   ├── AppIcon.appiconset/
│   │   │   └── Contents.json
│   │   ├── Contents.json
│   │   ├── StatusBarMenuImage.imageset/
│   │   │   └── Contents.json
│   │   ├── clipboard.fill.imageset/
│   │   │   └── Contents.json
│   │   ├── paperclip.imageset/
│   │   │   └── Contents.json
│   │   └── scissors.imageset/
│   │       └── Contents.json
│   ├── Clipboard.swift
│   ├── ColorImage.swift
│   ├── Extensions/
│   │   ├── Collection+Surrounding.swift
│   │   ├── Color+Random.swift
│   │   ├── Defaults.Keys+Names.swift
│   │   ├── Dictionary+RemoveItem.swift
│   │   ├── KeyEquivalent+Keys.swift
│   │   ├── KeyboardShortcuts.Name+Shortcuts.swift
│   │   ├── ModifierFlags+Description.swift
│   │   ├── NSApplication+Windows.swift
│   │   ├── NSImage+Names.swift
│   │   ├── NSImage+Resized.swift
│   │   ├── NSPasteboard.PasteboardType+Types.swift
│   │   ├── NSPoint+DefaultsSerializable.swift
│   │   ├── NSRect+Centered.swift
│   │   ├── NSRunningApplication+WindowFrame.swift
│   │   ├── NSScreen+ForPopup.swift
│   │   ├── NSSize+DefaultsSerializable.swift
│   │   ├── NSSound+Named.swift
│   │   ├── NSWorkspace+ApplicationName.swift
│   │   ├── Sauce+KeyboardShortcuts.swift
│   │   ├── Settings.PaneIdentifier+Panes.swift
│   │   ├── String+Identifiable.swift
│   │   └── String+Shortened.swift
│   ├── FloatingPanel.swift
│   ├── GlobalHotKey.swift
│   ├── HighlightMatch.swift
│   ├── History.xcdatamodeld/
│   │   └── History.xcdatamodel/
│   │       └── contents
│   ├── HistoryItemAction.swift
│   ├── Info.plist
│   ├── Intents/
│   │   ├── AppIntentError.swift
│   │   ├── Clear.swift
│   │   ├── Delete.swift
│   │   ├── Get.swift
│   │   ├── HistoryItemAppEntity.swift
│   │   └── Select.swift
│   ├── ItemsProtocol.swift
│   ├── KeyChord.swift
│   ├── KeyShortcut.swift
│   ├── KeyboardLayout.swift
│   ├── Maccy.entitlements
│   ├── MaccyApp.swift
│   ├── MenuIcon.swift
│   ├── Models/
│   │   ├── HistoryItem.swift
│   │   └── HistoryItemContent.swift
│   ├── Notifier.swift
│   ├── Observables/
│   │   ├── AppState.swift
│   │   ├── Footer.swift
│   │   ├── FooterItem.swift
│   │   ├── History.swift
│   │   ├── HistoryItemDecorator.swift
│   │   ├── ModifierFlags.swift
│   │   ├── NavigationManager.swift
│   │   ├── Popup.swift
│   │   └── SlideoutController.swift
│   ├── PasteStack.swift
│   ├── PinsPosition.swift
│   ├── PopupPosition.swift
│   ├── Search.swift
│   ├── SearchVisibility.swift
│   ├── Selection.swift
│   ├── Settings/
│   │   ├── AdvancedSettingsPane.swift
│   │   ├── AppearanceSettingsPane.swift
│   │   ├── GeneralSettingsPane.swift
│   │   ├── IgnoreSettingsPane/
│   │   │   ├── IgnoreApplicationsSettingsView.swift
│   │   │   ├── IgnorePasteboardTypesSettingsView.swift
│   │   │   └── IgnoreRegexpsSettingsView.swift
│   │   ├── IgnoreSettingsPane.swift
│   │   ├── PinsSettingsPane.swift
│   │   ├── StorageSettingsPane.swift
│   │   ├── ar.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── be.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── bn.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── bs.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ca.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ckb.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── cs.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── de.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── el.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── en.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── eo.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── es.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── fa.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── fr.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── he.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── hi.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── hr.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── hu.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── id.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── it.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ja.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ko.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── lt.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── lv.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── nb.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── nl.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── pl.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── pt-BR.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── pt.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ro.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ru.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── sl.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── sv.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ta.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── th.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── tr.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── uk.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── uz.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── vi.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── zh-Hans.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   └── zh-Hant.lproj/
│   │       ├── AdvancedSettings.strings
│   │       ├── AppearanceSettings.strings
│   │       ├── GeneralSettings.strings
│   │       ├── IgnoreSettings.strings
│   │       ├── PinsSettings.strings
│   │       └── StorageSettings.strings
│   ├── SoftwareUpdater.swift
│   ├── Sorter.swift
│   ├── Sounds/
│   │   ├── Knock.caf
│   │   └── Write.caf
│   ├── Storage.swift
│   ├── Storage.xcdatamodeld/
│   │   └── Storage.xcdatamodel/
│   │       └── contents
│   ├── Throttler.swift
│   ├── Views/
│   │   ├── AppImageView.swift
│   │   ├── AsyncView.swift
│   │   ├── ConfirmationView.swift
│   │   ├── ContentView.swift
│   │   ├── FooterItemView.swift
│   │   ├── FooterView.swift
│   │   ├── HeaderView.swift
│   │   ├── HeightReaderModifier.swift
│   │   ├── HistoryItemView.swift
│   │   ├── HistoryListView.swift
│   │   ├── HoverSelectionModifier.swift
│   │   ├── KeyHandlingView.swift
│   │   ├── KeyboardShortcutView.swift
│   │   ├── ListHeaderView.swift
│   │   ├── ListItemTitleView.swift
│   │   ├── ListItemView.swift
│   │   ├── MouseMovedViewModifer.swift
│   │   ├── MultipleSelectionListView.swift
│   │   ├── PasteStackItemView.swift
│   │   ├── PasteStackPreviewView.swift
│   │   ├── PasteStackView.swift
│   │   ├── PinsView.swift
│   │   ├── PreviewItemView.swift
│   │   ├── SearchFieldView.swift
│   │   ├── SlideoutContentView.swift
│   │   ├── SlideoutView.swift
│   │   ├── ToolbarView.swift
│   │   ├── VisualEffectView.swift
│   │   ├── WrappingTextView.swift
│   │   ├── ar.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── be.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── bn.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── bs.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ca.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ckb.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── cs.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── de.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── el.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── en.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── eo.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── es.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── fa.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── fr.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── he.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── hi.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── hr.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── hu.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── id.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── it.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ja.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ko.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── lt.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── lv.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── nb.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── nl.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── pl.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── pt-BR.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── pt.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ro.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ru.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── sl.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── sv.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ta.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── th.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── tr.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── uk.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── uz.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── vi.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── zh-Hans.lproj/
│   │   │   └── PreviewItemView.strings
│   │   └── zh-Hant.lproj/
│   │       └── PreviewItemView.strings
│   ├── ar.lproj/
│   │   └── Localizable.strings
│   ├── be.lproj/
│   │   └── Localizable.strings
│   ├── bn.lproj/
│   │   └── Localizable.strings
│   ├── bs.lproj/
│   │   └── Localizable.strings
│   ├── ca.lproj/
│   │   └── Localizable.strings
│   ├── ckb.lproj/
│   │   └── Localizable.strings
│   ├── cs.lproj/
│   │   ├── Localizable.strings
│   │   └── Preview.strings
│   ├── de.lproj/
│   │   └── Localizable.strings
│   ├── el.lproj/
│   │   └── Localizable.strings
│   ├── en.lproj/
│   │   └── Localizable.strings
│   ├── eo.lproj/
│   │   └── Localizable.strings
│   ├── es.lproj/
│   │   └── Localizable.strings
│   ├── fa.lproj/
│   │   └── Localizable.strings
│   ├── fr.lproj/
│   │   └── Localizable.strings
│   ├── he.lproj/
│   │   └── Localizable.strings
│   ├── hi.lproj/
│   │   └── Localizable.strings
│   ├── hr.lproj/
│   │   └── Localizable.strings
│   ├── hu.lproj/
│   │   └── Localizable.strings
│   ├── id.lproj/
│   │   └── Localizable.strings
│   ├── it.lproj/
│   │   └── Localizable.strings
│   ├── ja.lproj/
│   │   └── Localizable.strings
│   ├── ko.lproj/
│   │   └── Localizable.strings
│   ├── lt.lproj/
│   │   └── Localizable.strings
│   ├── lv.lproj/
│   │   └── Localizable.strings
│   ├── nb.lproj/
│   │   └── Localizable.strings
│   ├── nl.lproj/
│   │   └── Localizable.strings
│   ├── pl.lproj/
│   │   └── Localizable.strings
│   ├── pt-BR.lproj/
│   │   ├── Localizable.strings
│   │   └── Preview.strings
│   ├── pt.lproj/
│   │   └── Localizable.strings
│   ├── ro.lproj/
│   │   └── Localizable.strings
│   ├── ru.lproj/
│   │   └── Localizable.strings
│   ├── sl.lproj/
│   │   └── Localizable.strings
│   ├── sv.lproj/
│   │   └── Localizable.strings
│   ├── ta.lproj/
│   │   └── Localizable.strings
│   ├── th.lproj/
│   │   └── Localizable.strings
│   ├── tr.lproj/
│   │   └── Localizable.strings
│   ├── uk.lproj/
│   │   └── Localizable.strings
│   ├── uz.lproj/
│   │   └── Localizable.strings
│   ├── vi.lproj/
│   │   └── Localizable.strings
│   ├── zh-Hans.lproj/
│   │   └── Localizable.strings
│   └── zh-Hant.lproj/
│       └── Localizable.strings
├── Maccy.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   └── contents.xcworkspacedata
│   └── xcshareddata/
│       └── xcschemes/
│           └── Maccy.xcscheme
├── Maccy.xctestplan
├── MaccyTests/
│   ├── ClipboardTests.swift
│   ├── ColorImageTests.swift
│   ├── HistoryDecoratorTests.swift
│   ├── HistoryItemTests.swift
│   ├── HistoryTests.swift
│   ├── Info.plist
│   ├── SearchTests.swift
│   └── SorterTests.swift
├── MaccyUITests/
│   ├── Info.plist
│   └── MaccyUITests.swift
├── README.md
├── appcast.xml
└── docs/
    └── keyboard-shortcut-password-fields.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .bartycrouch.toml
================================================
[update]
tasks = ["interfaces", "translate", "normalize"]

[update.interfaces]
paths = ["Maccy"]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
defaultToBase = false
ignoreEmptyStrings = true
unstripped = false
ignoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"]

[update.translate]
paths = ["Maccy"]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
translator = "deepL"
secret = "<replace>"
sourceLocale = "en"
separateWithEmptyLine = false

[update.normalize]
paths = ["Maccy"]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
separateWithEmptyLine = false
sortByKeys = false

[lint]
paths = ["Maccy"]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
duplicateKeys = true
emptyValues = true


================================================
FILE: .github/FUNDING.yml
================================================
buy_me_a_coffee: p0deje


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
---
name: 🐛 Bug Report
description: Submit a Bug Report
labels: [bug]
body:
  - type: markdown
    attributes:
      value: |
        Thank you for taking the time to complete this bug report!
        This will help to find the cause of the issue faster and requires fewer follow-ups.
  - type: checkboxes
    attributes:
      label: Before Submitting Your Bug Report
      options:
        - label: I have verified that there isn't already an issue reporting the same bug to prevent duplication.
          required: false
        - label: I have seen the [FAQ](https://github.com/p0deje/Maccy?tab=readme-ov-file#faq).
          required: false
  - type: input
    attributes:
      label: Maccy Version (see 'About' window)
      placeholder: e.g. 0.29.0
    validations:
      required: false
  - type: input
    attributes:
      label: macOS Version
      placeholder: e.g. 13.5.2
    validations:
      required: false
  - type: textarea
    attributes:
      label: Maccy Settings
      description: Provide the output from running 'defaults read org.p0deje.Maccy' in Terminal.app.
      render: Shell
    validations:
      required: false
  - type: textarea
    attributes:
      label: Description
      description: Please provide a clear and concise description of the bug.
      placeholder: Short description
    validations:
      required: false
  - type: textarea
    attributes:
      label: Steps to Reproduce
      description: |
        Provide the steps to consistently reproduce the issue. If possible, record a screen video
        demonstrating the problem using QuickTime.app.
      placeholder: |
        1. Navigate to …
        2. Click on …
        3. Scroll down to …
        4. Observe …
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
---
name: 💪 Feature request
description: Suggest an idea for this project
labels: [enhancement]
body:
  - type: checkboxes
    attributes:
      label: Before Submitting Your Feature Request
      options:
        - label: Check that there isn't already a similar feature request to avoid creating a duplicate.
          required: false
        - label: I have seen the [FAQ](https://github.com/p0deje/Maccy?tab=readme-ov-file#faq).
          required: false
  - type: textarea
    attributes:
      label: Problem
      description:
        Please add a clear and concise description of the problem you are
        seeking to solve with this feature request.
      placeholder: |
        Description
  - type: textarea
    attributes:
      label: Solution
      description: Please describe what you might want to happen to address this issue. If applicable, add a screenshot, gif, or video to better convey your idea.
      placeholder: |
        Short description
    validations:
      required: false


================================================
FILE: .gitignore
================================================
xcuserdata/
Maccy.xcodeproj/project.xcworkspace/xcshareddata
.idea
.DS_Store
Maccy/.DS_Store


================================================
FILE: .periphery.yml
================================================
project: Maccy.xcodeproj
retain_objc_accessible: true
schemes:
- Maccy
targets:
- Maccy


================================================
FILE: .swiftlint.yml
================================================
disabled_rules:
  - multiple_closures_with_trailing_closure
  - non_optional_string_data_conversion
  - todo
line_length:
  ignores_comments: true


================================================
FILE: Designs/App-Store/Promo/Maccy_1527619437_20240124_MacAppStore_SupportingImagery.psd
================================================
[File too large to display: 30.6 MB]

================================================
FILE: Designs/Copies.txt
================================================
Hello! 👋
This is Maccy.
Clipboard manager for Mac. 💻
Search as you type. 🔍
Open source. ⚙️
No fluff! 😛


================================================
FILE: Designs/Instructions.pxd/data/selectionForContentTransform/meta
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>backingScale</key>
	<real>1</real>
	<key>mode</key>
	<integer>0</integer>
	<key>shapeSelectionFilename</key>
	<string>shapeSelection</string>
	<key>size</key>
	<data>
	NC10UHpTVFAQAAAAQKQAAAAAAABAmQAAAAAAAA==
	</data>
	<key>softness</key>
	<real>0.0</real>
	<key>timestamp</key>
	<real>682897674.67681396</real>
	<key>transform</key>
	<array>
		<real>1.2718749999999999</real>
		<real>0.0</real>
		<real>0.0</real>
		<real>1.2718750000000003</real>
		<real>303.99999999999943</real>
		<real>-115.00000000000023</real>
		<real>0.0</real>
		<real>0.0</real>
	</array>
	<key>version</key>
	<integer>2</integer>
</dict>
</plist>


================================================
FILE: Designs/Instructions.pxd/data/selectionForContentTransform/shapeSelection/meta
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>backingScale</key>
	<real>1</real>
	<key>pathFilename</key>
	<string>path</string>
	<key>version</key>
	<integer>1</integer>
</dict>
</plist>


================================================
FILE: Designs/Storage-Types.pxd/data/selection/meta
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>backingScale</key>
	<real>1</real>
	<key>mode</key>
	<integer>0</integer>
	<key>shapeSelectionFilename</key>
	<string>shapeSelection</string>
	<key>size</key>
	<data>
	NC10UHpTVFAQAAAAQKQAAAAAAABAmQAAAAAAAA==
	</data>
	<key>softness</key>
	<real>0.0</real>
	<key>timestamp</key>
	<real>682898643.54011703</real>
	<key>transform</key>
	<array>
		<real>1</real>
		<real>0.0</real>
		<real>0.0</real>
		<real>1</real>
		<real>0.0</real>
		<real>0.0</real>
		<real>0.0</real>
		<real>0.0</real>
	</array>
	<key>version</key>
	<integer>2</integer>
</dict>
</plist>


================================================
FILE: Designs/Storage-Types.pxd/data/selection/shapeSelection/meta
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>backingScale</key>
	<real>1</real>
	<key>pathFilename</key>
	<string>path</string>
	<key>version</key>
	<integer>1</integer>
</dict>
</plist>


================================================
FILE: Designs/Storage-Types.pxd/data/selectionForContentTransform/meta
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>backingScale</key>
	<real>1</real>
	<key>mode</key>
	<integer>0</integer>
	<key>shapeSelectionFilename</key>
	<string>shapeSelection</string>
	<key>size</key>
	<data>
	NC10UHpTVFAQAAAAQKQAAAAAAABAmQAAAAAAAA==
	</data>
	<key>softness</key>
	<real>0.0</real>
	<key>timestamp</key>
	<real>682898669.47036195</real>
	<key>transform</key>
	<array>
		<real>1</real>
		<real>0.0</real>
		<real>0.0</real>
		<real>1</real>
		<real>0.0</real>
		<real>0.0</real>
		<real>0.0</real>
		<real>0.0</real>
	</array>
	<key>version</key>
	<integer>2</integer>
</dict>
</plist>


================================================
FILE: Designs/Storage-Types.pxd/data/selectionForContentTransform/shapeSelection/meta
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>backingScale</key>
	<real>1</real>
	<key>pathFilename</key>
	<string>path</string>
	<key>version</key>
	<integer>1</integer>
</dict>
</plist>


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2025 Alex Rodionov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: Maccy/About.swift
================================================
import Cocoa

class About {
  private let familyCredits = NSAttributedString(
    string: "Special thank you to Tonia, Anna & Guy! ❤️",
    attributes: [NSAttributedString.Key.foregroundColor: NSColor.labelColor]
  )

  private var kossCredits: NSMutableAttributedString {
    let string = NSMutableAttributedString(string: "Kudos to Sasha Koss for help! 🏂",
                                           attributes: [NSAttributedString.Key.foregroundColor: NSColor.labelColor])
    string.addAttribute(.link, value: "https://koss.nocorp.me", range: NSRange(location: 9, length: 10))
    return string
  }

  private var links: NSMutableAttributedString {
    let string = NSMutableAttributedString(string: "Website│GitHub│Support",
                                           attributes: [NSAttributedString.Key.foregroundColor: NSColor.labelColor])
    string.addAttribute(.link, value: "https://maccy.app", range: NSRange(location: 0, length: 7))
    string.addAttribute(.link, value: "https://github.com/p0deje/Maccy", range: NSRange(location: 8, length: 6))
    string.addAttribute(.link, value: "mailto:support@maccy.app", range: NSRange(location: 15, length: 7))
    return string
  }

  private var credits: NSMutableAttributedString {
    let credits = NSMutableAttributedString(string: "",
                                            attributes: [NSAttributedString.Key.foregroundColor: NSColor.labelColor])
    credits.append(links)
    credits.append(NSAttributedString(string: "\n\n"))
    credits.append(kossCredits)
    credits.append(NSAttributedString(string: "\n"))
    credits.append(familyCredits)
    credits.setAlignment(.center, range: NSRange(location: 0, length: credits.length))
    return credits
  }

  @objc
  func openAbout(_ sender: NSMenuItem?) {
    NSApp.activate(ignoringOtherApps: true)
    NSApp.orderFrontStandardAboutPanel(options: [NSApplication.AboutPanelOptionKey.credits: credits])
  }
}


================================================
FILE: Maccy/Accessibility.swift
================================================
import AppKit

struct Accessibility {
  private static var allowed: Bool { AXIsProcessTrustedWithOptions(nil) }

  static func check() {
    guard !allowed else {
      return
    }
  }
}


================================================
FILE: Maccy/AppDelegate.swift
================================================
import Defaults
import KeyboardShortcuts
import Sparkle
import SwiftUI

class AppDelegate: NSObject, NSApplicationDelegate {
  var panel: FloatingPanel<ContentView>!

  @objc
  private lazy var statusItem: NSStatusItem = {
    let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
    statusItem.behavior = .removalAllowed
    statusItem.button?.action = #selector(performStatusItemClick)
    statusItem.button?.image = Defaults[.menuIcon].image
    statusItem.button?.imagePosition = .imageLeft
    statusItem.button?.target = self
    return statusItem
  }()

  private var isStatusItemDisabled: Bool {
    Defaults[.ignoreEvents] || Defaults[.enabledPasteboardTypes].isEmpty
  }

  private var statusItemVisibilityObserver: NSKeyValueObservation?

  func applicationWillFinishLaunching(_ notification: Notification) { // swiftlint:disable:this function_body_length
    #if DEBUG
    if CommandLine.arguments.contains("enable-testing") {
      SPUUpdater(hostBundle: Bundle.main,
                 applicationBundle: Bundle.main,
                 userDriver: SPUStandardUserDriver(hostBundle: Bundle.main, delegate: nil),
                 delegate: nil)
      .automaticallyChecksForUpdates = false
    }
    #endif

    // Bridge FloatingPanel via AppDelegate.
    AppState.shared.appDelegate = self

    Clipboard.shared.onNewCopy { History.shared.add($0) }
    Clipboard.shared.start()

    Task {
      for await _ in Defaults.updates(.clipboardCheckInterval, initial: false) {
        Clipboard.shared.restart()
      }
    }

    statusItemVisibilityObserver = observe(\.statusItem.isVisible, options: .new) { _, change in
      if let newValue = change.newValue, Defaults[.showInStatusBar] != newValue {
        Defaults[.showInStatusBar] = newValue
      }
    }

    Task {
      for await value in Defaults.updates(.showInStatusBar) {
        statusItem.isVisible = value
      }
    }

    Task {
      for await value in Defaults.updates(.menuIcon, initial: false) {
        statusItem.button?.image = value.image
      }
    }

    synchronizeMenuIconText()
    Task {
      for await value in Defaults.updates(.showRecentCopyInMenuBar) {
        if value {
          statusItem.button?.title = AppState.shared.menuIconText
        } else {
          statusItem.button?.title = ""
        }
      }
    }

    Task {
      for await _ in Defaults.updates(.ignoreEvents) {
        statusItem.button?.appearsDisabled = isStatusItemDisabled
      }
    }

    Task {
      for await _ in Defaults.updates(.enabledPasteboardTypes) {
        statusItem.button?.appearsDisabled = isStatusItemDisabled
      }
    }
  }

  func applicationDidFinishLaunching(_ aNotification: Notification) {
    migrateUserDefaults()
    disableUnusedGlobalHotkeys()

    panel = FloatingPanel(
      contentRect: NSRect(origin: .zero, size: Defaults[.windowSize]),
      identifier: Bundle.main.bundleIdentifier ?? "org.p0deje.Maccy",
      statusBarButton: statusItem.button,
      onClose: { AppState.shared.popup.reset() }
    ) {
      ContentView()
    }
  }

  func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
    panel.toggle(height: AppState.shared.popup.height)
    return true
  }

  func applicationWillTerminate(_ notification: Notification) {
    if Defaults[.clearOnQuit] {
      AppState.shared.history.clear()
    }
  }

  private func migrateUserDefaults() {
    if Defaults[.migrations]["2024-07-01-version-2"] != true {
      // Start 2.x from scratch.
      Defaults.reset(.migrations)

      // Inverse hide* configuration keys.
      Defaults[.showFooter] = !UserDefaults.standard.bool(forKey: "hideFooter")
      Defaults[.showSearch] = !UserDefaults.standard.bool(forKey: "hideSearch")
      Defaults[.showTitle] = !UserDefaults.standard.bool(forKey: "hideTitle")
      UserDefaults.standard.removeObject(forKey: "hideFooter")
      UserDefaults.standard.removeObject(forKey: "hideSearch")
      UserDefaults.standard.removeObject(forKey: "hideTitle")

      Defaults[.migrations]["2024-07-01-version-2"] = true
    }

    // The following defaults are not used in Maccy 2.x
    // and should be removed in 3.x.
    // - LaunchAtLogin__hasMigrated
    // - avoidTakingFocus
    // - saratovSeparator
    // - maxMenuItemLength
    // - maxMenuItems
  }

  @objc
  private func performStatusItemClick() {
    if let event = NSApp.currentEvent {
      let modifierFlags = event.modifierFlags.intersection(.deviceIndependentFlagsMask)

      if modifierFlags.contains(.option) {
        Defaults[.ignoreEvents].toggle()

        if modifierFlags.contains(.shift) {
          Defaults[.ignoreOnlyNextEvent] = Defaults[.ignoreEvents]
        }

        return
      }
    }

    panel.toggle(height: AppState.shared.popup.height, at: .statusItem)
  }

  private func synchronizeMenuIconText() {
    _ = withObservationTracking {
      AppState.shared.menuIconText
    } onChange: {
      DispatchQueue.main.async {
        if Defaults[.showRecentCopyInMenuBar] {
          self.statusItem.button?.title = AppState.shared.menuIconText
        }
        self.synchronizeMenuIconText()
      }
    }
  }

  private func disableUnusedGlobalHotkeys() {
    let names: [KeyboardShortcuts.Name] = [.delete, .pin]
    KeyboardShortcuts.disable(names)

    NotificationCenter.default.addObserver(
      forName: Notification.Name("KeyboardShortcuts_shortcutByNameDidChange"),
      object: nil,
      queue: nil
    ) { notification in
      if let name = notification.userInfo?["name"] as? KeyboardShortcuts.Name, names.contains(name) {
        KeyboardShortcuts.disable(name)
      }
    }
  }
}


================================================
FILE: Maccy/AppStoreReview.swift
================================================
import StoreKit
import Defaults

class AppStoreReview {
  class func ask() {
    Defaults[.numberOfUsages] += 1
    guard Defaults[.numberOfUsages] > 50 else { return }

    let today = Date()
    let lastReviewRequestDate = Defaults[.lastReviewRequestedAt]
    guard let minimumRequestDate = Calendar.current.date(byAdding: .month, value: 1, to: lastReviewRequestDate),
          today > minimumRequestDate else {
      return
    }

    Defaults[.lastReviewRequestedAt] = today

    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
      SKStoreReviewController.requestReview()
    }
  }
}


================================================
FILE: Maccy/ApplicationImage.swift
================================================
import Defaults
import SwiftUI

class ApplicationImage {
  fileprivate static let fallbackImage = NSImage(
    systemSymbolName: "questionmark.app.dashed",
    accessibilityDescription: nil
  )!
  private static let retryInterval: TimeInterval = 60 * 60

  let bundleIdentifier: String?
  private var image: NSImage?
  private var lastChecked: Date?
  private var eventSource: (any DispatchSourceFileSystemObject)?

  init(bundleIdentifier: String?, image: NSImage? = nil) {
    self.bundleIdentifier = bundleIdentifier
    self.image = image
  }

  var nsImage: NSImage {
    guard let bundleIdentifier else {
      return Self.fallbackImage
    }

    if let image {
      return image
    }

    // The image has been queried before but since the application has been deleted.
    // Check from time to time if the application has returned.
    if let lastChecked,
      Date().timeIntervalSince(lastChecked) < Self.retryInterval {
      return Self.fallbackImage
    }
    lastChecked = .now

    if let appURL = NSWorkspace.shared.urlForApplication(
      withBundleIdentifier: bundleIdentifier
    ) {
      let img = NSWorkspace.shared.icon(forFile: appURL.path)
      image = img

      let descriptor = open(appURL.path, O_EVTONLY)
      if descriptor == -1 {
        let errorCode = errno
        print("Error code: \(errorCode)")
        print("Error message: \(String(cString: strerror(errorCode)))")
      } else if descriptor > 0 {
        let source = DispatchSource.makeFileSystemObjectSource(
          fileDescriptor: descriptor,
          eventMask: [.write, .delete],
          queue: DispatchQueue.global()
        )
        eventSource = source
        source.setEventHandler {
          DispatchQueue.main.async {
            let event = source.data
            if event.contains(.delete) {
              // File was deleted.
              print("Deleted", appURL.path)
              source.cancel()
              self.image = nil
            } else if event.contains(.write) {
              // File was modified. Fetch new icon
              print("Modified", appURL.path)
              self.image = NSWorkspace.shared.icon(forFile: appURL.path)
            }
          }
        }
        source.setCancelHandler {
          close(descriptor)
        }
        source.resume()
      }

      return img
    }

    return Self.fallbackImage
  }
}


================================================
FILE: Maccy/ApplicationImageCache.swift
================================================
class ApplicationImageCache {
  static let shared = ApplicationImageCache()

  private let universalClipboardIdentifier: String =
  "com.apple.finder.Open-iCloudDrive"
  private let fallback = ApplicationImage(bundleIdentifier: nil)
  private var cache: [String: ApplicationImage] = [:]

  func getImage(item: HistoryItem) -> ApplicationImage {
    guard let bundleIdentifier = bundleIdentifier(for: item) else {
      return fallback
    }

    if let image = cache[bundleIdentifier] {
      return image
    }

    let image = ApplicationImage(bundleIdentifier: bundleIdentifier)
    cache[bundleIdentifier] = image

    return image
  }

  private func bundleIdentifier(for item: HistoryItem) -> String? {
    if item.universalClipboard {
      return universalClipboardIdentifier
    }

    if let bundleIdentifier = item.application {
      return bundleIdentifier
    }

    return nil
  }
}


================================================
FILE: Maccy/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "filename" : "AppIcon (Big Sur)-16w.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "16x16"
    },
    {
      "filename" : "AppIcon (Big Sur)-32w.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "16x16"
    },
    {
      "filename" : "AppIcon (Big Sur)-32w-1.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "32x32"
    },
    {
      "filename" : "AppIcon (Big Sur)-64w.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "32x32"
    },
    {
      "filename" : "AppIcon (Big Sur)-128w.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "128x128"
    },
    {
      "filename" : "AppIcon (Big Sur)-256w.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "128x128"
    },
    {
      "filename" : "AppIcon (Big Sur)-256w-1.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "256x256"
    },
    {
      "filename" : "AppIcon (Big Sur)-512w.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "256x256"
    },
    {
      "filename" : "AppIcon (Big Sur)-512w-1.png",
      "idiom" : "mac",
      "scale" : "1x",
      "size" : "512x512"
    },
    {
      "filename" : "AppIcon (Big Sur)-1024w.png",
      "idiom" : "mac",
      "scale" : "2x",
      "size" : "512x512"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Maccy/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Maccy/Assets.xcassets/StatusBarMenuImage.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "mac",
      "filename" : "DarkMenuBar-16w.png",
      "scale" : "1x"
    },
    {
      "idiom" : "mac",
      "filename" : "LightMenuBar-16w.png",
      "appearances" : [
        {
          "appearance" : "luminosity",
          "value" : "dark"
        }
      ],
      "scale" : "1x"
    },
    {
      "idiom" : "mac",
      "filename" : "DarkMenuBar-32w.png",
      "scale" : "2x"
    },
    {
      "idiom" : "mac",
      "filename" : "LightMenuBar-32w.png",
      "appearances" : [
        {
          "appearance" : "luminosity",
          "value" : "dark"
        }
      ],
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  },
  "properties" : {
    "template-rendering-intent" : "template"
  }
}

================================================
FILE: Maccy/Assets.xcassets/clipboard.fill.imageset/Contents.json
================================================
{
  "images" : [
    {
      "filename" : "clipboard.fill.light_16.png",
      "idiom" : "mac",
      "scale" : "1x"
    },
    {
      "appearances" : [
        {
          "appearance" : "luminosity",
          "value" : "dark"
        }
      ],
      "filename" : "clipboard.fill.dark_16.png",
      "idiom" : "mac",
      "scale" : "1x"
    },
    {
      "filename" : "clipboard.fill.light_32.png",
      "idiom" : "mac",
      "scale" : "2x"
    },
    {
      "appearances" : [
        {
          "appearance" : "luminosity",
          "value" : "dark"
        }
      ],
      "filename" : "clipboard.fill.dark_32.png",
      "idiom" : "mac",
      "scale" : "2x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  },
  "properties" : {
    "template-rendering-intent" : "template"
  }
}


================================================
FILE: Maccy/Assets.xcassets/paperclip.imageset/Contents.json
================================================
{
  "images" : [
    {
      "filename" : "clip.fill.light_16.png",
      "idiom" : "mac",
      "scale" : "1x"
    },
    {
      "appearances" : [
        {
          "appearance" : "luminosity",
          "value" : "dark"
        }
      ],
      "filename" : "clip.fill.dark_16 1.png",
      "idiom" : "mac",
      "scale" : "1x"
    },
    {
      "filename" : "clip.fill.light_32.png",
      "idiom" : "mac",
      "scale" : "2x"
    },
    {
      "appearances" : [
        {
          "appearance" : "luminosity",
          "value" : "dark"
        }
      ],
      "filename" : "clip.fill.dark_32 1.png",
      "idiom" : "mac",
      "scale" : "2x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: Maccy/Assets.xcassets/scissors.imageset/Contents.json
================================================
{
  "images" : [
    {
      "filename" : "scissors_light_16.png",
      "idiom" : "mac",
      "scale" : "1x"
    },
    {
      "appearances" : [
        {
          "appearance" : "luminosity",
          "value" : "dark"
        }
      ],
      "filename" : "scissors_dark_16.png",
      "idiom" : "mac",
      "scale" : "1x"
    },
    {
      "filename" : "scissors_light_32.png",
      "idiom" : "mac",
      "scale" : "2x"
    },
    {
      "appearances" : [
        {
          "appearance" : "luminosity",
          "value" : "dark"
        }
      ],
      "filename" : "scissors_dark_32.png",
      "idiom" : "mac",
      "scale" : "2x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  },
  "properties" : {
    "template-rendering-intent" : "template"
  }
}


================================================
FILE: Maccy/Clipboard.swift
================================================
import AppKit
import Defaults
import Sauce

class Clipboard {
  static let shared = Clipboard()

  typealias OnNewCopyHook = (HistoryItem) -> Void

  private var onNewCopyHooks: [OnNewCopyHook] = []
  var changeCount: Int

  private let pasteboard = NSPasteboard.general

  private var timer: Timer?

  private let dynamicTypePrefix = "dyn."
  private let microsoftSourcePrefix = "com.microsoft.ole.source."
  private let supportedTypes: Set<NSPasteboard.PasteboardType> = [
    .fileURL,
    .html,
    .png,
    .rtf,
    .string,
    .tiff
  ]
  private let ignoredTypes: Set<NSPasteboard.PasteboardType> = [
    .autoGenerated,
    .concealed,
    .transient
  ]

  private var enabledTypes: Set<NSPasteboard.PasteboardType> { Defaults[.enabledPasteboardTypes] }
  private var disabledTypes: Set<NSPasteboard.PasteboardType> { supportedTypes.subtracting(enabledTypes) }

  private var sourceApp: NSRunningApplication? { NSWorkspace.shared.frontmostApplication }

  init() {
    changeCount = pasteboard.changeCount
  }

  func onNewCopy(_ hook: @escaping OnNewCopyHook) {
    onNewCopyHooks.append(hook)
  }

  func clearHooks() {
    onNewCopyHooks = []
  }

  func start() {
    timer = Timer.scheduledTimer(
      timeInterval: Defaults[.clipboardCheckInterval],
      target: self,
      selector: #selector(checkForChangesInPasteboard),
      userInfo: nil,
      repeats: true
    )
  }

  func restart() {
    timer?.invalidate()
    start()
  }

  @MainActor
  func copy(_ string: String) {
    pasteboard.clearContents()
    pasteboard.setString(string, forType: .string)
    sync()
    checkForChangesInPasteboard()
  }

  @MainActor
  func copy(_ item: HistoryItem?, removeFormatting: Bool = false) {
    guard let item else { return }

    pasteboard.clearContents()
    var contents = item.contents

    if removeFormatting {
      contents = clearFormatting(contents)
    }

    for content in contents {
      guard content.type != NSPasteboard.PasteboardType.fileURL.rawValue else { continue }
      pasteboard.setData(content.value, forType: NSPasteboard.PasteboardType(content.type))
    }

    // Use writeObjects for file URLs so that multiple files that are copied actually work.
    // Only do this for file URLs because it causes an issue with some other data types (like formatted text)
    // where the item is pasted more than once.
    let fileURLItems: [NSPasteboardItem] = contents.compactMap { item in
      guard item.type == NSPasteboard.PasteboardType.fileURL.rawValue else { return nil }
      guard let value = item.value else { return nil }
      let pasteItem = NSPasteboardItem()
      pasteItem.setData(value, forType: NSPasteboard.PasteboardType(item.type))
      return pasteItem
    }
    pasteboard.writeObjects(fileURLItems)

    pasteboard.setString("", forType: .fromMaccy)
    pasteboard.setString(item.application ?? "", forType: .source)
    sync()

    Task {
      Notifier.notify(body: item.title, sound: .knock)
      checkForChangesInPasteboard()
    }
  }

  // Based on https://github.com/Clipy/Clipy/blob/develop/Clipy/Sources/Services/PasteService.swift.
  func paste() {
    Accessibility.check()

    // Add flag that left/right modifier key has been pressed.
    // See https://github.com/TermiT/Flycut/pull/18 for details.
    let cmdFlag = CGEventFlags(rawValue: UInt64(KeyChord.pasteKeyModifiers.rawValue) | 0x000008)
    var vCode = Sauce.shared.keyCode(for: KeyChord.pasteKey)

    // Force QWERTY keycode when keyboard layout switches to
    // QWERTY upon pressing ⌘ key (e.g. "Dvorak - QWERTY ⌘").
    // See https://github.com/p0deje/Maccy/issues/482 for details.
    if KeyboardLayout.current.commandSwitchesToQWERTY && cmdFlag.contains(.maskCommand) {
      vCode = KeyChord.pasteKey.QWERTYKeyCode
    }

    let source = CGEventSource(stateID: .combinedSessionState)
    // Disable local keyboard events while pasting
    source?.setLocalEventsFilterDuringSuppressionState([.permitLocalMouseEvents, .permitSystemDefinedEvents],
                                                       state: .eventSuppressionStateSuppressionInterval)

    let keyVDown = CGEvent(keyboardEventSource: source, virtualKey: vCode, keyDown: true)
    let keyVUp = CGEvent(keyboardEventSource: source, virtualKey: vCode, keyDown: false)
    keyVDown?.flags = cmdFlag
    keyVUp?.flags = cmdFlag
    keyVDown?.post(tap: .cgSessionEventTap)
    keyVUp?.post(tap: .cgSessionEventTap)
  }

  func clear() {
    guard Defaults[.clearSystemClipboard] else {
      return
    }

    pasteboard.clearContents()
  }

  @objc
  @MainActor
  func checkForChangesInPasteboard() { // swiftlint:disable:this cyclomatic_complexity
    guard pasteboard.changeCount != changeCount else {
      return
    }

    changeCount = pasteboard.changeCount

    if pasteboard.pasteboardItems?.contains(where: { $0.types.contains(.fromMaccy) }) != true {
      // External copy occurred. Stop the current paste stack.
      // Maybe queue it into the paste stack? Configurable behaviour?
      AppState.shared.history.interruptPasteStack()
    }

    if Defaults[.ignoreEvents] {
      if Defaults[.ignoreOnlyNextEvent] {
        Defaults[.ignoreEvents] = false
        Defaults[.ignoreOnlyNextEvent] = false
      }

      return
    }

    // Reading types on NSPasteboard gives all the available
    // types - even the ones that are not present on the NSPasteboardItem.
    // See https://github.com/p0deje/Maccy/issues/241.
    if shouldIgnore(Set(pasteboard.types ?? [])) {
      return
    }

    if let sourceAppBundle = sourceApp?.bundleIdentifier, shouldIgnore(sourceAppBundle) {
      return
    }

    // Some applications (BBEdit, Edge) add 2 items to pasteboard when copying
    // so it's better to merge all data into a single record.
    // - https://github.com/p0deje/Maccy/issues/78
    // - https://github.com/p0deje/Maccy/issues/472
    var contents = [HistoryItemContent]()
    pasteboard.pasteboardItems?.forEach({ item in
      var types = Set(item.types)
      if types.contains(.string) && isEmptyString(item) && !richText(item) {
        return
      }

      if shouldIgnore(item) {
        return
      }

      types = types
        .subtracting(disabledTypes)
        .filter { !$0.rawValue.starts(with: dynamicTypePrefix) }
        .filter { !$0.rawValue.starts(with: microsoftSourcePrefix) }

      // Avoid reading Microsoft Word links from bookmarks and cross-references.
      // https://github.com/p0deje/Maccy/issues/613
      // https://github.com/p0deje/Maccy/issues/770
      if types.isSuperset(of: [.microsoftLinkSource, .microsoftObjectLink]) {
        types = types.subtracting([.microsoftLinkSource, .microsoftObjectLink, .pdf])
      }

      types.forEach { type in
        contents.append(HistoryItemContent(type: type.rawValue, value: item.data(forType: type)))
      }
    })

    guard !contents.isEmpty else {
      return
    }

    let historyItem = HistoryItem(contents: contents)

    if #unavailable(macOS 15.0) {
      // On macOS 14 the history item needs to be inserted into storage directly after creating it.
      try? History.shared.insertIntoStorage(historyItem)
    }

    historyItem.application = sourceApp?.bundleIdentifier
    historyItem.title = historyItem.generateTitle()

    onNewCopyHooks.forEach({ $0(historyItem) })
  }

  private func shouldIgnore(_ types: Set<NSPasteboard.PasteboardType>) -> Bool {
    let ignoredTypes = self.ignoredTypes
      .union(Defaults[.ignoredPasteboardTypes].map({ NSPasteboard.PasteboardType($0) }))

    return types.isDisjoint(with: enabledTypes) ||
      !types.isDisjoint(with: ignoredTypes)
  }

  private func shouldIgnore(_ sourceAppBundle: String) -> Bool {
    if Defaults[.ignoreAllAppsExceptListed] {
      return !Defaults[.ignoredApps].contains(sourceAppBundle)
    } else {
      return Defaults[.ignoredApps].contains(sourceAppBundle)
    }
  }

  private func shouldIgnore(_ item: NSPasteboardItem) -> Bool {
    for regexp in Defaults[.ignoreRegexp] {
      if let string = item.string(forType: .string) {
        do {
          let regex = try NSRegularExpression(pattern: regexp)
          if regex.numberOfMatches(in: string, range: NSRange(string.startIndex..., in: string)) > 0 {
            return true
          }
        } catch {
          return false
        }
      }
    }
    return false
  }

  private func isEmptyString(_ item: NSPasteboardItem) -> Bool {
    guard let string = item.string(forType: .string) else {
      return true
    }

    return string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
  }

  private func richText(_ item: NSPasteboardItem) -> Bool {
    if let rtf = item.data(forType: .rtf) {
      if let attributedString = NSAttributedString(rtf: rtf, documentAttributes: nil) {
        return !attributedString.string.isEmpty
      }
    }

    if let html = item.data(forType: .html) {
      if let attributedString = NSAttributedString(html: html, documentAttributes: nil) {
        return !attributedString.string.isEmpty
      }
    }

    return false
  }

  // Some applications requires window be unfocused and focused back to sync the clipboard.
  // - Chrome Remote Desktop (https://github.com/p0deje/Maccy/issues/948)
  // - Netbeans (https://github.com/p0deje/Maccy/issues/879)
  private func sync() {
    guard let app = sourceApp,
          app.bundleURL?.lastPathComponent == "Chrome Remote Desktop.app" ||
            app.localizedName?.contains("NetBeans") == true else {
      return
    }

    NSApp.activate(ignoringOtherApps: true)
    NSApp.hide(self)
  }

  private func clearFormatting(_ contents: [HistoryItemContent]) -> [HistoryItemContent] {
    var newContents: [HistoryItemContent] = contents
    let stringContents = contents.filter { NSPasteboard.PasteboardType($0.type) == .string }

    // If there is no string representation of data,
    // behave like we didn't have to remove formatting.
    if !stringContents.isEmpty {
      newContents = stringContents

      // Preserve file URLs.
      // https://github.com/p0deje/Maccy/issues/962
      let fileURLContents = contents.filter { NSPasteboard.PasteboardType($0.type) == .fileURL }
      if !fileURLContents.isEmpty {
        newContents += fileURLContents
      }
    }

    return newContents
  }
}


================================================
FILE: Maccy/ColorImage.swift
================================================
import AppKit
import SwiftHEXColors

class ColorImage {
  static func from(_ colorHex: String) -> NSImage? {
    guard let color = NSColor(hexString: colorHex) else {
      return nil
    }

    let image = NSImage(size: NSSize(width: 12, height: 12))
    image.lockFocus()
    color.drawSwatch(in: NSRect(x: 0, y: 0, width: 12, height: 12))
    image.unlockFocus()

    return image
  }
}


================================================
FILE: Maccy/Extensions/Collection+Surrounding.swift
================================================
extension Collection where Element: Equatable {
  func item(after: Element, where predicate: (Element) -> Bool) -> Element? {
    guard let currentIndex = firstIndex(of: after) else {
      return nil
    }

    var nextIndex = index(currentIndex, offsetBy: 1)
    while nextIndex < endIndex {
      let item = self[nextIndex]
      if predicate(item) {
        return item
      }
      nextIndex = index(nextIndex, offsetBy: 1)
    }
    return nil
  }

  func item(before: Element, where predicate: (Element) -> Bool) -> Element? {
    guard let currentIndex = firstIndex(of: before) else {
      return nil
    }

    var prevIndex = index(currentIndex, offsetBy: -1)
    while prevIndex >= startIndex {
      let item = self[prevIndex]
      if predicate(item) {
        return item
      }
      prevIndex = index(prevIndex, offsetBy: -1)
    }
    return nil
  }

  func between(from fromElement: Element, to toElement: Element, inOrder: Bool = false) -> [Element]? {
    guard let fromIndex = firstIndex(of: fromElement) else {
      return nil
    }
    guard let toIndex = firstIndex(of: toElement) else {
      return nil
    }
    let startIndex = Swift.min(fromIndex, toIndex)
    let endIndex = Swift.max(fromIndex, toIndex)
    let items = self[startIndex...endIndex]
    if !inOrder && fromIndex > toIndex {
      return items.reversed()
    } else {
      return Array(items)
    }
  }
}

extension Array where Element: Equatable {
  func nearest(to element: Element, where condition: (Element) -> Bool) -> Element? {
    guard let currentIndex = firstIndex(of: element) else {
      return nil
    }
    let nextNearest = self[currentIndex...].firstIndex(where: { condition($0) })
    let previousNearest = self[...currentIndex].lastIndex(where: { condition($0) })
    switch (nextNearest, previousNearest) {
    case (nil, nil):
      return nil
    case (.some(let index), .none):
      return self[currentIndex + index]
    case (.none, .some(let index)):
      return self[index]
    case (.some(let index1), .some(let index2)):
      let pos1 = currentIndex + index1
      let pos2 = index2
      return abs(pos1 - currentIndex) < abs(pos2 - currentIndex)
      ? self[pos1]
      : self[pos2]
    }

  }
}


================================================
FILE: Maccy/Extensions/Color+Random.swift
================================================
import SwiftUI

// Useful to debug SwiftUI view redraws: .background(.random).
extension ShapeStyle where Self == Color {
  static var random: Color {
    Color(
      red: .random(in: 0...1),
      green: .random(in: 0...1),
      blue: .random(in: 0...1)
    )
  }
}


================================================
FILE: Maccy/Extensions/Defaults.Keys+Names.swift
================================================
import AppKit
import Defaults

struct StorageType {
  static let files = StorageType(types: [.fileURL])
  static let images = StorageType(types: [.png, .tiff])
  static let text = StorageType(types: [.html, .rtf, .string])
  static let all = StorageType(types: files.types + images.types + text.types)

  var types: [NSPasteboard.PasteboardType]
}

extension Defaults.Keys {
  static let clearOnQuit = Key<Bool>("clearOnQuit", default: false)
  static let clearSystemClipboard = Key<Bool>("clearSystemClipboard", default: false)
  static let clipboardCheckInterval = Key<Double>("clipboardCheckInterval", default: 0.5)
  static let enabledPasteboardTypes = Key<Set<NSPasteboard.PasteboardType>>(
    "enabledPasteboardTypes", default: Set(StorageType.all.types)
  )
  static let highlightMatch = Key<HighlightMatch>("highlightMatch", default: .bold)
  static let ignoreAllAppsExceptListed = Key<Bool>("ignoreAllAppsExceptListed", default: false)
  static let ignoreEvents = Key<Bool>("ignoreEvents", default: false)
  static let ignoreOnlyNextEvent = Key<Bool>("ignoreOnlyNextEvent", default: false)
  static let ignoreRegexp = Key<[String]>("ignoreRegexp", default: [])
  static let ignoredApps = Key<[String]>("ignoredApps", default: [])
  static let ignoredPasteboardTypes = Key<Set<String>>(
    "ignoredPasteboardTypes",
    default: Set([
      "Pasteboard generator type",
      "com.agilebits.onepassword",
      "com.typeit4me.clipping",
      "de.petermaurer.TransientPasteboardType",
      "net.antelle.keeweb"
    ])
  )
  static let imageMaxHeight = Key<Int>("imageMaxHeight", default: 40)
  static let lastReviewRequestedAt = Key<Date>("lastReviewRequestedAt", default: Date.now)
  static let menuIcon = Key<MenuIcon>("menuIcon", default: .maccy)
  static let migrations = Key<[String: Bool]>("migrations", default: [:])
  static let numberOfUsages = Key<Int>("numberOfUsages", default: 0)
  static let pasteByDefault = Key<Bool>("pasteByDefault", default: false)
  static let pinTo = Key<PinsPosition>("pinTo", default: .top)
  static let popupPosition = Key<PopupPosition>("popupPosition", default: .cursor)
  static let popupScreen = Key<Int>("popupScreen", default: 0)
  static let previewDelay = Key<Int>("previewDelay", default: 1500)
  static let removeFormattingByDefault = Key<Bool>("removeFormattingByDefault", default: false)
  static let searchMode = Key<Search.Mode>("searchMode", default: .exact)
  static let showFooter = Key<Bool>("showFooter", default: true)
  static let showInStatusBar = Key<Bool>("showInStatusBar", default: true)
  static let showRecentCopyInMenuBar = Key<Bool>("showRecentCopyInMenuBar", default: false)
  static let showSearch = Key<Bool>("showSearch", default: true)
  static let searchVisibility = Key<SearchVisibility>("searchVisibility", default: .always)
  static let showSpecialSymbols = Key<Bool>("showSpecialSymbols", default: true)
  static let showTitle = Key<Bool>("showTitle", default: true)
  static let size = Key<Int>("historySize", default: 200)
  static let sortBy = Key<Sorter.By>("sortBy", default: .lastCopiedAt)
  static let suppressClearAlert = Key<Bool>("suppressClearAlert", default: false)
  static let windowSize = Key<NSSize>("windowSize", default: NSSize(width: 450, height: 800))
  static let windowPosition = Key<NSPoint>("windowPosition", default: NSPoint(x: 0.5, y: 0.8))
  static let showApplicationIcons = Key<Bool>("showApplicationIcons", default: false)
  static let previewWidth = Key<CGFloat>("previewWidth", default: 400)
}


================================================
FILE: Maccy/Extensions/Dictionary+RemoveItem.swift
================================================
extension Dictionary {
  // Removes all key-value pairs where the value satisfies the given predicate.
  mutating func removeValues(where shouldRemove: (Value) -> Bool) {
    for (key, value) in self where shouldRemove(value) {
      self.removeValue(forKey: key)
    }
  }
}


================================================
FILE: Maccy/Extensions/KeyEquivalent+Keys.swift
================================================
import SwiftUI

extension KeyEquivalent {
  static let backspace = KeyEquivalent("\u{7F}")
}


================================================
FILE: Maccy/Extensions/KeyboardShortcuts.Name+Shortcuts.swift
================================================
import KeyboardShortcuts

extension KeyboardShortcuts.Name {
  static let popup = Self("popup", default: Shortcut(.c, modifiers: [.command, .shift]))
  static let pin = Self("pin", default: Shortcut(.p, modifiers: [.option]))
  static let delete = Self("delete", default: Shortcut(.delete, modifiers: [.option]))
  static let togglePreview = Self("togglePreview", default: Shortcut(.space, modifiers: [.control]))
}


================================================
FILE: Maccy/Extensions/ModifierFlags+Description.swift
================================================
import AppKit.NSEvent
import Carbon.HIToolbox

// https://github.com/sindresorhus/KeyboardShortcuts/blob/e6b60117ec266e1e5d059f7f34815144f9762b36/Sources/KeyboardShortcuts/Utilities.swift#L308-L342
extension NSEvent.ModifierFlags {
  var description: String {
    var description = ""

    if contains(.control) {
      description += "⌃"
    }

    if contains(.option) {
      description += "⌥"
    }

    if contains(.shift) {
      description += "⇧"
    }

    if contains(.command) {
      description += "⌘"
    }

    if contains(.function) {
      description += "🌐\u{FE0E}"
    }

    return description
  }
}


================================================
FILE: Maccy/Extensions/NSApplication+Windows.swift
================================================
import AppKit

extension NSApplication {
  var alertWindow: NSWindow? { windows.first { $0.className == "_NSAlertPanel" } }
  var characterPickerWindow: NSWindow? { windows.first { $0.className == "NSPanelViewBridge" } }
}


================================================
FILE: Maccy/Extensions/NSImage+Names.swift
================================================
import Cocoa

extension NSImage {
  static let gearshape = NSImage(systemSymbolName: "gearshape", accessibilityDescription: "gearshape")
  static let externaldrive = NSImage(systemSymbolName: "externaldrive", accessibilityDescription: "externaldrive")
  static let paintpalette = NSImage(systemSymbolName: "paintpalette", accessibilityDescription: "paintpalette")
  static let pincircle = NSImage(systemSymbolName: "pin.circle", accessibilityDescription: "pin.cirlce")
  static let nosign = NSImage(systemSymbolName: "nosign", accessibilityDescription: "nosign")
  static let gearshape2 = NSImage(systemSymbolName: "gearshape.2", accessibilityDescription: "gearshape2")
}

extension NSImage.Name {
  static let clipboard = NSImage.Name("clipboard.fill")
  static let maccyStatusBar = NSImage.Name("StatusBarMenuImage")
  static let scissors = NSImage.Name("scissors")
  static let paperclip = NSImage.Name("paperclip")
}


================================================
FILE: Maccy/Extensions/NSImage+Resized.swift
================================================
import AppKit.NSImage

// Based on https://stackoverflow.com/questions/73062803/resizing-nsimage-keeping-aspect-ratio-reducing-the-image-size-while-trying-to-sc.
extension NSImage {
  func resized(to newSize: NSSize) -> NSImage {
    let ratioX = newSize.width / size.width
    let ratioY = newSize.height / size.height
    let ratio = ratioX < ratioY ? ratioX : ratioY
    let newHeight = size.height * ratio
    let newWidth = size.width * ratio
    let newSize = NSSize(width: newWidth, height: newHeight)

    // Don't attempt to size up.
    if newSize.height >= size.height {
      return self
    }

    return NSImage(size: newSize, flipped: false) { destRect in
      if let context = NSGraphicsContext.current {
        context.imageInterpolation = .high
        self.draw(in: destRect, from: NSRect.zero, operation: .copy, fraction: 1)
      }

      return true
    }
  }
}


================================================
FILE: Maccy/Extensions/NSPasteboard.PasteboardType+Types.swift
================================================
import AppKit.NSPasteboard
import Defaults

extension NSPasteboard.PasteboardType: Defaults.Serializable {
  static let heic = NSPasteboard.PasteboardType(rawValue: "public.heic")
  static let jpeg = NSPasteboard.PasteboardType(rawValue: "public.jpeg")
  static let universalClipboard = NSPasteboard.PasteboardType(rawValue: "com.apple.is-remote-clipboard")

  // See http://nspasteboard.org for more details.
  static let autoGenerated = NSPasteboard.PasteboardType(rawValue: "org.nspasteboard.AutoGeneratedType")
  static let concealed = NSPasteboard.PasteboardType(rawValue: "org.nspasteboard.ConcealedType")
  static let source = NSPasteboard.PasteboardType(rawValue: "org.nspasteboard.source")
  static let transient = NSPasteboard.PasteboardType(rawValue: "org.nspasteboard.TransientType")

  // https://github.com/p0deje/Maccy/issues/429#issuecomment-1182575226
  static let modified = NSPasteboard.PasteboardType(rawValue: "x.nspasteboard.ModifiedType")

  // Marks that copy was made from Maccy.
  static let fromMaccy = NSPasteboard.PasteboardType(rawValue: "org.p0deje.Maccy")

  // Types that indicate Microsoft Word bookmarks (links).
  static let microsoftObjectLink = NSPasteboard.PasteboardType(rawValue: "com.microsoft.ObjectLink")
  static let microsoftLinkSource = NSPasteboard.PasteboardType(rawValue: "com.microsoft.Link-Source")

  // Safari preview and extra metadata that changes frequently.
  static let linkPresentationMetadata = NSPasteboard.PasteboardType(rawValue: "com.apple.linkpresentation.metadata")
  // swiftlint:disable:next line_length
  static let customWebKitPasteboardData = NSPasteboard.PasteboardType(rawValue: "com.apple.WebKit.custom-pasteboard-data")

  // Chromium (VSCode)
  static let customChromiumWebData = NSPasteboard.PasteboardType(rawValue: "org.chromium.web-custom-data")
  static let chromiumSourceUrl = NSPasteboard.PasteboardType(rawValue: "org.chromium.source-url")
  static let chromiumSourceToken = NSPasteboard.PasteboardType(rawValue: "org.chromium.internal.source-rfh-token")

  // Apple Notes
  static let notesRichText = NSPasteboard.PasteboardType(rawValue: "com.apple.notes.richtext")
}


================================================
FILE: Maccy/Extensions/NSPoint+DefaultsSerializable.swift
================================================
import CoreGraphics
import Defaults
import Foundation

extension NSPoint: Defaults.Serializable {
}


================================================
FILE: Maccy/Extensions/NSRect+Centered.swift
================================================
import Foundation

extension NSRect {
  static func centered(ofSize size: NSSize, in frame: NSRect) -> NSRect {
    let bottomLeftX = (frame.width - size.width) / 2 + frame.minX
    let bottomLeftY = (frame.height - size.height) / 2 + frame.minY

    return NSRect(x: bottomLeftX + 1.0, y: bottomLeftY + 1.0, width: size.width, height: size.height)
  }
}


================================================
FILE: Maccy/Extensions/NSRunningApplication+WindowFrame.swift
================================================
import AppKit.NSRunningApplication
import Carbon

extension NSRunningApplication {
  var windowFrame: NSRect? {
    let options = CGWindowListOption(arrayLiteral: [.excludeDesktopElements, .optionOnScreenOnly])
    let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0))
    if let windowInfoList = windowListInfo as NSArray? as? [[String: AnyObject]] {
      for info in windowInfoList {
        if let windowPID = info["kCGWindowOwnerPID"] as? UInt32, windowPID == processIdentifier {
          if let screen = NSScreen.screens.first,
             let topLeftX = info["kCGWindowBounds"]?["X"] as? Double,
             let topLeftY = info["kCGWindowBounds"]?["Y"] as? Double,
             let width = info["kCGWindowBounds"]?["Width"] as? Double,
             let height = info["kCGWindowBounds"]?["Height"] as? Double {
            var rect = NSRect(x: topLeftX, y: topLeftY, width: width, height: height)
            // Convert CGWindowBounds to NSScreen coordinates
            // http://www.krizka.net/2010/04/20/converting-between-kcgwindowbounds-and-nswindowframe
            rect.origin.y = screen.frame.size.height - rect.origin.y - rect.size.height
            return rect
          }
        }
      }
    }

    return nil
  }
}


================================================
FILE: Maccy/Extensions/NSScreen+ForPopup.swift
================================================
import AppKit.NSScreen
import Defaults

extension NSScreen {
  static var forPopup: NSScreen? {
    let desiredScreen = Defaults[.popupScreen]
    if desiredScreen == 0 || desiredScreen > NSScreen.screens.count {
      return NSScreen.main
    } else {
      return NSScreen.screens[desiredScreen - 1]
    }
  }
}


================================================
FILE: Maccy/Extensions/NSSize+DefaultsSerializable.swift
================================================
import CoreGraphics
import Defaults
import Foundation

extension NSSize: Defaults.Serializable {
}


================================================
FILE: Maccy/Extensions/NSSound+Named.swift
================================================
import AppKit.NSSound

extension NSSound {
  static let knock = NSSound(
    contentsOf: Bundle.main.url(forResource: "Knock", withExtension: "caf")!, byReference: true)
  static let write = NSSound(
    contentsOf: Bundle.main.url(forResource: "Write", withExtension: "caf")!, byReference: true)
}


================================================
FILE: Maccy/Extensions/NSWorkspace+ApplicationName.swift
================================================
import AppKit.NSWorkspace

extension NSWorkspace {
  func applicationName(url: URL) -> String {
    if let bundle = Bundle(url: url) {
      if let displayName = bundle.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String {
        return displayName
      } else if let name = bundle.object(forInfoDictionaryKey: "CFBundleName") as? String {
        return name
      }
    }

    return url.deletingLastPathComponent().lastPathComponent
  }
}


================================================
FILE: Maccy/Extensions/Sauce+KeyboardShortcuts.swift
================================================
import KeyboardShortcuts
import Sauce

extension Sauce {
  func key(shortcut: KeyboardShortcuts.Name) -> Key? {
    if let shortcut = KeyboardShortcuts.Shortcut(name: shortcut) {
      return Sauce.shared.key(for: shortcut.carbonKeyCode)
    } else {
      return nil
    }
  }
}


================================================
FILE: Maccy/Extensions/Settings.PaneIdentifier+Panes.swift
================================================
import Settings

extension Settings.PaneIdentifier {
  static let advanced = Self("advanced")
  static let appearance = Self("appearance")
  static let general = Self("general")
  static let ignore = Self("ignore")
  static let pins = Self("pins")
  static let storage = Self("storage")
}


================================================
FILE: Maccy/Extensions/String+Identifiable.swift
================================================
extension String: @retroactive Identifiable {
  public var id: Self { self }
}


================================================
FILE: Maccy/Extensions/String+Shortened.swift
================================================
extension String {
  func shortened(to maxLength: Int) -> String {
    guard count > maxLength else {
      return self
    }

    return String(self[...index(startIndex, offsetBy: maxLength)])
  }
}


================================================
FILE: Maccy/FloatingPanel.swift
================================================
import Defaults
import SwiftUI

// An NSPanel subclass that implements floating panel traits.
// https://stackoverflow.com/questions/46023769/how-to-show-a-window-without-stealing-focus-on-macos
class FloatingPanel<Content: View>: NSPanel, NSWindowDelegate {
  var isPresented: Bool = false
  var statusBarButton: NSStatusBarButton?
  let onClose: () -> Void

  override var isMovable: Bool {
    get { Defaults[.popupPosition] != .statusItem }
    set {}
  }

  init(
    contentRect: NSRect,
    identifier: String = "",
    statusBarButton: NSStatusBarButton? = nil,
    onClose: @escaping () -> Void,
    view: () -> Content
  ) {
    self.onClose = onClose

    super.init(
        contentRect: contentRect,
        styleMask: [.nonactivatingPanel, .resizable, .closable, .fullSizeContentView],
        backing: .buffered,
        defer: false
    )

    self.statusBarButton = statusBarButton
    self.identifier = NSUserInterfaceItemIdentifier(identifier)

    Defaults[.windowSize] = contentRect.size
    delegate = self

    animationBehavior = .none
    isFloatingPanel = true
    level = .statusBar
    collectionBehavior = [.auxiliary, .stationary, .moveToActiveSpace, .fullScreenAuxiliary]
    titleVisibility = .hidden
    titlebarAppearsTransparent = true
    isMovableByWindowBackground = true
    hidesOnDeactivate = false
    backgroundColor = .clear
    titlebarSeparatorStyle = .none

    // Hide all traffic light buttons
    standardWindowButton(.closeButton)?.isHidden = true
    standardWindowButton(.miniaturizeButton)?.isHidden = true
    standardWindowButton(.zoomButton)?.isHidden = true

    contentView = NSHostingView(
      rootView: view()
        // The safe area is ignored because the title bar still interferes with the geometry
        .ignoresSafeArea()
        .gesture(DragGesture()
          .onEnded { _ in
            self.saveWindowPosition()
        })
    )
    contentView?.layer?.cornerRadius = Popup.cornerRadius + Popup.horizontalPadding
  }

  func toggle(height: CGFloat, at popupPosition: PopupPosition = Defaults[.popupPosition]) {
    if isPresented {
      close()
    } else {
      open(height: height, at: popupPosition)
    }
  }

  func open(height: CGFloat, at popupPosition: PopupPosition = Defaults[.popupPosition]) {
    let size = Defaults[.windowSize]
    setContentSize(NSSize(width: min(frame.width, size.width), height: min(height, size.height)))
    setFrameOrigin(popupPosition.origin(size: frame.size, statusBarButton: statusBarButton))
    orderFrontRegardless()
    makeKey()
    isPresented = true

    if popupPosition == .statusItem {
      DispatchQueue.main.async {
        self.statusBarButton?.isHighlighted = true
      }
    }
  }

  func verticallyResize(to newHeight: CGFloat) {
    var newSize = frame.size
    newSize.height = newHeight
    var newOrigin = frame.origin
    newOrigin.y += (frame.height - newSize.height)

    NSAnimationContext.runAnimationGroup { (context) in
      context.duration = 0.2
      animator().setFrame(NSRect(origin: newOrigin, size: newSize), display: true)
    }
  }

  func determinePreviewPlacement() {
    let preview = AppState.shared.preview
    guard !preview.state.isOpen else { return }
    let newSize = preview.computeSizeWithPreview(frame.size, state: .open)
    preview.placement = preview.computePlacement(window: self, for: newSize)
  }

  func saveWindowPosition() {
    if let screenFrame = screen?.visibleFrame {
      // Only store the size of the window without the preview
      let width = AppState.shared.preview.contentWidth

      let anchorX = frame.minX + width / 2 - screenFrame.minX
      let anchorY = frame.maxY - screenFrame.minY
      Defaults[.windowPosition] = NSPoint(x: anchorX / screenFrame.width, y: anchorY / screenFrame.height)
    }
  }

  func saveWindowFrame(frame: NSRect) {
    Defaults[.windowSize] = frame.size
    saveWindowPosition()
  }

  func windowWillResize(_ sender: NSWindow, to frameSize: NSSize) -> NSSize {
    let preview = AppState.shared.preview

    if inLiveResize && preview.resizingMode == .none {
      let screenPoint = NSEvent.mouseLocation
      let windowPoint = convertPoint(fromScreen: screenPoint)
      let location: SlideoutPlacement = windowPoint.x <= frame.width / 2 ? .left : .right
      if (location == preview.placement) && preview.state == .open {
        preview.startResize(mode: .slideout)
      } else {
        preview.startResize(mode: .content)
      }
    }

    var finalFrameSize = frameSize
    var minContent = preview.minimumContentWidth
    var minPreview = 0.0

    if inLiveResize && preview.resizingMode != .none {
      if preview.resizingMode == .content && preview.state == .open {
        minPreview = preview.slideoutWidth
      }
      if preview.resizingMode == .slideout {
        minPreview = preview.minimumSlideoutWidth
        minContent = preview.contentWidth
      }
    }
    finalFrameSize.width = max(finalFrameSize.width, minContent + minPreview)

    if !AppState.shared.preview.state.isAnimating {
      var size = frame.size
      // Only store the size of the window without the preview
      size.width = AppState.shared.preview.contentWidth
      saveWindowFrame(frame: NSRect(origin: frame.origin, size: size))
    }

    return finalFrameSize
  }

  func windowWillMove(_ notification: Notification) {
    determinePreviewPlacement()
  }

  func windowDidMove(_ notification: Notification) {
    determinePreviewPlacement()
  }

  func windowWillStartLiveResize(_ notification: Notification) {
    AppState.shared.preview.cancelAutoOpen()
  }

  func windowDidEndLiveResize(_ notification: Notification) {
    AppState.shared.preview.startAutoOpen()
    AppState.shared.preview.endResize()
  }

  func windowDidBecomeKey(_ notification: Notification) {
    AppState.shared.preview.enableAutoOpen()

    if AppState.shared.navigator.leadHistoryItem != nil {
      AppState.shared.preview.startAutoOpen()
    }
  }

  func windowDidResignKey(_ notification: Notification) {
    AppState.shared.preview.disableAutoOpen()
  }

  // Close automatically when out of focus, e.g. outside click.
  override func resignKey() {
    super.resignKey()
    // Don't hide if confirmation is shown.
    if NSApp.alertWindow == nil {
      close()
    }
  }

  override func close() {
    super.close()
    AppState.shared.preview.state = .closed
    isPresented = false
    statusBarButton?.isHighlighted = false
    onClose()
  }

  // Allow text inputs inside the panel can receive focus
  override var canBecomeKey: Bool {
    return true
  }
}


================================================
FILE: Maccy/GlobalHotKey.swift
================================================
import AppKit
import KeyboardShortcuts
import Sauce
import SwiftUI

class GlobalHotKey {
  typealias Handler = () -> Void

  static public var key: KeyEquivalent? { KeyboardShortcuts.Shortcut(name: .popup)?.toKeyEquivalent() }
  static public var modifierFlags: EventModifiers? { KeyboardShortcuts.Shortcut(name: .popup)?.toEventModifiers() }

  private var handler: Handler

  init(_ handler: @escaping Handler) {
    self.handler = handler
//    KeyboardShortcuts.onKeyDown(for: .popup, action: handler)
  }
}


================================================
FILE: Maccy/HighlightMatch.swift
================================================
import Foundation
import Defaults

enum HighlightMatch: String, CaseIterable, Identifiable, CustomStringConvertible, Defaults.Serializable {
  case color
  case bold
  case italic
  case underline

  var id: Self { self }

  var description: String {
    switch self {
    case .bold:
      return NSLocalizedString("HighlightMatchBold", tableName: "AppearanceSettings", comment: "")
    case .color:
      return NSLocalizedString("HighlightMatchColor", tableName: "AppearanceSettings", comment: "")
    case .italic:
      return NSLocalizedString("HighlightMatchItalic", tableName: "AppearanceSettings", comment: "")
    case .underline:
      return NSLocalizedString("HighlightMatchUnderline", tableName: "AppearanceSettings", comment: "")
    }
  }
}


================================================
FILE: Maccy/History.xcdatamodeld/History.xcdatamodel/contents
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="16119" systemVersion="19E266" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
    <elements/>
</model>

================================================
FILE: Maccy/HistoryItemAction.swift
================================================
import AppKit.NSEvent
import Defaults

enum HistoryItemAction {
  case unknown
  case copy
  case paste
  case pasteWithoutFormatting

  init(_ modifierFlags: NSEvent.ModifierFlags) {  // swiftlint:disable:this cyclomatic_complexity
    switch modifierFlags {
    case .command where !Defaults[.pasteByDefault]:
      self = .copy
    case .command where Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      self = .paste
    case .command where Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      self = .pasteWithoutFormatting
    case .option where !Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      self = .paste
    case .option where !Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      self = .pasteWithoutFormatting
    case .option where Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      self = .copy
    case .option where Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      self = .copy
    case [.option, .shift] where !Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      self = .pasteWithoutFormatting
    case [.option, .shift] where !Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      self = .paste
    case [.command, .shift] where Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      self = .pasteWithoutFormatting
    case [.command, .shift] where Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      self = .paste
    default:
      self = .unknown
    }
  }

  var modifierFlags: NSEvent.ModifierFlags {
    switch self {
    case .copy where !Defaults[.pasteByDefault]:
      return .command
    case .paste where Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      return .command
    case .pasteWithoutFormatting where Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      return .command
    case .paste where !Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      return .option
    case .pasteWithoutFormatting where !Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      return .option
    case .copy where Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      return .option
    case .copy where Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      return .option
    case .pasteWithoutFormatting where !Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      return [.option, .shift]
    case .paste where !Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      return [.option, .shift]
    case .pasteWithoutFormatting where Defaults[.pasteByDefault] && !Defaults[.removeFormattingByDefault]:
      return [.command, .shift]
    case .paste where Defaults[.pasteByDefault] && Defaults[.removeFormattingByDefault]:
      return [.command, .shift]
    default:
      return []
    }
  }
}


================================================
FILE: Maccy/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(MARKETING_VERSION)</string>
	<key>CFBundleVersion</key>
	<string>$(CURRENT_PROJECT_VERSION)</string>
	<key>LSApplicationCategoryType</key>
	<string>public.app-category.productivity</string>
	<key>LSMinimumSystemVersion</key>
	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
	<key>LSUIElement</key>
	<true/>
	<key>NSHumanReadableCopyright</key>
	<string>Copyright © Alexey Rodionov</string>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>
	<key>SUEnableDownloaderService</key>
	<true/>
	<key>SUEnableInstallerLauncherService</key>
	<true/>
	<key>SUFeedURL</key>
	<string>https://raw.githubusercontent.com/p0deje/Maccy/master/appcast.xml</string>
</dict>
</plist>


================================================
FILE: Maccy/Intents/AppIntentError.swift
================================================
import Foundation

enum AppIntentError: Swift.Error, CustomLocalizedStringResourceConvertible {
  case notFound

  var localizedStringResource: LocalizedStringResource {
    switch self {
    case .notFound: return "Clipboard item not found"
    }
  }
}


================================================
FILE: Maccy/Intents/Clear.swift
================================================
import AppIntents
import Defaults

struct Clear: AppIntent, CustomIntentMigratedAppIntent {
  static let intentClassName = "ClearIntent"

  static var title: LocalizedStringResource = "Clear Clipboard History"
  static var description = IntentDescription("Clears all Maccy clipboard history except for pinned items.")

  static var parameterSummary: some ParameterSummary {
    Summary("Clear Clipboard History")
  }

  func perform() async throws -> some IntentResult {
    if !Defaults[.suppressClearAlert] {
      try await requestConfirmation()
    }

    await AppState.shared.history.clear()
    return .result()
  }
}


================================================
FILE: Maccy/Intents/Delete.swift
================================================
import AppIntents

struct Delete: AppIntent, CustomIntentMigratedAppIntent {
  static let intentClassName = "DeleteIntent"

  static var title: LocalizedStringResource = "Delete Item from Clipboard History"
  static var description = IntentDescription("Deletes an item from Maccy clipboard history.")

  @Parameter(title: "Number", default: 1)
  var number: Int

  static var parameterSummary: some ParameterSummary {
    Summary("Delete \(\.$number) Item from Clipboard History")
  }

  private let positionOffset = 1

  func perform() async throws -> some IntentResult {
    let items = AppState.shared.history.items
    let index = number - positionOffset
    guard items.count >= index else {
      throw AppIntentError.notFound
    }

    await AppState.shared.history.delete(items[index])

    return .result()
  }
}


================================================
FILE: Maccy/Intents/Get.swift
================================================
import Foundation
import AppIntents

struct Get: AppIntent, CustomIntentMigratedAppIntent {
  static let intentClassName = "GetIntent"

  static var title: LocalizedStringResource = "Get Item from Clipboard History"
  static var description = IntentDescription("""
  Gets an item from Maccy clipboard history.
  The returned item can be used to access its plain/rich/HTML text, image contents or file location.
  """)

  @Parameter(title: "Selected", default: true)
  var selected: Bool

  @Parameter(title: "Number", default: 1)
  var number: Int

  private let positionOffset = 1

  static var parameterSummary: some ParameterSummary {
    When(\.$selected, .equalTo, false) {
      Summary {
        \.$number
        \.$selected
      }
    } otherwise: {
      Summary {
        \.$selected
      }
    }
  }

  func perform() async throws -> some IntentResult & ReturnsValue<HistoryItemAppEntity> {
    var item: HistoryItem?
    if selected {
      item = AppState.shared.navigator.selection.first?.item
    } else {
      let index = number - positionOffset
      if AppState.shared.history.items.count >= index {
        item = AppState.shared.history.items[index].item
      }
    }

    guard let item else {
      throw AppIntentError.notFound
    }

    let intentItem = HistoryItemAppEntity()
    intentItem.text = item.text

    if let html = item.htmlData {
      intentItem.html = String(data: html, encoding: .utf8)
    }

    if let fileURL = item.fileURLs.first {
      intentItem.file = fileURL
    }

    if let imageData = item.imageData {
      let file = URL.documentsDirectory.appending(path: "image.png")
      try imageData.write(to: file, options: [.atomic, .completeFileProtection])
      intentItem.image = file
    }

    if let rtf = item.rtfData {
      intentItem.richText = String(data: rtf, encoding: .utf8)
    }

    return .result(value: intentItem)
  }
}


================================================
FILE: Maccy/Intents/HistoryItemAppEntity.swift
================================================
import AppIntents

struct HistoryItemAppEntity: TransientAppEntity {
  static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Clipboard item")

  @Property(title: "File")
  var file: URL?

  @Property(title: "HTML")
  var html: String?

  @Property(title: "Image")
  var image: URL?

  @Property(title: "Rich Text")
  var richText: String?

  @Property(title: "Text")
  var text: String?

  var displayRepresentation: DisplayRepresentation {
    DisplayRepresentation(title: "Clipboard item")
  }
}


================================================
FILE: Maccy/Intents/Select.swift
================================================
import AppIntents

struct Select: AppIntent, CustomIntentMigratedAppIntent {
  static let intentClassName = "SelectIntent"

  static var title: LocalizedStringResource = "Select Item in Clipboard History"
  static var description = IntentDescription("""
  Selects an item in Maccy clipboard history.
  Depending on Maccy settings, it might trigger pasting of the selected item.
  """)

  static var parameterSummary: some ParameterSummary {
    Summary("Select \(\.$number) Item in Clipboard History")
  }

  @Parameter(title: "Number", default: 1, requestValueDialog: "What is the number of the item?")
  var number: Int

  private let positionOffset = 1

  func perform() async throws -> some IntentResult & ReturnsValue<String> {
    let items = AppState.shared.history.items
    let index = number - positionOffset
    guard items.count >= index else {
      throw AppIntentError.notFound
    }

    let value = items[index].title
    await AppState.shared.history.select(items[index])

    return .result(value: value)
  }
}


================================================
FILE: Maccy/ItemsProtocol.swift
================================================
protocol HasVisibility {
  var isVisible: Bool { get }
}

protocol ItemsContainer {
  associatedtype Item
  var containerVisible: Bool { get }
  var items: [Item] { get set }
}

extension ItemsContainer {
    var containerVisible: Bool { true }
}

private extension ItemsContainer where Item: HasVisibility {}

extension ItemsContainer where Item: HasVisibility {

  var visibleItems: [Item] {
    guard containerVisible else { return [] }
    return self.items.lazy.filter(\.isVisible)
  }

  var firstVisibleItem: Item? {
    guard containerVisible else { return nil }
    return self.items.first(where: \.isVisible)
  }
  func firstVisibleItem(where predicate: (Item) -> Bool) -> Item? {
    guard containerVisible else { return nil }
    return self.items.first { $0.isVisible && predicate($0) }
  }
  var lastVisibleItem: Item? {
    guard containerVisible else { return nil }
    return self.items.last(where: \.isVisible)
  }
  func lastVisibleItem(where predicate: (Item) -> Bool) -> Item? {
    guard containerVisible else { return nil }
    return self.items.last { $0.isVisible && predicate($0) }
  }
}

extension ItemsContainer where Item: HasVisibility, Item: Equatable {
  func visibleItem(before: Item) -> Item? {
    return self.items.item(before: before, where: \.isVisible)
  }
  func visibleItem(after: Item) -> Item? {
    return self.items.item(after: after, where: \.isVisible)
  }
}


================================================
FILE: Maccy/KeyChord.swift
================================================
import AppKit.NSEvent
import KeyboardShortcuts
import Sauce

enum KeyChord: CaseIterable {
  static var pasteKey: Key { pasteMenuItem?.key ?? Key.v }
  static var pasteKeyModifiers: NSEvent.ModifierFlags { pasteMenuItem?.keyEquivalentModifierMask ?? .command }
  private static var pasteMenuItem: NSMenuItem? {
    NSApp.mainMenu?.items
      .flatMap { $0.submenu?.items ?? [] }
      .first { $0.action == #selector(NSText.paste) }
  }

  static var deleteKey: Key? { Sauce.shared.key(shortcut: .delete) }
  static var deleteModifiers: NSEvent.ModifierFlags? { KeyboardShortcuts.Shortcut(name: .delete)?.modifiers }

  static var pinKey: Key? { Sauce.shared.key(shortcut: .pin) }
  static var pinModifiers: NSEvent.ModifierFlags? { KeyboardShortcuts.Shortcut(name: .pin)?.modifiers }

  static var previewKey: Key? { Sauce.shared.key(shortcut: .togglePreview) }
  static var previewModifiers: NSEvent.ModifierFlags? { KeyboardShortcuts.Shortcut(name: .togglePreview)?.modifiers }

  case clearHistory
  case clearHistoryAll
  case clearSearch
  case deleteCurrentItem
  case deleteOneCharFromSearch
  case deleteLastWordFromSearch
  case ignored
  case moveToNext
  case moveToLast
  case moveToPrevious
  case moveToFirst
  case extendToNext
  case extendToLast
  case extendToPrevious
  case extendToFirst
  case openPreferences
  case pinOrUnpin
  case selectCurrentItem
  case close
  case togglePreview
  case unknown

  init(_ event: NSEvent?) {
    guard let event, event.type == .keyDown else {
      self = .unknown
      return
    }

    let modifierFlags = event.modifierFlags
      .intersection(.deviceIndependentFlagsMask)
      .subtracting([.capsLock, .numericPad, .function])
    var key: Key?

    if KeyboardLayout.current.commandSwitchesToQWERTY, modifierFlags.contains(.command) {
      key = Key(QWERTYKeyCode: Int(event.keyCode))
    } else {
      key = Sauce.shared.key(for: Int(event.keyCode))
    }

    guard let key else {
      self = .unknown
      return
    }

    self.init(key, modifierFlags)
  }

  // swiftlint:disable:next cyclomatic_complexity function_body_length
  init(_ key: Key, _ modifierFlags: NSEvent.ModifierFlags) {
    switch (key, modifierFlags) {
    case (.delete, [.command, .option]):
      self = .clearHistory
    case (.delete, [.command, .option, .shift]):
      self = .clearHistoryAll
    case (.u, [.control]):
      self = .clearSearch
    case (KeyChord.deleteKey, KeyChord.deleteModifiers):
      self = .deleteCurrentItem
    case (.h, [.control]):
      self = .deleteOneCharFromSearch
    case (.w, [.control]):
      self = .deleteLastWordFromSearch
    case (.downArrow, [.shift]),
         (.n, [.control, .shift]):
      self = AppState.shared.multiSelectionEnabled ? .extendToNext : .moveToNext
    case (.downArrow, []),
         (.n, [.control]),
         (.j, [.control]):
      self = .moveToNext
    case (.downArrow, [.command, .shift]),
         (.downArrow, [.option, .shift]),
         (.n, [.control, .option, .shift]):
      self = AppState.shared.multiSelectionEnabled ? .extendToLast : .moveToLast
    case (.downArrow, _) where modifierFlags.contains(.command) || modifierFlags.contains(.option),
         (.n, [.control, .option]),
         (.pageDown, []):
      self = .moveToLast
    case (.upArrow, [.shift]),
         (.p, [.control, .shift]):
      self = AppState.shared.multiSelectionEnabled ? .extendToPrevious : .moveToPrevious
    case (.upArrow, []),
         (.p, [.control]),
         (.k, [.control]):
      self = .moveToPrevious
    case (.upArrow, [.command, .shift]),
         (.upArrow, [.option, .shift]),
         (.p, [.control, .option, .shift]):
      self = AppState.shared.multiSelectionEnabled ? .extendToFirst : .moveToFirst
    case (.upArrow, _) where modifierFlags.contains(.command) || modifierFlags.contains(.option),
         (.p, [.control, .option]),
         (.pageUp, []):
      self = .moveToFirst
    case (KeyChord.pinKey, KeyChord.pinModifiers):
      self = .pinOrUnpin
    case (.comma, [.command]):
      self = .openPreferences
    case (.return, _),
         (.keypadEnter, _):
      self = .selectCurrentItem
    case (.escape, _):
      self = .close
    case (KeyChord.previewKey, KeyChord.previewModifiers):
      self = .togglePreview
    case (_, _) where !modifierFlags.isDisjoint(with: [.command, .control, .option]):
      self = .ignored
    default:
      self = .unknown
    }
  }
}


================================================
FILE: Maccy/KeyShortcut.swift
================================================
import AppKit.NSEvent
import Defaults
import Sauce

struct KeyShortcut: Identifiable {
  static func create(character: String) -> [KeyShortcut] {
    let key = Key(character: character, virtualKeyCode: nil)
    return [
      KeyShortcut(key: key),
      KeyShortcut(key: key, modifierFlags: [.option]),
      KeyShortcut(key: key, modifierFlags: [Defaults[.pasteByDefault] ? .command : .option, .shift])
    ]
  }

  let id = UUID()

  var key: Key?
  var modifierFlags: NSEvent.ModifierFlags = [.command]

  var description: String {
    guard let key, let character = Sauce.shared.currentASCIICapableCharacter(
      for: Int(Sauce.shared.keyCode(for: key)),
      cocoaModifiers: []
    ) else {
      return ""
    }

    return "\(modifierFlags.description)\(character.capitalized)"
  }

  func isVisible(_ all: [KeyShortcut], _ pressedModifierFlags: NSEvent.ModifierFlags) -> Bool {
    if all.count == 1 {
      return true
    }

    if modifierFlags == [.command], pressedModifierFlags.isEmpty {
      return true
    }

    if modifierFlags == [.command], !pressedModifierFlags.isEmpty,
       !all.contains(where: { $0.id != id && $0.modifierFlags == pressedModifierFlags }) {
      return true
    }

    return modifierFlags == pressedModifierFlags
  }
}


================================================
FILE: Maccy/KeyboardLayout.swift
================================================
import Carbon
import Sauce

class KeyboardLayout {
  static var current: KeyboardLayout { KeyboardLayout() }

  // Dvorak - QWERTY ⌘ (https://github.com/p0deje/Maccy/issues/482)
  // bépo 1.1 - Azerty ⌘ (https://github.com/p0deje/Maccy/issues/520)
  var commandSwitchesToQWERTY: Bool { localizedName.hasSuffix("⌘") }

  var localizedName: String {
    if let value = TISGetInputSourceProperty(inputSource, kTISPropertyLocalizedName) {
      return Unmanaged<CFString>.fromOpaque(value).takeUnretainedValue() as String
    } else {
      return ""
    }
  }

  private var inputSource: TISInputSource!

  init() {
    inputSource = TISCopyCurrentKeyboardLayoutInputSource().takeUnretainedValue()
  }
}


================================================
FILE: Maccy/Maccy.entitlements
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
	<key>com.apple.security.files.user-selected.read-only</key>
	<true/>
	<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
	<array>
    	<string>$(PRODUCT_BUNDLE_IDENTIFIER)-spks</string>
    	<string>$(PRODUCT_BUNDLE_IDENTIFIER)-spki</string>
	</array>
</dict>
</plist>


================================================
FILE: Maccy/MaccyApp.swift
================================================
import SwiftUI

@main
struct MaccyApp: App {
  @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

  // It's impossible to create sceneless application,
  // so we are hacking this around by creating a menubar
  // scene that is always hidden.
  @State private var hiddenMenu: Bool = false

  var body: some Scene {
    MenuBarExtra("", isInserted: $hiddenMenu) {
      EmptyView()
    }
  }
}


================================================
FILE: Maccy/MenuIcon.swift
================================================
import AppKit
import Defaults

enum MenuIcon: String, CaseIterable, Identifiable, Defaults.Serializable {
  case maccy
  case clipboard
  case scissors
  case paperclip

  var id: Self { self }

  var image: NSImage {
    switch self {
    case .maccy:
      return NSImage(named: .maccyStatusBar)!
    case .clipboard:
      return NSImage(named: .clipboard)!
    case .scissors:
      return NSImage(named: .scissors)!
    case .paperclip:
      return NSImage(named: .paperclip)!
    }
  }
}


================================================
FILE: Maccy/Models/HistoryItem.swift
================================================
import AppKit
import Defaults
import Sauce
import SwiftData
import Vision

@Model
class HistoryItem {
  static var supportedPins: Set<String> {
    // "a" reserved for select all
    // "q" reserved for quit
    // "v" reserved for paste
    // "w" reserved for close window
    // "z" reserved for undo/redo
    var keys = Set([
      "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
      "m", "n", "o", "p", "r", "s", "t", "u", "x", "y"
    ])

    if let deleteKey = KeyChord.deleteKey,
       let character = Sauce.shared.character(for: Int(deleteKey.QWERTYKeyCode), cocoaModifiers: []) {
      keys.remove(character)
    }

    if let pinKey = KeyChord.pinKey,
       let character = Sauce.shared.character(for: Int(pinKey.QWERTYKeyCode), cocoaModifiers: []) {
      keys.remove(character)
    }
    if let previewKey = KeyChord.previewKey,
       let character = Sauce.shared.character(for: Int(previewKey.QWERTYKeyCode), cocoaModifiers: []) {
      keys.remove(character)
    }

    return keys
  }

  @MainActor
  static var availablePins: [String] {
    let descriptor = FetchDescriptor<HistoryItem>(
      predicate: #Predicate { $0.pin != nil }
    )
    let pins = try? Storage.shared.context.fetch(descriptor).compactMap({ $0.pin })
    let assignedPins = Set(pins ?? [])
    return Array(supportedPins.subtracting(assignedPins))
  }

  @MainActor
  static var randomAvailablePin: String { availablePins.randomElement() ?? "" }

  private static let transientTypes: [String] = [
    NSPasteboard.PasteboardType.modified.rawValue,
    NSPasteboard.PasteboardType.fromMaccy.rawValue,
    NSPasteboard.PasteboardType.linkPresentationMetadata.rawValue,
    NSPasteboard.PasteboardType.customWebKitPasteboardData.rawValue,
    NSPasteboard.PasteboardType.source.rawValue,
    NSPasteboard.PasteboardType.customChromiumWebData.rawValue,
    NSPasteboard.PasteboardType.chromiumSourceUrl.rawValue,
    NSPasteboard.PasteboardType.chromiumSourceToken.rawValue,
    NSPasteboard.PasteboardType.notesRichText.rawValue
  ]

  var application: String?
  var firstCopiedAt: Date = Date.now
  var lastCopiedAt: Date = Date.now
  var numberOfCopies: Int = 1
  var pin: String?
  var title = ""

  @Relationship(deleteRule: .cascade, inverse: \HistoryItemContent.item)
  var contents: [HistoryItemContent] = []

  init(contents: [HistoryItemContent] = []) {
    self.firstCopiedAt = firstCopiedAt
    self.lastCopiedAt = lastCopiedAt
    self.contents = contents
  }

  func supersedes(_ item: HistoryItem) -> Bool {
    return item.contents
      .filter { content in
        !Self.transientTypes.contains(content.type)
      }
      .allSatisfy { content in
        contents.contains(where: { $0.type == content.type && $0.value == content.value })
      }
  }

  func generateTitle() -> String {
    guard image == nil else {
      Task {
        self.performTextRecognition()
      }
      return ""
    }

    // 1k characters is trade-off for performance
    var title = previewableText.shortened(to: 1_000)

    if Defaults[.showSpecialSymbols] {
      if let range = title.range(of: "^ +", options: .regularExpression) {
        title = title.replacingOccurrences(of: " ", with: "·", range: range)
      }
      if let range = title.range(of: " +$", options: .regularExpression) {
        title = title.replacingOccurrences(of: " ", with: "·", range: range)
      }
      title = title
        .replacingOccurrences(of: "\n", with: "⏎")
        .replacingOccurrences(of: "\t", with: "⇥")
    } else {
      title = title.trimmingCharacters(in: .whitespacesAndNewlines)
    }

    return title
  }

  var previewableText: String {
    if !fileURLs.isEmpty {
      fileURLs
        .compactMap { $0.absoluteString.removingPercentEncoding }
        .joined(separator: "\n")
    } else if let text = text, !text.isEmpty {
      text
    } else if let rtf = rtf, !rtf.string.isEmpty {
      rtf.string
    } else if let html = html, !html.string.isEmpty {
      html.string
    } else {
      title
    }
  }

  var fileURLs: [URL] {
    guard !universalClipboardText else {
      return []
    }

    return allContentData([.fileURL])
      .compactMap { URL(dataRepresentation: $0, relativeTo: nil, isAbsolute: true) }
  }

  var htmlData: Data? { contentData([.html]) }
  var html: NSAttributedString? {
    guard let data = htmlData else {
      return nil
    }

    return NSAttributedString(html: data, documentAttributes: nil)
  }

  var imageData: Data? {
    var data: Data?
    data = contentData([.tiff, .png, .jpeg, .heic])
    if data == nil, universalClipboardImage, let url = fileURLs.first {
      data = try? Data(contentsOf: url)
    }

    return data
  }

  var image: NSImage? {
    guard let data = imageData else {
      return nil
    }

    return NSImage(data: data)
  }

  var rtfData: Data? { contentData([.rtf]) }
  var rtf: NSAttributedString? {
    guard let data = rtfData else {
      return nil
    }

    return NSAttributedString(rtf: data, documentAttributes: nil)
  }

  var text: String? {
    guard let data = contentData([.string]) else {
      return nil
    }

    return String(data: data, encoding: .utf8)
  }

  var modified: Int? {
    guard let data = contentData([.modified]),
          let modified = String(data: data, encoding: .utf8) else {
      return nil
    }

    return Int(modified)
  }

  var fromMaccy: Bool { contentData([.fromMaccy]) != nil }
  var universalClipboard: Bool { contentData([.universalClipboard]) != nil }

  private var universalClipboardImage: Bool { universalClipboard && fileURLs.first?.pathExtension == "jpeg" }
  private var universalClipboardText: Bool {
    universalClipboard && contentData([.html, .tiff, .png, .jpeg, .rtf, .string, .heic]) != nil
  }

  private func contentData(_ types: [NSPasteboard.PasteboardType]) -> Data? {
    let content = contents.first(where: { content in
      return types.contains(NSPasteboard.PasteboardType(content.type))
    })

    return content?.value
  }

  private func allContentData(_ types: [NSPasteboard.PasteboardType]) -> [Data] {
    return contents
      .filter { types.contains(NSPasteboard.PasteboardType($0.type)) }
      .compactMap { $0.value }
  }

  private func performTextRecognition() {
    guard let cgImage = image?.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
      return
    }

    let requestHandler = VNImageRequestHandler(cgImage: cgImage)
    let request = VNRecognizeTextRequest(completionHandler: recognizeTextHandler)
    request.recognitionLevel = .fast

    do {
      try requestHandler.perform([request])
    } catch {
      print("Unable to perform the request: \(error).")
    }
  }

  private func recognizeTextHandler(request: VNRequest, error: Error?) {
    guard let observations = request.results as? [VNRecognizedTextObservation] else {
      return
    }

    let recognizedStrings = observations.compactMap { observation in
      return observation.topCandidates(1).first?.string
    }

    self.title = recognizedStrings.joined(separator: "\n")
  }
}


================================================
FILE: Maccy/Models/HistoryItemContent.swift
================================================
import Foundation
import SwiftData

@Model
class HistoryItemContent {
  var type: String = ""
  var value: Data?

  @Relationship
  var item: HistoryItem?

  init(type: String, value: Data? = nil) {
    self.type = type
    self.value = value
  }
}


================================================
FILE: Maccy/Notifier.swift
================================================
import AppKit
import UserNotifications

class Notifier {
  private static var center: UNUserNotificationCenter { UNUserNotificationCenter.current() }

  static func authorize() {
    center.requestAuthorization(options: [.alert, .sound]) { _, error in
      if error != nil {
        NSLog("Failed to authorize notifications: \(String(describing: error))")
      }
    }
  }

  static func notify(body: String?, sound: NSSound?) {
    guard let body else { return }

    authorize()

    center.getNotificationSettings { settings in
      guard (settings.authorizationStatus == .authorized) ||
            (settings.authorizationStatus == .provisional) else { return }

      let content = UNMutableNotificationContent()
      if settings.alertSetting == .enabled {
        content.body = body
      }

      let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
      center.add(request) { error in
        if error != nil {
          NSLog("Failed to deliver notification: \(String(describing: error))")
        } else {
          if settings.soundSetting == .enabled {
            sound?.play()
          }
        }
      }
    }
  }
}


================================================
FILE: Maccy/Observables/AppState.swift
================================================
import AppKit
import Defaults
import Foundation
import Settings
import SwiftUI

@Observable
class AppState: Sendable {
  static let shared = AppState(history: History.shared, footer: Footer())

  let multiSelectionEnabled = false

  var appDelegate: AppDelegate?
  var popup: Popup
  var history: History
  var footer: Footer
  var navigator: NavigationManager
  var preview: SlideoutController

  var searchVisible: Bool {
    if !Defaults[.showSearch] { return false }
    switch Defaults[.searchVisibility] {
    case .always: return true
    case .duringSearch: return !history.searchQuery.isEmpty
    }
  }

  var menuIconText: String {
    var title = history.unpinnedItems.first?.text.shortened(to: 100)
      .trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
    title.unicodeScalars.removeAll(where: CharacterSet.newlines.contains)
    return title.shortened(to: 20)
  }

  private let about = About()
  private var settingsWindowController: SettingsWindowController?

  init(history: History, footer: Footer) {
    self.history = history
    self.footer = footer
    popup = Popup()
    navigator = NavigationManager(history: history, footer: footer)
    preview = SlideoutController(
      onContentResize: { contentWidth in
        Defaults[.windowSize].width = contentWidth
      },
      onSlideoutResize: { previewWidth in
        Defaults[.previewWidth] = previewWidth
      })
    preview.contentWidth = Defaults[.windowSize].width
    preview.slideoutWidth = Defaults[.previewWidth]
  }

  @MainActor
  func select() {
    if !navigator.selection.isEmpty {
      if navigator.isMultiSelectInProgress {
        navigator.isManualMultiSelect = false
        history.startPasteStack(selection: &navigator.selection)
      } else {
        history.select(navigator.selection.first)
      }
    } else if let item = footer.selectedItem {
      // TODO: Use item.suppressConfirmation, but it's not updated!
      if item.confirmation != nil, Defaults[.suppressClearAlert] == false {
        item.showConfirmation = true
      } else {
        item.action()
      }
    } else {
      Clipboard.shared.copy(history.searchQuery)
      history.searchQuery = ""
    }
  }

  @MainActor
  func togglePin() {
    withTransaction(Transaction()) {
      navigator.selection.forEach { _, item in
        history.togglePin(item)
      }
    }
  }

  @MainActor
  func removePasteStack() {
    history.interruptPasteStack()
    navigator.highlightFirst()
  }

  @MainActor
  func deleteSelection() {
    guard let leadItem = navigator.leadHistoryItem else { return }
    let nextUnselectedItem = history.visibleItems.nearest(to: leadItem) { !$0.isSelected }

    withTransaction(Transaction()) {
      navigator.selection.forEach { _, item in
        history.delete(item)
      }
      navigator.select(item: nextUnselectedItem)
    }
  }

  func openAbout() {
    about.openAbout(nil)
  }

  @MainActor
  func openPreferences() { // swiftlint:disable:this function_body_length
    if settingsWindowController == nil {
      settingsWindowController = SettingsWindowController(
        panes: [
          Settings.Pane(
            identifier: Settings.PaneIdentifier.general,
            title: NSLocalizedString("Title", tableName: "GeneralSettings", comment: ""),
            toolbarIcon: NSImage.gearshape!
          ) {
            GeneralSettingsPane()
          },
          Settings.Pane(
            identifier: Settings.PaneIdentifier.storage,
            title: NSLocalizedString("Title", tableName: "StorageSettings", comment: ""),
            toolbarIcon: NSImage.externaldrive!
          ) {
            StorageSettingsPane()
          },
          Settings.Pane(
            identifier: Settings.PaneIdentifier.appearance,
            title: NSLocalizedString("Title", tableName: "AppearanceSettings", comment: ""),
            toolbarIcon: NSImage.paintpalette!
          ) {
            AppearanceSettingsPane()
          },
          Settings.Pane(
            identifier: Settings.PaneIdentifier.pins,
            title: NSLocalizedString("Title", tableName: "PinsSettings", comment: ""),
            toolbarIcon: NSImage.pincircle!
          ) {
            PinsSettingsPane()
              .environment(self)
              .modelContainer(Storage.shared.container)
          },
          Settings.Pane(
            identifier: Settings.PaneIdentifier.ignore,
            title: NSLocalizedString("Title", tableName: "IgnoreSettings", comment: ""),
            toolbarIcon: NSImage.nosign!
          ) {
            IgnoreSettingsPane()
          },
          Settings.Pane(
            identifier: Settings.PaneIdentifier.advanced,
            title: NSLocalizedString("Title", tableName: "AdvancedSettings", comment: ""),
            toolbarIcon: NSImage.gearshape2!
          ) {
            AdvancedSettingsPane()
          }
        ]
      )
    }
    settingsWindowController?.show()
    settingsWindowController?.window?.orderFrontRegardless()
  }

  func quit() {
    NSApp.terminate(self)
  }
}


================================================
FILE: Maccy/Observables/Footer.swift
================================================
import Defaults
import SwiftUI

@Observable
class Footer: ItemsContainer {
  var items: [FooterItem] = []

  var selectedItem: FooterItem? {
    willSet {
      selectedItem?.isSelected = false
      newValue?.isSelected = true
    }
  }

  var suppressClearAlert = Binding<Bool>(
    get: { Defaults[.suppressClearAlert] },
    set: { Defaults[.suppressClearAlert] = $0 }
  )

  private var showFooter: Bool {
    return Defaults[.showFooter]
  }
  var containerVisible: Bool {
    return showFooter
  }

  init() { // swiftlint:disable:this function_body_length
    items = [
      FooterItem(
        title: "clear",
        shortcuts: [KeyShortcut(key: .delete, modifierFlags: [.command, .option])],
        help: "clear_tooltip",
        confirmation: .init(
          message: "clear_alert_message",
          comment: "clear_alert_comment",
          confirm: "clear_alert_confirm",
          cancel: "clear_alert_cancel"
        ),
        suppressConfirmation: suppressClearAlert
      ) {
        Task { @MainActor in
          AppState.shared.history.clear()
        }
      },
      FooterItem(
        title: "clear_all",
        shortcuts: [KeyShortcut(key: .delete, modifierFlags: [.command, .option, .shift])],
        help: "clear_all_tooltip",
        confirmation: .init(
          message: "clear_alert_message",
          comment: "clear_alert_comment",
          confirm: "clear_alert_confirm",
          cancel: "clear_alert_cancel"
        ),
        suppressConfirmation: suppressClearAlert
      ) {
        Task { @MainActor in
          AppState.shared.history.clearAll()
        }
      },
      FooterItem(
        title: "preferences",
        shortcuts: [KeyShortcut(key: .comma)]
      ) {
        Task { @MainActor in
          AppState.shared.openPreferences()
        }
      },
      FooterItem(
        title: "about",
        help: "about_tooltip"
      ) {
        AppState.shared.openAbout()
      },
      FooterItem(
        title: "quit",
        shortcuts: [KeyShortcut(key: .q)],
        help: "quit_tooltip"
      ) {
        AppState.shared.quit()
      }
    ]
  }
}


================================================
FILE: Maccy/Observables/FooterItem.swift
================================================
import SwiftUI

@Observable
class FooterItem: Equatable, Identifiable, HasVisibility {
  struct Confirmation {
    var message: LocalizedStringKey
    var comment: LocalizedStringKey
    var confirm: LocalizedStringKey
    var cancel: LocalizedStringKey
  }

  static func == (lhs: FooterItem, rhs: FooterItem) -> Bool {
    return lhs.id == rhs.id
  }

  let id = UUID()

  var title: String
  var shortcuts: [KeyShortcut] = []
  var help: LocalizedStringKey?
  var isSelected: Bool = false
  var confirmation: Confirmation?
  var showConfirmation: Bool = false
  var suppressConfirmation: Binding<Bool>?
  var isVisible: Bool = true
  var action: () -> Void

  init(
    title: String,
    shortcuts: [KeyShortcut] = [],
    help: LocalizedStringKey? = nil,
    confirmation: Confirmation? = nil,
    suppressConfirmation: Binding<Bool>? = nil,
    action: @escaping () -> Void
  ) {
    self.title = title
    self.shortcuts = shortcuts
    self.help = help
    self.confirmation = confirmation
    self.suppressConfirmation = suppressConfirmation
    self.action = action
  }
}


================================================
FILE: Maccy/Observables/History.swift
================================================
// swiftlint:disable file_length
import AppKit.NSRunningApplication
import Defaults
import Foundation
import Logging
import Observation
import Sauce
import Settings
import SwiftData

@Observable
class History: ItemsContainer { // swiftlint:disable:this type_body_length
  static let shared = History()
  let logger = Logger(label: "org.p0deje.Maccy")

  var items: [HistoryItemDecorator] = []
  var pasteStack: PasteStack?

  var pinnedItems: [HistoryItemDecorator] { items.filter(\.isPinned) }
  var unpinnedItems: [HistoryItemDecorator] { items.filter(\.isUnpinned) }

  var searchQuery: String = "" {
    didSet {
      throttler.throttle { [self] in
        updateItems(search.search(string: searchQuery, within: all))

        if searchQuery.isEmpty {
          AppState.shared.navigator.select(item: unpinnedItems.first)
        } else {
          AppState.shared.navigator.highlightFirst()
        }

        AppState.shared.popup.needsResize = true
      }
    }
  }

  var pressedShortcutItem: HistoryItemDecorator? {
    guard let event = NSApp.currentEvent else {
      return nil
    }

    let modifierFlags = event.modifierFlags
      .intersection(.deviceIndependentFlagsMask)
      .subtracting(.capsLock)

    guard HistoryItemAction(modifierFlags) != .unknown else {
      return nil
    }

    let key = Sauce.shared.key(for: Int(event.keyCode))
    return items.first { $0.shortcuts.contains(where: { $0.key == key }) }
  }

  private let search = Search()
  private let sorter = Sorter()
  private let throttler = Throttler(minimumDelay: 0.2)

  @ObservationIgnored
  private var sessionLog: [Int: HistoryItem] = [:]

  // The distinction between `all` and `items` is the following:
  // - `all` stores all history items, even the ones that are currently hidden by a search
  // - `items` stores only visible history items, updated during a search
  @ObservationIgnored
  var all: [HistoryItemDecorator] = []

  init() {
    Task {
      for await _ in Defaults.updates(.pasteByDefault, initial: false) {
        updateShortcuts()
      }
    }

    Task {
      for await _ in Defaults.updates(.sortBy, initial: false) {
        try? await load()
      }
    }

    Task {
      for await _ in Defaults.updates(.pinTo, initial: false) {
        try? await load()
      }
    }

    Task {
      for await _ in Defaults.updates(.showSpecialSymbols, initial: false) {
        for item in items {
          await updateTitle(item: item, title: item.item.generateTitle())
        }
      }
    }

    Task {
      for await _ in Defaults.updates(.imageMaxHeight, initial: false) {
        for item in items {
          await item.cleanupImages()
        }
      }
    }
  }

  @MainActor
  func load() async throws {
    let descriptor = FetchDescriptor<HistoryItem>()
    let results = try Storage.shared.context.fetch(descriptor)
    all = sorter.sort(results).map { HistoryItemDecorator($0) }
    items = all

    limitHistorySize(to: Defaults[.size])

    updateShortcuts()
    // Ensure that panel size is proper *after* loading all items.
    Task {
      AppState.shared.popup.needsResize = true
    }
  }

  @MainActor
  private func limitHistorySize(to maxSize: Int) {
    let unpinned = all.filter(\.isUnpinned)
    if unpinned.count >= maxSize {
      unpinned[maxSize...].forEach(delete)
    }
  }

  @MainActor
  func insertIntoStorage(_ item: HistoryItem) throws {
    logger.info("Inserting item with id '\(item.title)'")
    Storage.shared.context.insert(item)
    Storage.shared.context.processPendingChanges()
    try? Storage.shared.context.save()
  }

  @discardableResult
  @MainActor
  func add(_ item: HistoryItem) -> HistoryItemDecorator {
    if #available(macOS 15.0, *) {
      try? History.shared.insertIntoStorage(item)
    } else {
      // On macOS 14 the history item needs to be inserted into storage directly after creating it.
      // It was already inserted after creation in Clipboard.swift
    }

    var removedItemIndex: Int?
    if let existingHistoryItem = findSimilarItem(item) {
      if isModified(item) == nil {
        item.contents = existingHistoryItem.contents
      }
      item.firstCopiedAt = existingHistoryItem.firstCopiedAt
      item.numberOfCopies += existingHistoryItem.numberOfCopies
      item.pin = existingHistoryItem.pin
      item.title = existingHistoryItem.title
      if !item.fromMaccy {
        item.application = existingHistoryItem.application
      }
      logger.info("Removing duplicate item '\(item.title)'")
      Storage.shared.context.delete(existingHistoryItem)
      removedItemIndex = all.firstIndex(where: { $0.item == existingHistoryItem })
      if let removedItemIndex {
        all.remove(at: removedItemIndex)
      }
    } else {
      Task {
        Notifier.notify(body: item.title, sound: .write)
      }
    }

    // Remove exceeding items. Do this after the item is added to avoid removing something
    // if a duplicate was found as then the size already stayed the same.
    limitHistorySize(to: Defaults[.size] - 1)

    sessionLog[Clipboard.shared.changeCount] = item

    var itemDecorator: HistoryItemDecorator
    if let pin = item.pin {
      itemDecorator = HistoryItemDecorator(item, shortcuts: KeyShortcut.create(character: pin))
      // Keep pins in the same place.
      if let removedItemIndex {
        all.insert(itemDecorator, at: removedItemIndex)
      }
    } else {
      itemDecorator = HistoryItemDecorator(item)

      let sortedItems = sorter.sort(all.map(\.item) + [item])
      if let index = sortedItems.firstIndex(of: item) {
        all.insert(itemDecorator, at: index)
      }

      items = all
      updateUnpinnedShortcuts()
      AppState.shared.popup.needsResize = true
    }

    return itemDecorator
  }

  @MainActor
  private func withLogging(_ msg: String, _ block: () throws -> Void) rethrows {
    func dataCounts() -> String {
      let historyItemCount = try? Storage.shared.context.fetchCount(FetchDescriptor<HistoryItem>())
      let historyContentCount = try? Storage.shared.context.fetchCount(FetchDescriptor<HistoryItemContent>())
      return "HistoryItem=\(historyItemCount ?? 0) HistoryItemContent=\(historyContentCount ?? 0)"
    }

    logger.info("\(msg) Before: \(dataCounts())")
    try? block()
    logger.info("\(msg) After: \(dataCounts())")
  }

  @MainActor
  func clear() {
    withLogging("Clearing history") {
      all.forEach { item in
        if item.isUnpinned {
          cleanup(item)
        }
      }
      all.removeAll(where: \.isUnpinned)
      sessionLog.removeValues { $0.pin == nil }
      items = all

      try? Storage.shared.context.transaction {
        try? Storage.shared.context.delete(
          model: HistoryItem.self,
          where: #Predicate { $0.pin == nil }
        )
        try? Storage.shared.context.delete(
          model: HistoryItemContent.self,
          where: #Predicate { $0.item?.pin == nil }
        )
      }
      Storage.shared.context.processPendingChanges()
      try? Storage.shared.context.save()
    }

    Clipboard.shared.clear()
    AppState.shared.popup.close()
    Task {
      AppState.shared.popup.needsResize = true
    }
  }

  @MainActor
  func clearAll() {
    withLogging("Clearing all history") {
      all.forEach { item in
        cleanup(item)
      }
      all.removeAll()
      sessionLog.removeAll()
      items = all

      try? Storage.shared.context.delete(model: HistoryItem.self)
      Storage.shared.context.processPendingChanges()
      try? Storage.shared.context.save()
    }

    Clipboard.shared.clear()
    AppState.shared.popup.close()
    Task {
      AppState.shared.popup.needsResize = true
    }
  }

  @MainActor
  func delete(_ item: HistoryItemDecorator?) {
    guard let item else { return }

    cleanup(item)
    withLogging("Removing history item") {
      Storage.shared.context.delete(item.item)
      Storage.shared.context.processPendingChanges()
      try? Storage.shared.context.save()
    }

    all.removeAll { $0 == item }
    items.removeAll { $0 == item }
    sessionLog.removeValues { $0 == item.item }

    updateUnpinnedShortcuts()
    Task {
      AppState.shared.popup.needsResize = true
    }
  }

  @MainActor
  private func cleanup(_ item: HistoryItemDecorator) {
    item.cleanupImages()
  }

  private func currentModifierFlags() -> NSEvent.ModifierFlags {
    return NSApp.currentEvent?.modifierFlags
      .intersection(.deviceIndependentFlagsMask)
      .subtracting([.capsLock, .numericPad, .function]) ?? []
  }

  @MainActor
  func select(_ item: HistoryItemDecorator?) {
    guard let item else {
      return
    }

    let modifierFlags = currentModifierFlags()

    if modifierFlags.isEmpty {
      AppState.shared.popup.close()
      Clipboard.shared.copy(item.item, removeFormatting: Defaults[.removeFormattingByDefault])
      if Defaults[.pasteByDefault] {
        Clipboard.shared.paste()
      }
    } else {
      switch HistoryItemAction(modifierFlags) {
      case .copy:
        AppState.shared.popup.close()
        Clipboard.shared.copy(item.item)
      case .paste:
        AppState.shared.popup.close()
        Clipboard.shared.copy(item.item)
        Clipboard.shared.paste()
      case .pasteWithoutFormatting:
        AppState.shared.popup.close()
        Clipboard.shared.copy(item.item, removeFormatting: true)
        Clipboard.shared.paste()
      case .unknown:
        return
      }
    }

    Task {
      searchQuery = ""
    }
  }

  @MainActor
  func startPasteStack(selection: inout Selection<HistoryItemDecorator>) {
    guard AppState.shared.multiSelectionEnabled else { return }
    guard let item = selection.first else { return }
    PasteStack.initializeIfNeeded()

    let modifierFlags = currentModifierFlags()

    let stack = PasteStack(items: selection.items, modifierFlags: modifierFlags)
    pasteStack = stack

    logger.info("Initialising PasteStack with \(stack.items.count) items")
    logger.info("Copying \(item.item.title) from PasteStack")

    if modifierFlags.isEmpty {
      AppState.shared.popup.close()
      Clipboard.shared.copy(item.item, removeFormatting: Defaults[.removeFormattingByDefault])
    } else {
      switch HistoryItemAction(modifierFlags) {
      case .copy:
        AppState.shared.popup.close()
        Clipboard.shared.copy(item.item)
      case .paste:
        AppState.shared.popup.close()
        Clipboard.shared.copy(item.item)
      case .pasteWithoutFormatting:
        AppState.shared.popup.close()
        Clipboard.shared.copy(item.item, removeFormatting: true)
        Clipboard.shared.paste()
      case .unknown:
        return
      }
    }

    Task {
      searchQuery = ""
    }
  }

  func handlePasteStack() {
    guard let stack = pasteStack else {
      return
    }

    guard let pasted = stack.items.first else {
      pasteStack = nil
      logger.info("PasteStack is empty")
      return
    }

    logger.info("PasteStack pasted \(pasted.item.title)")

    stack.items.removeFirst()

    guard let item = stack.items.first else {
      pasteStack = nil
      logger.info("PasteStack is empty")
      return
    }

    logger.info("Copying \(item.item.title) from PasteStack. \(stack.items.count) items remaining in stack.")

    Task {
      if stack.modifierFlags.isEmpty {
        await Clipboard.shared.copy(item.item, removeFormatting: Defaults[.removeFormattingByDefault])
      } else {
        switch HistoryItemAction(stack.modifierFlags) {
        case .copy:
          await Clipboard.shared.copy(item.item)
        case .paste:
          await Clipboard.shared.copy(item.item)
        case .pasteWithoutFormatting:
          await Clipboard.shared.copy(item.item, removeFormatting: true)
        case .unknown:
          return
        }
      }
    }
  }

  func interruptPasteStack() {
    guard pasteStack != nil else {
      return
    }
    logger.info("Interrupting PasteStack")
    pasteStack = nil
  }

  @MainActor
  func togglePin(_ item: HistoryItemDecorator?) {
    guard let item else { return }

    item.togglePin()

    let sortedItems = sorter.sort(all.map(\.item))
    if let currentIndex = all.firstIndex(of: item),
       let newIndex = sortedItems.firstIndex(of: item.item) {
      all.remove(at: currentIndex)
      all.insert(item, at: newIndex)
    }

    items = all

    searchQuery = ""
    updateUnpinnedShortcuts()
    if item.isUnpinned {
      AppState.shared.navigator.scrollTarget = item.id
    }
  }

  @MainActor
  private func findSimilarItem(_ item: HistoryItem) -> HistoryItem? {
    let descriptor = FetchDescriptor<HistoryItem>()
    if let all = try? Storage.shared.context.fetch(descriptor) {
      let duplicates = all.filter({ $0 == item || $0.supersedes(item) })
      if duplicates.count > 1 {
        return duplicates.first(where: { $0 != item })
      } else {
        return isModified(item)
      }
    }

    return item
  }

  private func isModified(_ item: HistoryItem) -> HistoryItem? {
    if let modified = item.modified, sessionLog.keys.contains(modified) {
      return sessionLog[modified]
    }

    return nil
  }

  private func updateItems(_ newItems: [Search.SearchResult]) {
    items = newItems.map { result in
      let item = result.object
      item.highlight(searchQuery, result.ranges)

      return item
    }

    updateUnpinnedShortcuts()
  }

  private func updateShortcuts() {
    for item in pinnedItems {
      if let pin = item.item.pin {
        item.shortcuts = KeyShortcut.create(character: pin)
      }
    }

    updateUnpinnedShortcuts()
  }

  @MainActor
  private func updateTitle(item: HistoryItemDecorator, title: String) {
    item.title = title
    item.item.title = title
  }

  private func updateUnpinnedShortcuts() {
    let visibleUnpinnedItems = unpinnedItems.filter(\.isVisible)
    for item in visibleUnpinnedItems {
      item.shortcuts = []
    }

    var index = 1
    for item in visibleUnpinnedItems.prefix(9) {
      item.shortcuts = KeyShortcut.create(character: String(index))
      index += 1
    }
  }
}


================================================
FILE: Maccy/Observables/HistoryItemDecorator.swift
================================================
import AppKit.NSWorkspace
import Defaults
import Foundation
import Observation
import Sauce

@Observable
class HistoryItemDecorator: Identifiable, Hashable, HasVisibility {
  static func == (lhs: HistoryItemDecorator, rhs: HistoryItemDecorator) -> Bool {
    return lhs.id == rhs.id
  }

  static var previewImageSize: NSSize { NSScreen.forPopup?.visibleFrame.size ?? NSSize(width: 2048, height: 1536) }
  static var thumbnailImageSize: NSSize { NSSize(width: 340, height: Defaults[.imageMaxHeight]) }

  let id = UUID()

  var title: String = ""
  var attributedTitle: AttributedString?

  var isVisible: Bool = true
  var selectionIndex: Int = -1
  var isSelected: Bool {
    return selectionIndex != -1
  }
  var shortcuts: [KeyShortcut] = []

  var application: String? {
    if item.universalClipboard {
      return "iCloud"
    }

    guard let bundle = item.application,
      let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundle)
    else {
      return nil
    }

    return url.deletingPathExtension().lastPathComponent
  }

  var hasImage: Bool { item.image != nil }

  var previewImageGenerationTask: Task<(), Error>?
  var thumbnailImageGenerationTask: Task<(), Error>?
  var previewImage: NSImage?
  var thumbnailImage: NSImage?
  var applicationImage: ApplicationImage

  // 10k characters seems to be more than enough on large displays
  var text: String { item.previewableText.shortened(to: 10_000) }

  var isPinned: Bool { item.pin != nil }
  var isUnpinned: Bool { item.pin == nil }

  func hash(into hasher: inout Hasher) {
    // We need to hash title and attributedTitle, so SwiftUI knows it needs to update the view if they chage
    hasher.combine(id)
    hasher.combine(title)
    hasher.combine(attributedTitle)
  }

  private(set) var item: HistoryItem

  init(_ item: HistoryItem, shortcuts: [KeyShortcut] = []) {
    self.item = item
    self.shortcuts = shortcuts
    self.title = item.title
    self.applicationImage = ApplicationImageCache.shared.getImage(item: item)

    synchronizeItemPin()
    synchronizeItemTitle()
  }

  @MainActor
  func ensureThumbnailImage() {
    guard item.image != nil else {
      return
    }
    guard thumbnailImage == nil else {
      return
    }
    guard thumbnailImageGenerationTask == nil else {
      return
    }
    thumbnailImageGenerationTask = Task { [weak self] in
      self?.generateThumbnailImage()
    }
  }

  @MainActor
  func ensurePreviewImage() {
    guard item.image != nil else {
      return
    }
    guard previewImage == nil else {
      return
    }
    guard previewImageGenerationTask == nil else {
      return
    }
    previewImageGenerationTask = Task { [weak self] in
      self?.generatePreviewImage()
    }
  }

  @MainActor
  func asyncGetPreviewImage() async -> NSImage? {
    if let image = previewImage {
      return image
    }
    ensurePreviewImage()
    _ = await previewImageGenerationTask?.result
    return previewImage
  }

  @MainActor
  func cleanupImages() {
    thumbnailImageGenerationTask?.cancel()
    previewImageGenerationTask?.cancel()
    thumbnailImage?.recache()
    previewImage?.recache()
    thumbnailImage = nil
    previewImage = nil
  }

  @MainActor
  private func generateThumbnailImage() {
    guard let image = item.image else {
      return
    }
    thumbnailImage = image.resized(to: HistoryItemDecorator.thumbnailImageSize)
  }

  @MainActor
  private func generatePreviewImage() {
    guard let image = item.image else {
      return
    }
    previewImage = image.resized(to: HistoryItemDecorator.previewImageSize)
  }

  @MainActor
  func sizeImages() {
    generatePreviewImage()
    generateThumbnailImage()
  }

  func highlight(_ query: String, _ ranges: [Range<String.Index>]) {
    guard !query.isEmpty, !title.isEmpty else {
      attributedTitle = nil
      return
    }

    var attributedString = AttributedString(title.shortened(to: 500))
    for range in ranges {
      if let lowerBound = AttributedString.Index(range.lowerBound, within: attributedString),
         let upperBound = AttributedString.Index(range.upperBound, within: attributedString) {
        switch Defaults[.highlightMatch] {
        case .bold:
          attributedString[lowerBound..<upperBound].font = .bold(.body)()
        case .italic:
          attributedString[lowerBound..<upperBound].font = .italic(.body)()
        case .underline:
          attributedString[lowerBound..<upperBound].underlineStyle = .single
        default:
          attributedString[lowerBound..<upperBound].backgroundColor = .findHighlightColor
          attributedString[lowerBound..<upperBound].foregroundColor = .black
        }
      }
    }

    attributedTitle = attributedString
  }

  @MainActor
  func togglePin() {
    if item.pin != nil {
      item.pin = nil
    } else {
      let pin = HistoryItem.randomAvailablePin
      item.pin = pin
    }
  }

  private func synchronizeItemPin() {
    _ = withObservationTracking {
      item.pin
    } onChange: {
      DispatchQueue.main.async {
        if let pin = self.item.pin {
          self.shortcuts = KeyShortcut.create(character: pin)
        }
        self.synchronizeItemPin()
      }
    }
  }

  private func synchronizeItemTitle() {
    _ = withObservationTracking {
      item.title
    } onChange: {
      DispatchQueue.main.async {
        self.title = self.item.title
        self.synchronizeItemTitle()
      }
    }
  }
}


================================================
FILE: Maccy/Observables/ModifierFlags.swift
================================================
import AppKit.NSEvent
import Defaults

@Observable
class ModifierFlags {
  var flags: NSEvent.ModifierFlags = []

  init() {
    NSEvent.addLocalMonitorForEvents(matching: .flagsChanged) { event in
      self.flags = event.modifierFlags.intersection(.deviceIndependentFlagsMask)
      return event
    }
  }
}


================================================
FILE: Maccy/Observables/NavigationManager.swift
================================================
import Foundation
import SwiftUI

@Observable
class NavigationManager { // swiftlint:disable:this type_body_length
  private var history: History
  private var footer: Footer

  init(history: History, footer: Footer) {
    self.history = history
    self.footer = footer
  }

  var selection: Selection<HistoryItemDecorator> = Selection() {
    willSet {
      selection.forEach { _, item in item.selectionIndex = -1 }
      newValue.forEach { index, item in item.selectionIndex = index }
    }
  }

  var scrollTarget: UUID?
  var leadSelection: UUID? {
    if let item = leadHistoryItem {
      return item.id
    }
    if let footerItem = footer.selectedItem {
      return footerItem.id
    }
    return history.pasteStack?.id
  }
  private(set) var leadHistoryItem: HistoryItemDecorator? {
    didSet {
      guard oldValue?.id != leadHistoryItem?.id else { return }

      let preview = AppState.shared.preview
      if leadHistoryItem != nil {
        preview.resetAutoOpenSuppression()
        preview.startAutoOpen()
      } else {
        preview.cancelAutoOpen()
      }
    }
  }

  var pasteStackSelected: Bool {
    return leadSelection != nil && leadSelection == history.pasteStack?.id
  }

  var isManualMultiSelect: Bool = false
  var isMultiSelectInProgress: Bool {
    return isManualMultiSelect || selection.count > 1
  }

  var hoverSelectionWhileKeyboardNavigating: UUID?
  var isKeyboardNavigating: Bool = true {
    didSet {
      if !isKeyboardNavigating && !isMultiSelectInProgress,
         let hoverSelection = hoverSelectionWhileKeyboardNavigating {
        hoverSelectionWhileKeyboardNavigating = nil
        select(id: hoverSelection)
      }
    }
  }

  private func scroll(to id: UUID?, item: HistoryItemDecorator? = nil) {
    scrollTarget = id
  }

  func select(id: UUID) {
    if let item = history.items.first(where: { $0.id == id }) {
      select(item: item, footerItem: nil)
    } else if let item = footer.items.first(where: { $0.id == id }) {
      select(item: nil, footerItem: item)
    } else {
      select(item: nil, footerItem: nil)
    }
  }

  func select(item: HistoryItemDecorator? = nil, footerItem: FooterItem? = nil) {
    withTransaction(Transaction()) {
      selectWithoutScrolling(item: item, footerItem: footerItem)
      scroll(to: item?.id, item: item)
    }
  }

  func addToSelection(item: HistoryItemDecorator) {
    var newSelectionState = selection

    if item.isSelected {
      if newSelectionState.count <= 1 {
        isManualMultiSelect = !isManualMultiSelect
      } else {
        newSelectionState.remove(item)
      }
    } else {
      newSelectionState.add(item)
    }

    withTransaction(Transaction()) {
      selection = newSelectionState
      leadHistoryItem = item
      scrollTarget = leadSelection
    }
  }

  func extendSelection(
    from fromItem: HistoryItemDecorator,
    to toItem: HistoryItemDecorator,
    isRange: Bool
  ) {
    var newSelectionState = selection

    if isRange {
      if let itemRange = history.visibleItems.between(
        from: fromItem,
        to: toItem,
        inOrder: false
      ) {
        newSelectionState = Selection(items: itemRange)
      }
    } else {
      if toItem.isSelected {
        newSelectionState.remove(fromItem)
      } else {
        newSelectionState.add(toItem)
      }
    }

    withTransaction(Transaction()) {
      selection = newSelectionState
      leadHistoryItem = toItem
      scrollTarget = leadSelection
    }
  }

  func selectWithoutScrolling(id: UUID) {
    if let stack = history.pasteStack,
       stack.id == id {
      selectWithoutScrolling(item: nil, footerItem: nil)
    } else if let item = history.items.first(where: { $0.id == id }) {
      if !isMultiSelectInProgress {
        selectWithoutScrolling(item: item, footerItem: nil)
      }
    } else if let item = footer.items.first(where: { $0.id == id }) {
      selectWithoutScrolling(item: nil, footerItem: item)
    } else {
      selectWithoutScrolling(item: nil, footerItem: nil)
    }
  }

  func selectWithoutScrolling(
    item: HistoryItemDecorator? = nil,
    footerItem: FooterItem? = nil
  ) {
    if let item = item {
      selectInHistory(item)
    } else if let footerItem = footerItem {
      selectInFooter(footerItem)
    } else {
      leadHistoryItem = nil
      selection = .init()
      footer.selectedItem = nil
    }
  }

  private func selectInHistory(_ item: HistoryItemDecorator) {
    leadHistoryItem = item
    selection = .init(items: [item])
    footer.selectedItem = nil
  }

  private func selectInFooter(_ item: FooterItem) {
    leadHistoryItem = nil
    if !isMultiSelectInProgress {
      selection = .init()
    }
    footer.selectedItem = item
  }

  private func selectFromKeyboardNavigation(
    item: HistoryItemDecorator? = nil,
    footerItem: FooterItem? = nil
  ) {
    isKeyboardNavigating = true
    isManualMultiSelect = false
    select(item: item, footerItem: footerItem)
  }

  private func extendHistorySelectionFromKeyboardNavigation(
    from fromItem: HistoryItemDecorator,
    to toItem: HistoryItemDecorator,
    isRange: Bool
  ) {
    isKeyboardNavigating = true
    extendSelection(from: fromItem, to: toItem, isRange: isRange)
  }

  func highlightFirst() {
    if let item = history.firstVisibleItem {
      selectFromKeyboardNavigation(item: item)
    } else {
      selectFromKeyboardNavigation(item: nil)
    }
  }

  func highlightPrevious() {
    guard let lead = leadSelection else { return }

    if let historyItem = history.firstVisibleItem(where: { $0.id == lead }) {
      if let nextItem = history.visibleItem(before: historyItem) {
        selectFromKeyboardNavigation(item: nextItem)
      } else if history.pasteStack != nil {
        selectWithoutScrolling(item: nil)
      } else {
        highlightFirst()
      }
    } else if let footerItem = footer.firstVisibleItem(where: { $0.id == lead }) {
      if let nextItem = footer.visibleItem(before: footerItem) {
        selectFromKeyboardNavigation(footerItem: nextItem)
      } else if let nextItem = history.lastVisibleItem {
        selectFromKeyboardNavigation(item: nextItem)
      }
    }
  }

  func highlightNext(allowCycle: Bool = false) {
    guard let lead = leadSelection else { return }

    if leadSelection == history.pasteStack?.id {
      highlightFirst()
      return
    }

    if let historyItem = history.firstVisibleItem(where: { $0.id == lead }) {
      if let nextItem = history.visibleItem(after: historyItem) {
        selectFromKeyboardNavigation(item: nextItem)
      } else if let nextItem = footer.firstVisibleItem {
        selectFromKeyboardNavigation(footerItem: nextItem)
      } else if allowCycle {
        highlightFirst()
      }
    } else if let footerItem = footer.firstVisibleItem(where: { $0.id == lead }) {
      if let nextItem = footer.visibleItem(after: footerItem) {
        selectFromKeyboardNavigation(footerItem: nextItem)
      } else if let nextItem = footer.firstVisibleItem {
        selectFromKeyboardNavigation(footerItem: nextItem)
      } else if allowCycle {
        // End of footer; cycle to the beginning
        highlightFirst()
      }
    }
  }

  func highlightLast() {
    guard let lead = leadSelection else { return }

    if let historyItem = history.firstVisibleItem(where: { $0.id == lead }) {
      if historyItem == history.lastVisibleItem,
         let nextItem = footer.firstVisibleItem {
        selectFromKeyboardNavigation(footerItem: nextItem)
      } else {
        selectFromKeyboardNavigation(item: history.lastVisibleItem)
      }
    } else if footer.selectedItem != nil {
      selectFromKeyboardNavigation(footerItem: footer.lastVisibleItem)
    } else {
      selectFromKeyboardNavigation(footerItem: footer.firstVisibleItem)
    }
  }

  func extendHighlightToNext() {
    if let leadSelection,
       let leadItem = history.firstVisibleItem(where: {$0.id == leadSelection}) {
      guard let nextItem = history.visibleItem(after: leadItem) else { return }
      extendHistorySelectionFromKeyboardNavigation(from: leadItem, to: nextItem, isRange: false)
    } else {
      highlightNext()
    }
  }

  func extendHighlightToPrevious() {
    if let leadSelection,
       let leadItem = history.firstVisibleItem(where: {$0.id == leadSelection}) {
      guard let nextItem = history.visibleItem(before: leadItem) else { return }
      extendHistorySelectionFromKeyboardNavigation(from: leadItem, to: nextItem, isRange: false)
    } else {
      highlightPrevious()
    }
  }

  func extendHighlightToFirst() {
    if let leadSelection,
       let leadItem = history.firstVisibleItem(where: {$0.id == leadSelection}) {
      guard let nextItem = history.firstVisibleItem else { return }
      extendHistorySelectionFromKeyboardNavigation(from: leadItem, to: nextItem, isRange: true)
    } else {
      highlightFirst()
    }
  }

  func extendHighlightToLast() {
    if let leadSelection,
       let leadItem = history.firstVisibleItem(where: {$0.id == leadSelection}) {
      guard let nextItem = history.lastVisibleItem else { return }
      extendHistorySelectionFromKeyboardNavigation(from: leadItem, to: nextItem, isRange: true)
    } else {
      highlightFirst()
    }
  }

}


================================================
FILE: Maccy/Observables/Popup.swift
================================================
import AppKit.NSRunningApplication
import Defaults
import KeyboardShortcuts
import Observation

enum PopupState {
  // Default; shortcut will toggle the popup
  case toggle
  // In this mode, every additional press of the main key
  // will cycle to the next item in the paste history list.
  // Releasing the modifier keys will accept selection and close the popup
  case cycle
  // Transition state when the shortcut is first pressed and
  // we don't know whether we are in "toggle" or "cycle" mode.
  case opening
}

@Observable
class Popup {
  static let verticalSeparatorPadding = 6.0
  static let horizontalSeparatorPadding = 6.0
  static let verticalPadding: CGFloat = 5
  static let horizontalPadding: CGFloat = 5
  static let minimumPreviewHeight: CGFloat = 150

  // Radius used for items inset by the padding. Ensures they visually have the same curvature
  // as the menu.
  static let cornerRadius: CGFloat = if #available(macOS 26.0, *) {
    7
  } else {
    4
  }

  static let itemHeight: CGFloat = if #available(macOS 26.0, *) {
    24
  } else {
    22
  }

  var needsResize = false
  var height: CGFloat = 0
  var headerHeight: CGFloat = 0
  var extraTopHeight: CGFloat = 0
  var extraBottomHeight: CGFloat = 0
  var footerHeight: CGFloat = 0

  private var eventsMonitor: Any?

  private var state: PopupState = .toggle

  init() {
    KeyboardShortcuts.onKeyDown(for: .popup, action: handleFirstKeyDown)
    initEventsMonitor()
  }

  deinit {
    deinitEventsMonitor()
  }

  func initEventsMonitor() {
    guard eventsMonitor == nil else { return }

    self.eventsMonitor = NSEvent.addLocalMonitorForEvents(
      matching: [.flagsChanged, .keyDown],
      handler: handleEvent
    )
  }

  func deinitEventsMonitor() {
    guard let eventsMonitor else { return }

    NSEvent.removeMonitor(eventsMonitor)
  }

  func open(height: CGFloat, at popupPosition: PopupPosition = Defaults[.popupPosition]) {
    AppState.shared.appDelegate?.panel.open(height: height, at: popupPosition)
  }

  func reset() {
    state = .toggle
    KeyboardShortcuts.enable(.popup)
  }

  func close() {
    AppState.shared.appDelegate?.panel.close()  // close() calls reset
  }

  func isClosed() -> Bool {
    AppState.shared.appDelegate?.panel.isPresented != true
  }

  func preferredHeight(for newHeight: CGFloat) -> CGFloat {
    var height = newHeight

    var minimumHeight = 0.0
    // If the preview is non-empty make sure the window accomodates for it to be visible.
    if AppState.shared.preview.state.isOpen && AppState.shared.navigator.leadSelection != nil {
      minimumHeight += Self.minimumPreviewHeight
    }
    minimumHeight = max(headerHeight + Self.verticalPadding, minimumHeight)

    height = max(height, minimumHeight)
    height = min(height, Defaults[.windowSize].height)
    return height
  }

  func resize(height: CGFloat) {
    self.height = height + headerHeight + extraTopHeight + extraBottomHeight + footerHeight
    AppState.shared.appDelegate?.panel.verticallyResize(to: preferredHeight(for: self.height))
    needsResize = false
  }

  private func handleFirstKeyDown() {
    if isClosed() {
      open(height: height)
      state = .opening
      KeyboardShortcuts.disable(.popup)  // Handle events via eventsMonitor. Re-enable on popup close
      return
    }

    // Maccy was not opened via shortcut. We assume toggle mode and close it
    close()
  }

  private func handleEvent(_ event: NSEvent) -> NSEvent? {
    switch event.type {
    case .keyDown:
      return handleKeyDown(event)
    case .flagsChanged:
      return handleFlagsChanged(event)
    default:
      return event
    }
  }

  private func handleKeyDown(_ event: NSEvent) -> NSEvent? {
    if isHotKeyCode(Int(event.keyCode)) {
      if let item = History.shared.pressedShortcutItem {
        AppState.shared.navigator.select(item: item)
        Task { @MainActor in
          AppState.shared.history.select(item)
        }
        return nil
      }

      if state == .opening {
        state = .cycle
        // Next 'if' will highlight next item and then return nil
      }

      if state == .cycle {
        AppState.shared.navigator.highlightNext(allowCycle: true)
        return nil
      }

      if state == .toggle && isHotKeyModifiers(event.modifierFlags) {
        close()
        return nil
      }
    }

    return event
  }

  private func handleFlagsChanged(_ event: NSEvent) -> NSEvent? {
    // If we are in cycle mode, releasing modifiers triggers a selection
    if state == .cycle && allModifiersReleased(event) {
      DispatchQueue.main.async {
        AppState.shared.select()
      }
      return nil
    }

    // Otherwise if in opening mode, enter toggle mode
    if state == .opening && allModifiersReleased(event) {
      state = .toggle
      return event
    }

    return event
  }

  private func isHotKeyCode(_ keyCode: Int) -> Bool {
    guard let shortcut = KeyboardShortcuts.Name.popup.shortcut else {
      return false
    }

    return shortcut.key?.rawValue == keyCode
  }

  private func isHotKeyModifiers(_ modifiers: NSEvent.ModifierFlags) -> Bool {
    guard let shortcut = KeyboardShortcuts.Name.popup.shortcut else {
      return false
    }

    return modifiers.intersection(.deviceIndependentFlagsMask) ==
      shortcut.modifiers.intersection(.deviceIndependentFlagsMask)
  }

  private func allModifiersReleased(_ event: NSEvent) -> Bool {
    return event.modifierFlags.isDisjoint(with: .deviceIndependentFlagsMask)
  }
}


================================================
FILE: Maccy/Observables/SlideoutController.swift
================================================
import Defaults
import Logging
import Observation
import SwiftUI

enum SlideoutState {
  case opening
  case closing
  case open
  case closed

  var isAnimating: Bool {
    switch self {
    case .closed, .open:
      return false
    case .opening, .closing:
      return true
    }
  }

  var isOpen: Bool {
    switch self {
    case .open, .opening:
      return true
    case .closed, .closing:
      return false
    }
  }

  fileprivate func toggleWithAnimation() -> SlideoutState {
    switch self {
    case .open, .opening:
      return .closing
    case .closed, .closing:
      return .opening
    }
  }

  func animationDone() -> SlideoutState {
    switch self {
    case .open, .opening:
      return .open
    case .closed, .closing:
      return .closed
    }
  }
}

enum SlideoutPlacement {
  case left
  case right
}

enum SlideoutToggleTrigger {
  case autoOpen
  case manual
}

enum ResizingMode {
  case none
  case content
  case slideout
}

@Observable
class SlideoutController {
  let logger = Logger(label: "org.p0deje.Maccy")
  private static let animationDuration = 0.25

  let onContentResize: (CGFloat) -> Void
  let onSlideoutResize: (CGFloat) -> Void

  let minimumContentWidth: CGFloat = 200
  var contentResizeWidth: CGFloat = 0
  var contentAnimationWidth: CGFloat?

  let minimumSlideoutWidth: CGFloat = 200
  var slideoutResizeWidth: CGFloat = 0

  private var _contentWidth: CGFloat = 0
  var contentWidth: CGFloat {
    get { return _contentWidth }
    set {
      _contentWidth = max(minimumContentWidth, newValue).rounded()
      onContentResize(_contentWidth)
    }
  }
  private var _slideoutWidth: CGFloat = 400
  var slideoutWidth: CGFloat {
    get { return _slideoutWidth }
    set {
      _slideoutWidth = max(minimumSlideoutWidth, newValue).rounded()
      onSlideoutResize(_slideoutWidth)
    }
  }

  var placement: SlideoutPlacement = .right
  var state: SlideoutState = .closed
  var resizingMode: ResizingMode = .none

  var nswindow: NSWindow? {
    return AppState.shared.appDelegate?.panel
  }

  private var windowAnimationOrigin: CGPoint?
  private var windowAnimationOriginBaseState: SlideoutState = .closed

  private var autoOpenTask: Task<Void, Never>?
  private var autoOpenSuppressed = false
  private var autoOpenEnabled = true

  init(onContentResize: @escaping (CGFloat) -> Void, onSlideoutResize: @escaping (CGFloat) -> Void) {
    self.onContentResize = onContentResize
    self.onSlideoutResize = onSlideoutResize
  }

  private func togglePreviewStateWithAnimation(windowFrame: NSRect) {
    let newValue = state.toggleWithAnimation()
    if !state.isAnimating && newValue.isAnimating {
      contentAnimationWidth = contentWidth
      windowAnimationOrigin = windowFrame.origin
      windowAnimationOriginBaseState = state
    }
    state = newValue
  }

  func computePlacement(window: NSWindow, for size: NSSize) -> SlideoutPlacement {
    guard let screen = window.screen?.frame else { return placement }
    let windowFrame = window.frame
    if windowFrame.minX + size.width > screen.maxX {
      return .left
    } else {
      return .right
    }
  }

  func computeSizeWithPreview(_ size: NSSize, state newState: SlideoutState) -> NSSize {
    var newSize = size
    if newState.isOpen {
      newSize.width += slideoutWidth
    }
    let popup = AppState.shared.popup
    newSize.height = popup.preferredHeight(for: popup.height)
    return newSize
  }

  func togglePreview(trigger: SlideoutToggleTrigger = .manual) {
    if !state.isOpen {
      let navigator = AppState.shared.navigator
      guard navigator.leadHistoryItem != nil || navigator.pasteStackSelected else { return }
    }

    if trigger == .manual {
      if state.isOpen {
        autoOpenSuppressed = true
      } else {
        autoOpenSuppressed = false
      }
    }

    cancelAutoOpen()
    withAnimation(.easeInOut(duration: Self.animationDuration), completionCriteria: .removed) {
      if let window = nswindow {
        togglePreviewStateWithAnimation(windowFrame: window.frame)
        var newSize = window.frame.size
        newSize.width = contentWidth
        newSize = computeSizeWithPreview(newSize, state: self.state)
        if state.isOpen {
          placement = computePlacement(window: window, for: newSize)
        }

        let expectedAnimationState = state
        NSAnimationContext.runAnimationGroup { (context) in
          var newOrigin = windowAnimationOrigin ?? window.frame.origin
          newOrigin.y += (window.frame.height - newSize.height)

          if placement == .left {
            if windowAnimationOriginBaseState == .closed && state.isOpen {
              newOrigin.x -= slideoutWidth
            } else if windowAnimationOriginBaseState == .open
              && !state.isOpen {
              newOrigin.x += slideoutWidth
            }
            // Otherwise the base is the desired position
          }
          context.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
          context.completionHandler = {
            if self.state == expectedAnimationState {
              self.state = expectedAnimationState.animationDone()
            }
          }
          context.duration = Self.animationDuration
          window.animator().setFrame(
            NSRect(origin: newOrigin, size: newSize),
            display: true
          )
        }
      }
    } completion: {
    }
  }

  func startResize(mode: ResizingMode) {
    logger.info("Starting resize with mode \(mode)")
    resizingMode = mode
    contentWidth = contentResizeWidth
    slideoutWidth = slideoutResizeWidth
  }

  func endResize() {
    logger.info("Ended resize. Mode was \(resizingMode)")
    switch resizingMode {
    case .none:
      return
    case .content:
      contentWidth = contentResizeWidth
    case .slideout:
      slideoutWidth = slideoutResizeWidth
    }
    resizingMode = .none
  }

  func startAutoOpen() {
    cancelAutoOpen()

    guard autoOpenEnabled else { return }
    guard !autoOpenSuppressed else { return }
    guard !state.isOpen else { return }

    autoOpenTask = Task { @MainActor in
      try? await Task.sleep(for: .milliseconds(Defaults[.previewDelay]))
      guard !Task.isCancelled else { return }

      if !state.isOpen {
        togglePreview(trigger: .autoOpen)
      }
    }
  }

  func cancelAutoOpen() {
    autoOpenTask?.cancel()
    autoOpenTask = nil
  }

  func enableAutoOpen() {
    autoOpenEnabled = true
  }

  func disableAutoOpen() {
    autoOpenEnabled = false
    cancelAutoOpen()
  }

  func resetAutoOpenSuppression() {
    autoOpenSuppressed = false
  }
}


================================================
FILE: Maccy/PasteStack.swift
================================================
import Foundation
import AppKit

@Observable
class PasteStack: Identifiable, Hashable {
  private static var listener: Any?

  static func initializeIfNeeded() {
    guard listener == nil else { return }
    Accessibility.check()

    var pasteDown: Bool = false
    listener = NSEvent.addGlobalMonitorForEvents(matching: [.keyUp, .keyDown]) { event in
      switch event.type {
      case .keyDown:
        if event.keyCode == KeyChord.pasteKey.QWERTYKeyCode
           && event.modifierFlags.intersection(.deviceIndependentFlagsMask) == [.command] {
          pasteDown = true
        }
      case .keyUp:
        if pasteDown && event.keyCode == KeyChord.pasteKey.QWERTYKeyCode {
          pasteDown = false
          AppState.shared.history.handlePasteStack()
        }
      default:
        break
      }
    }
  }

  var id: UUID = UUID()
  var items: [HistoryItemDecorator] = []
  var modifierFlags: NSEvent.ModifierFlags

  init(items: [HistoryItemDecorator], modifierFlags: NSEvent.ModifierFlags) {
    self.items = items
    self.modifierFlags = modifierFlags
  }

  static func == (lhs: PasteStack, rhs: PasteStack) -> Bool {
    return lhs.id == rhs.id
      && lhs.items == rhs.items
      && lhs.modifierFlags.rawValue == rhs.modifierFlags.rawValue
  }

  func hash(into hasher: inout Hasher) {
    hasher.combine(id)
    hasher.combine(items)
    hasher.combine(modifierFlags.rawValue)
  }

}


================================================
FILE: Maccy/PinsPosition.swift
================================================
import Foundation
import Defaults

enum PinsPosition: String, CaseIterable, Identifiable, CustomStringConvertible, Defaults.Serializable {
  case top
  case bottom

  var id: Self { self }

  var description: String {
    switch self {
    case .top:
      return NSLocalizedString("PinToTop", tableName: "AppearanceSettings", comment: "")
    case .bottom:
      return NSLocalizedString("PinToBottom", tableName: "AppearanceSettings", comment: "")
    }
  }
}


================================================
FILE: Maccy/PopupPosition.swift
================================================
import AppKit.NSEvent
import Defaults
import Foundation

enum PopupPosition: String, CaseIterable, Identifiable, CustomStringConvertible, Defaults.Serializable {
  case cursor
  case statusItem
  case window
  case center
  case lastPosition

  var id: Self { self }

  var description: String {
    switch self {
    case .cursor:
      return NSLocalizedString("PopupAtCursor", tableName: "AppearanceSettings", comment: "")
    case .statusItem:
      return NSLocalizedString("PopupAtMenuBarIcon", tableName: "AppearanceSettings", comment: "")
    case .window:
      return NSLocalizedString("PopupAtWindowCenter", tableName: "AppearanceSettings", comment: "")
    case .center:
      return NSLocalizedString("PopupAtScreenCenter", tableName: "AppearanceSettings", comment: "")
    case .lastPosition:
      return NSLocalizedString("PopupAtLastPosition", tableName: "AppearanceSettings", comment: "")
    }
  }

  // swiftlint:disable:next cyclomatic_complexity
  func origin(size: NSSize, statusBarButton: NSStatusBarButton?) -> NSPoint {
    switch self {
    case .center:
      if let frame = NSScreen.forPopup?.visibleFrame {
        return NSRect.centered(ofSize: size, in: frame).origin
      }
    case .window:
      if let frame = NSWorkspace.shared.frontmostApplication?.windowFrame {
        return NSRect.centered(ofSize: size, in: frame).origin
      }
    case .statusItem:
      if let statusBarButton, let screen = NSScreen.main {
        let rectInWindow = statusBarButton.convert(statusBarButton.bounds, to: nil)
        if let screenRect = statusBarButton.window?.convertToScreen(rectInWindow) {
          var topLeftPoint = NSPoint(x: screenRect.minX, y: screenRect.minY - size.height)
          // Ensure that window doesn't spill over to the right screen.
          if (topLeftPoint.x + size.width) > screen.frame.maxX {
            topLeftPoint.x = screen.frame.maxX - size.width
          }

          return topLeftPoint
        }
      }
    case .lastPosition:
      if let frame = NSScreen.forPopup?.visibleFrame {
        let relativePos = Defaults[.windowPosition]
        let anchorX = frame.minX + frame.width * relativePos.x
        let anchorY = frame.minY + frame.height * relativePos.y
        // Anchor is top middle of frame
        return NSPoint(x: anchorX - size.width / 2, y: anchorY - size.height)
      }
    default:
      break
    }

    var point = NSEvent.mouseLocation
    point.y -= size.height
    return point
  }
}


================================================
FILE: Maccy/Search.swift
================================================
import AppKit
import Defaults
import Fuse

class Search {
  enum Mode: String, CaseIterable, Identifiable, CustomStringConvertible, Defaults.Serializable {
    case exact
    case fuzzy
    case regexp
    case mixed

    var id: Self { self }

    var description: String {
      switch self {
      case .exact:
        return NSLocalizedString("Exact", tableName: "GeneralSettings", comment: "")
      case .fuzzy:
        return NSLocalizedString("Fuzzy", tableName: "GeneralSettings", comment: "")
      case .regexp:
        return NSLocalizedString("Regex", tableName: "GeneralSettings", comment: "")
      case .mixed:
        return NSLocalizedString("Mixed", tableName: "GeneralSettings", comment: "")
      }
    }
  }

  struct SearchResult: Equatable {
    var score: Double?
    var object: Searchable
    var ranges: [Range<String.Index>] = []
  }

  typealias Searchable = HistoryItemDecorator

  private let fuse = Fuse(threshold: 0.7) // threshold found by trial-and-error
  private let fuzzySearchLimit = 5_000

  func search(string: String, within: [Searchable]) -> [SearchResult] {
    guard !string.isEmpty else {
      return within.map { SearchResult(object: $0) }
    }

    switch Defaults[.searchMode] {
    case .mixed:
      return mixedSearch(string: string, within: within)
    case .regexp:
      return simpleSearch(string: string, within: within, options: .regularExpression)
    case .fuzzy:
      return fuzzySearch(string: string, within: within)
    default:
      return simpleSearch(string: string, within: within, options: .caseInsensitive)
    }
  }

  private func fuzzySearch(string: String, within: [Searchable]) -> [SearchResult] {
    let pattern = fuse.createPattern(from: string)
    let searchResults: [SearchResult] = within.compactMap { item in
      fuzzySearch(for: pattern, in: item.title, of: item)
    }
    let sortedResults = searchResults.sorted(by: { ($0.score ?? 0) < ($1.score ?? 0) })
    return sortedResults
  }

  private func fuzzySearch(
    for pattern: Fuse.Pattern?,
    in searchString: String,
    of item: Searchable
  ) -> SearchResult? {
    var searchString = searchString
    if searchString.count > fuzzySearchLimit {
      // shortcut to avoid slow search
      let stopIndex = searchString.index(searchString.startIndex, offsetBy: fuzzySearchLimit)
      searchString = "\(searchString[...stopIndex])"
    }

    if let fuzzyResult = fuse.search(pattern, in: searchString) {
      return SearchResult(
        score: fuzzyResult.score,
        object: item,
        ranges: fuzzyResult.ranges.map {
          let startIndex = searchString.startIndex
          let lowerBound = searchString.index(startIndex, offsetBy: $0.lowerBound)
          let upperBound = searchString.index(startIndex, offsetBy: $0.upperBound + 1)

          return lowerBound..<upperBound
        }
      )
    } else {
      return nil
    }
  }

  private func simpleSearch(
    string: String,
    within: [Searchable],
    options: NSString.CompareOptions
  ) -> [SearchResult] {
    return within.compactMap { simpleSearch(for: string, in: $0.title, of: $0, options: options) }
  }

  private func simpleSearch(
    for string: String,
    in searchString: String,
    of item: Searchable,
    options: NSString.CompareOptions
  ) -> SearchResult? {
    if let range = searchString.range(of: string, options: options, range: nil, locale: nil) {
      return SearchResult(object: item, ranges: [range])
    } else {
      return nil
    }
  }

  private func mixedSearch(string: String, within: [Searchable]) -> [SearchResult] {
    var results = simpleSearch(string: string, within: within, options: .caseInsensitive)
    guard results.isEmpty else {
      return results
    }

    results = simpleSearch(string: string, within: within, options: .regularExpression)
    guard results.isEmpty else {
      return results
    }

    results = fuzzySearch(string: string, within: within)
    guard results.isEmpty else {
      return results
    }

    return []
  }
}


================================================
FILE: Maccy/SearchVisibility.swift
================================================
import Defaults
import Foundation

enum SearchVisibility: String, CaseIterable, Identifiable, CustomStringConvertible, Defaults.Serializable {
  case always
  case duringSearch

  var id: Self { self }

  var description: String {
    switch self {
    case .always:
      return NSLocalizedString("SearchVisibilityAlways", tableName: "AppearanceSettings", comment: "")
    case .duringSearch:
      return NSLocalizedString("SearchVisibilityDuringSearch", tableName: "AppearanceSettings", comment: "")
    }
  }
}


================================================
FILE: Maccy/Selection.swift
================================================
import AppKit

struct Selection<Item: Equatable> {
  var items: [Item]

  init(items: [Item] = []) {
    self.items = items
  }

  var isEmpty: Bool {
    return items.isEmpty
  }

  var count: Int {
    return items.count
  }

  var first: Item? {
    return items.first
  }

  func first(where condition: (Item) -> Bool) -> Item? {
    return items.first(where: condition)
  }

  func forEach(_ body: (Int, Item) throws -> Void) rethrows {
    try items.enumerated().forEach(body)
  }

  mutating func remove(_ item: Item) {
    items.removeAll { $0 == item }
  }

  mutating func add(_ item: Item) {
    items.append(item)
  }
}


================================================
FILE: Maccy/Settings/AdvancedSettingsPane.swift
================================================
import SwiftUI
import Defaults

struct AdvancedSettingsPane: View {
  var body: some View {
    VStack(alignment: .leading) {
      Defaults.Toggle(key: .ignoreEvents) {
        Text("TurnOff", tableName: "AdvancedSettings")
      }
      Text("TurnOffDescription", tableName: "AdvancedSettings")
        .fixedSize(horizontal: false, vertical: true)
        .foregroundStyle(.gray)
        .controlSize(.small)
      Text("TurnOffShellScript", tableName: "AdvancedSettings")
        .fixedSize(horizontal: false, vertical: true)
        .foregroundStyle(.gray)
        .font(.system(size: 11, design: .monospaced))
        .controlSize(.small)
        .padding(.vertical, 2)
      Text("TurnOffViaMenuIconDescription", tableName: "AdvancedSettings")
        .fixedSize(horizontal: false, vertical: true)
        .foregroundStyle(.gray)
        .controlSize(.small)
      Text("TurnOffNextShellScript", tableName: "AdvancedSettings")
        .fixedSize(horizontal: false, vertical: true)
        .foregroundStyle(.gray)
        .font(.system(size: 11, design: .monospaced))
        .controlSize(.small)
        .padding(.vertical, 2)

      Divider()

      Defaults.Toggle(key: .clearOnQuit) {
        Text("ClearHistoryOnQuit", tableName: "AdvancedSettings")
      }.help(Text("ClearHistoryOnQuitTooltip", tableName: "AdvancedSettings"))

      Defaults.Toggle(key: .clearSystemClipboard) {
        Text("ClearSystemClipboard", tableName: "AdvancedSettings")
      }.help(Text("ClearSystemClipboardTooltip", tableName: "AdvancedSettings"))
    }
    .frame(minWidth: 350, maxWidth: 450)
    .padding()
  }
}

#Preview {
  AdvancedSettingsPane()
    .environment(\.locale, .init(identifier: "en"))
}


================================================
FILE: Maccy/Settings/AppearanceSettingsPane.swift
================================================
import AppKit
import SwiftUI
import Defaults
import Settings

struct AppearanceSettingsPane: View {
  @Default(.popupPosition) private var popupAt
  @Default(.popupScreen) private var popupScreen
  @Default(.pinTo) private var pinTo
  @Default(.imageMaxHeight) private var imageHeight
  @Default(.previewDelay) private var previewDelay
  @Default(.highlightMatch) private var highlightMatch
  @Default(.menuIcon) private var menuIcon
  @Default(.showInStatusBar) private var showInStatusBar
  @Default(.showSearch) private var showSearch
  @Default(.searchVisibility) private var searchVisibility
  @Default(.showFooter) private var showFooter
  @Default(.windowPosition) private var windowPosition
  @Default(.showApplicationIcons) private var showApplicationIcons

  @State private var screens = NSScreen.screens

  private let imageHeightFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.minimum = 1
    formatter.maximum = 200
    return formatter
  }()

  private let numberOfItemsFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.minimum = 0
    formatter.maximum = 100
    return formatter
  }()

  private let titleLengthFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.minimum = 30
    formatter.maximum = 200
    return formatter
  }()

  private let previewDelayFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.minimum = 200
    formatter.maximum = 100_000
    return formatter
  }()

  var body: some View {
    Settings.Container(contentWidth: 650) {
      Settings.Section(label: { Text("PopupAt", tableName: "AppearanceSettings") }) {
        HStack {
          Picker("", selection: $popupAt) {
            ForEach(PopupPosition.allCases) { position in
              if position == .center || position == .lastPosition, screens.count > 1 {
                screenPicker(for: position)
              } else {
                Text(position.description)
              }
            }
          }
          .labelsHidden()
          .frame(width: 141, alignment: .leading)
          .help(Text("PopupAtTooltip", tableName: "AppearanceSettings"))

          if popupAt == .lastPosition {
            Button {
              _windowPosition.reset()
            } label: {
              Image(systemName: "arrow.uturn.backward.circle.fill")
                .imageScale(.large)
            }
            .buttonStyle(.borderless)
            .help(Text("PopupAtLastLocationReset", tableName: "AppearanceSettings"))
            .disabled(windowPosition == _windowPosition.defaultValue)
          }
        }
      }

      Settings.Section(label: { Text("PinTo", tableName: "AppearanceSettings") }) {
        Picker("", selection: $pinTo) {
          ForEach(PinsPosition.allCases) { position in
            Text(position.description)
          }
        }
        .labelsHidden()
        .frame(width: 141, alignment: .leading)
        .help(Text("PinToTooltip", tableName: "AppearanceSettings"))
      }

      Settings.Section(label: { Text("ImageHeight", tableName: "AppearanceSettings") }) {
        HStack {
          TextField("", value: $imageHeight, formatter: imageHeightFormatter)
            .frame(width: 120)
            .help(Text("ImageHeightTooltip", tableName: "AppearanceSettings"))
          Stepper("", value: $imageHeight, in: 1...200)
            .labelsHidden()
        }
      }

      Settings.Section(label: { Text("PreviewDelay", tableName: "AppearanceSettings") }) {
        HStack {
          TextField("", value: $previewDelay, formatter: previewDelayFormatter)
            .frame(width: 120)
            .help(Text("PreviewDelayTooltip", tableName: "AppearanceSettings"))
          Stepper("", value: $previewDelay, in: 200...100_000)
            .labelsHidden()
        }
      }

      Settings.Section(
        bottomDivider: true,
        label: { Text("HighlightMatches", tableName: "AppearanceSettings") }
      ) {
        Picker("", selection: $highlightMatch) {
          ForEach(HighlightMatch.allCases) { match in
            Text(match.description)
          }
        }
        .labelsHidden()
        .frame(width: 141, alignment: .leading)
        .help(Text("HighlightMatchesTooltip", tableName: "AppearanceSettings"))
      }

      Settings.Section(title: "") {
        Defaults.Toggle(key: .showSpecialSymbols) {
          Text("ShowSpecialSymbols", tableName: "AppearanceSettings")
        }
        .help(Text("ShowSpecialSymbolsTooltip", tableName: "AppearanceSettings"))

        HStack {
          Defaults.Toggle(key: .showInStatusBar) {
            Text("ShowMenuIcon", tableName: "AppearanceSettings")
          }

          Picker("", selection: $menuIcon) {
            ForEach(MenuIcon.allCases) { icon in
              Image(nsImage: icon.image)
            }
          }
          .labelsHidden()
          .scaledToFit()
          .disabled(!showInStatusBar)
          .controlSize(.small)
        }

        Defaults.Toggle(key: .showRecentCopyInMenuBar) {
          Text("ShowRecentCopyInMenuBar", tableName: "AppearanceSettings")
        }
        HStack {
          Defaults.Toggle(key: .showSearch) {
            Text("ShowSearchField", tableName: "AppearanceSettings")
          }

          Picker("", selection: $searchVisibility) {
            ForEach(SearchVisibility.allCases) { type in
              Text(type.description)
            }
          }
          .labelsHidden()
          .scaledToFit()
          .disabled(!showSearch)
          .controlSize(.small)
        }
        Defaults.Toggle(key: .showTitle) {
          Text("ShowTitleBeforeSearchField", tableName: "AppearanceSettings")
        }
        Defaults.Toggle(key: .showApplicationIcons) {
          Text("ShowApplicationIcons", tableName: "AppearanceSettings")
        }

        Defaults.Toggle(key: .showFooter) {
          Text("ShowFooter", tableName: "AppearanceSettings")
        }
        Text("OpenPreferencesWarning", tableName: "AppearanceSettings")
          .opacity(showFooter ? 0 : 1)
          .controlSize(.small)
          .foregroundStyle(.gray)
      }
    }
    .onReceive(NotificationCenter.default.publisher(for: NSApplication.didChangeScreenParametersNotification)) { _ in
      screens = NSScreen.screens
    }
  }

  @ViewBuilder
  private func screenPicker(for position: PopupPosition) -> some View {
    let screenBinding: Binding<Int> = Binding {
      return popupScreen
    } set: {
      popupScreen = $0
      popupAt = position
    }

    Picker(selection: screenBinding) {
      Text(labelForScreen(index: 0))
        .tag(0)

      ForEach(screens.indices, id: \.self) { index in
        Text(labelForScreen(index: index + 1))
          .tag(index + 1)
      }
    } label: {
      if popupAt == position {
        Text("\(position.description) (\(labelForScreen(index: popupScreen)))")
      } else {
        Text(position.description)
      }
    }
  }

  private func labelForScreen(index screenIndex: Int) -> String {
    switch screenIndex {
    case 0:
      return String(localized: "ActiveScreen", table: "AppearanceSettings")
    case _:
      return screens[screenIndex - 1].localizedName
    }
  }
}

#Preview {
  AppearanceSettingsPane()
    .environment(\.locale, .init(identifier: "en"))
}


================================================
FILE: Maccy/Settings/GeneralSettingsPane.swift
================================================
import SwiftUI
import Defaults
import KeyboardShortcuts
import LaunchAtLogin
import Settings

struct GeneralSettingsPane: View {
  private let notificationsURL = URL(
    string: "x-apple.systempreferences:com.apple.preference.notifications?id=\(Bundle.main.bundleIdentifier ?? "")"
  )

  @Default(.searchMode) private var searchMode

  @State private var copyModifier = HistoryItemAction.copy.modifierFlags.description
  @State private var pasteModifier = HistoryItemAction.paste.modifierFlags.description
  @State private var pasteWithoutFormatting = HistoryItemAction.pasteWithoutFormatting.modifierFlags.description

  @State private var updater = SoftwareUpdater()

  var body: some View {
    Settings.Container(contentWidth: 450) {
      Settings.Section(title: "", bottomDivider: true) {
        LaunchAtLogin.Toggle {
          Text("LaunchAtLogin", tableName: "GeneralSettings")
        }
        Toggle(isOn: $updater.automaticallyChecksForUpdates) {
          Text("CheckForUpdates", tableName: "GeneralSettings")
        }
        Button(
          action: { updater.checkForUpdates() },
          label: { Text("CheckNow", tableName: "GeneralSettings") }
        )
      }

      Settings.Section(label: { Text("Open", tableName: "GeneralSettings") }) {
        KeyboardShortcuts.Recorder(for: .popup, onChange: { newShortcut in
          if newShortcut == nil {
            // No shortcut is recorded. Remove keys monitor
            AppState.shared.popup.deinitEventsMonitor()
          } else {
            // User is using shortcut. Ensure keys monitor is initialized
            AppState.shared.popup.initEventsMonitor()
          }
        })
          .help(Text("OpenTooltip", tableName: "GeneralSettings"))
      }

      Settings.Section(label: { Text("Pin", tableName: "GeneralSettings") }) {
        KeyboardShortcuts.Recorder(for: .pin)
          .help(Text("PinTooltip", tableName: "GeneralSettings"))
      }
      Settings.Section(label: { Text("Delete", tableName: "GeneralSettings") }
      ) {
        KeyboardShortcuts.Recorder(for: .delete)
          .help(Text("DeleteTooltip", tableName: "GeneralSettings"))
      }
      Settings.Section(
        bottomDivider: true,
        label: { Text("ShowPreview", tableName: "GeneralSettings") }
      ) {
        KeyboardShortcuts.Recorder(for: .togglePreview)
          .help(Text("ShowPreviewTooltip", tableName: "GeneralSettings"))
      }

      Settings.Section(
        bottomDivider: true,
        label: { Text("Search", tableName: "GeneralSettings") }
      ) {
        Picker("", selection: $searchMode) {
          ForEach(Search.Mode.allCases) { mode in
            Text(mode.description)
          }
        }
        .labelsHidden()
        .frame(width: 180, alignment: .leading)
      }

      Settings.Section(
        bottomDivider: true,
        label: { Text("Behavior", tableName: "GeneralSettings") }
      ) {
        Defaults.Toggle(key: .pasteByDefault) {
          Text("PasteAutomatically", tableName: "GeneralSettings")
        }
        .onChange(refreshModifiers)
        .fixedSize()

        Defaults.Toggle(key: .removeFormattingByDefault) {
          Text("PasteWithoutFormatting", tableName: "GeneralSettings")
        }
        .onChange(refreshModifiers)
        .fixedSize()

        Text(String(
          format: NSLocalizedString("Modifiers", tableName: "GeneralSettings", comment: ""),
          copyModifier, pasteModifier, pasteWithoutFormatting
        ))
        .fixedSize(horizontal: false, vertical: true)
        .foregroundStyle(.gray)
        .controlSize(.small)
      }

      Settings.Section(title: "") {
        if let notificationsURL = notificationsURL {
          Link(destination: notificationsURL, label: {
            Text("NotificationsAndSounds", tableName: "GeneralSettings")
          })
        }
      }
    }
  }

  private func refreshModifiers(_ sender: Sendable) {
    copyModifier = HistoryItemAction.copy.modifierFlags.description
    pasteModifier = HistoryItemAction.paste.modifierFlags.description
    pasteWithoutFormatting = HistoryItemAction.pasteWithoutFormatting.modifierFlags.description
  }
}

#Preview {
  GeneralSettingsPane()
    .environment(\.locale, .init(identifier: "en"))
}


================================================
FILE: Maccy/Settings/IgnoreSettingsPane/IgnoreApplicationsSettingsView.swift
================================================
import SwiftUI
import Defaults

struct IgnoreApplicationsSettingsView: View {
  @Default(.ignoredApps) private var ignoredApps

  @State private var isAdding = false
  @State private var selection = ""

  var body: some View {
    VStack(alignment: .leading) {
      List(selection: $selection) {
        ForEach($ignoredApps) { $app in
          if let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: app) {
            Label(
              title: {
                Text(NSWorkspace.shared.applicationName(url: url))
                  .padding(.horizontal, 5)
              },
              icon: {
                Image(nsImage: NSWorkspace.shared.icon(forFile: url.path))
              }
            ).frame(height: 32).padding(.horizontal, 5)
          } else {
            Label(
              title: { Text(app).padding(.horizontal, 5) },
              icon: { Image(systemName: "questionmark.circle").imageScale(.large) }
            ).frame(height: 32).padding(.horizontal, 5)
          }
        }
      }.onDeleteCommand {
        remove(selection)
      }

      HStack {
        ControlGroup {
          Button("", systemImage: "plus") {
            isAdding = true
          }

          Button("", systemImage: "minus") {
            remove(selection)
          }
        }
        .frame(width: 50)
        .fileDialogDefaultDirectory(URL(string: "/Applications"))
        .fileImporter(
          isPresented: $isAdding,
          allowedContentTypes: [.application]
        ) { result in
          switch result {
          case .success(let appUrl):
            if let bundle = Bundle(path: appUrl.path),
               let bundleIdentifier = bundle.bundleIdentifier,
               !ignoredApps.contains(bundleIdentifier) {
              ignoredApps.append(bundleIdentifier)
            }
          case .failure(let error):
            print("Failed to select application: \(error)")
          }
        }

        Defaults.Toggle(key: .ignoreAllAppsExceptListed) {
          Text("IgnoredAllAppsExceptListed", tableName: "IgnoreSettings")
        }
      }

      Text("IgnoredAppsDescription", tableName: "IgnoreSettings")
        .fixedSize(horizontal: false, vertical: true)
        .foregroundStyle(.gray)
        .controlSize(.small)
    }.padding()
  }

  private func remove(_ app: String?) {
    guard let app else { return }

    ignoredApps.removeAll(where: { $0 == app })
  }
}

#Preview {
  IgnoreApplicationsSettingsView()
    .environment(\.locale, .init(identifier: "en"))
}


================================================
FILE: Maccy/Settings/IgnoreSettingsPane/IgnorePasteboardTypesSettingsView.swift
================================================
import Defaults
import SwiftUI

struct IgnorePasteboardTypesSettingsView: View {
  @Default(.ignoredPasteboardTypes) private var ignoredPasteboardTypes

  @FocusState private var focus: String.ID?
  @State private var edit = ""
  @State private var selection = ""

  var body: some View {
    VStack(alignment: .leading) {
      List(selection: $selection) {
        ForEach(ignoredPasteboardTypes.sorted()) { type in
          TextField("", text: Binding(
            get: { type },
            set: {
              guard !$0.isEmpty, type != $0 else { return }
              edit = $0
            })
          )
          .onSubmit {
            remove(type)
            ignoredPasteboardTypes.insert(edit)
          }
          .focused($focus, equals: type)
        }
      }
      .onDeleteCommand {
        remove(selection)
      }

      HStack {
        ControlGroup {
          Button("", systemImage: "plus") {
            ignoredPasteboardTypes.insert("xxx.yyy.zzz")
            focus = "xxx.yyy.zzz"
          }
          Button("", systemImage: "minus") {
            remove(selection)
          }
        }
        .frame(width: 50)

        Spacer()

        Button {
          Defaults.reset(.ignoredPasteboardTypes)
        } label: {
          Text("IgnoredPasteboardTypesReset", tableName: "IgnoreSettings")
        }
      }

      Text("IgnoredPasteboardTypesDescription", tableName: "IgnoreSettings")
        .fixedSize(horizontal: false, vertical: true)
        .foregroundStyle(.gray)
        .controlSize(.small)
    }
    .padding()
  }

  private func remove(_ type: String?) {
    guard let type else { return }

    ignoredPasteboardTypes.remove(type)
  }
}

#Preview {
  IgnorePasteboardTypesSettingsView()
    .environment(\.locale, .init(identifier: "en"))
}


================================================
FILE: Maccy/Settings/IgnoreSettingsPane/IgnoreRegexpsSettingsView.swift
================================================
import SwiftUI
import Defaults

struct IgnoreRegexpsSettingsView: View {
  @Default(.ignoreRegexp) private var ignoredRegexps

  @FocusState private var focus: String.ID?
  @State private var edit = ""
  @State private var selection = ""

  var body: some View {
    VStack(alignment: .leading) {
      List(selection: $selection) {
        ForEach(ignoredRegexps) { regexp in
          TextField("", text: Binding(
            get: { regexp },
            set: {
              guard !$0.isEmpty, regexp != $0 else { return }
              edit = $0
            })
          ).onSubmit {
            remove(regexp)
            ignoredRegexps.append(edit)
          }.focused($focus, equals: regexp)
        }
      }.onDeleteCommand {
        remove(selection)
      }

      ControlGroup {
        Button("", systemImage: "plus") {
          ignoredRegexps.append("^[a-zA-Z0-9]{50}$")
          focus = "^[a-zA-Z0-9]{50}$"
        }
        Button("", systemImage: "minus") {
          remove(selection)
        }
      }.frame(width: 50)

      Text("IgnoredRegexpsDescription", tableName: "IgnoreSettings")
        .fixedSize(horizontal: false, vertical: true)
        .foregroundStyle(.gray)
        .controlSize(.small)
    }.padding()
  }

  private func remove(_ regexp: String?) {
    guard let regexp else { return }

    ignoredRegexps.removeAll(where: { $0 == regexp })
  }
}

#Preview {
  IgnoreRegexpsSettingsView()
    .environment(\.locale, .init(identifier: "en"))
}


================================================
FILE: Maccy/Settings/IgnoreSettingsPane.swift
================================================
import SwiftUI

struct IgnoreSettingsPane: View {
  var body: some View {
    TabView {
      IgnoreApplicationsSettingsView()
        .tabItem {
          Text("ApplicationsTab", tableName: "IgnoreSettings")
        }
      IgnorePasteboardTypesSettingsView()
        .tabItem {
          Text("PasteboardTypesTab", tableName: "IgnoreSettings")
        }
      IgnoreRegexpsSettingsView()
        .tabItem {
          Text("RegexpTab", tableName: "IgnoreSettings")
        }
    }
    .frame(maxWidth: 500, minHeight: 400)
    .padding()
  }
}

#Preview {
  IgnoreSettingsPane()
    .environment(\.locale, .init(identifier: "en"))
}


================================================
FILE: Maccy/Settings/PinsSettingsPane.swift
================================================
import SwiftData
import SwiftUI

struct PinPickerView: View {
  @Bindable var item: HistoryItem
  var availablePins: [String]

  var body: some View {
    if let pin = item.pin {
      // Ensure unique pins for ForEach
      let uniquePins = Array(Set(availablePins + [pin])).sorted()
      Picker("", selection: $item.pin) {
        ForEach(uniquePins, id: \.self) { pin in
          Text(pin)
            .tag(pin as String?)
        }
      }
      .controlSize(.small)
      .labelsHidden()
    }
  }
}

struct PinTitleView: View {
  @Bindable var item: HistoryItem

  var body: some View {
    TextField("", text: $item.title)
  }
}

struct PinValueView: View {
  @Bindable var item: HistoryItem
  @State private var editableValue: String
  @State private var isTextContent: Bool
  @State private var isRichText: Bool
  @FocusState private var isEditing: Bool
  @State private var showWarningPopover: Bool = false

  init(item: HistoryItem) {
    self.item = item
    self._editableValue = State(initialValue: item.previewableText)

    // Check if this item has editable text content
    let hasPlainText = item.text != nil
    let hasImage = item.image != nil
    let hasFileURLs = !item.fileURLs.isEmpty
    let hasRichText = item.rtf != nil || item.html != nil

    // Consider it text content only if it has plain text and doesn't have images or file URLs
    self._isTextContent = State(initialValue: hasPlainText && !hasImage && !hasFileURLs)
    self._isRichText = State(initialValue: hasRichText && !hasImage && !hasFileURLs)
  }

  var body: some View {
    Group {
      if isTextContent || isRichText {
        ZStack(alignment: .trailing) {
          TextField("", text: $editableValue)
            .focused($isEditing)
            .onSubmit {
              updateItemContent()
            }
            .onChange(of: editableValue) { _, _ in
              updateItemContent()
            }
            .padding(.trailing, isRichText ? 40 : 0) // increased space for icon

          if isRichText && isEditing {
            HStack(spacing: 0) {
              Spacer(minLength: 0)
              Image(systemName: "exclamationmark.triangle.fill")
                .foregroundColor(.orange)
                .help(Text("RichTextEditWarning", tableName: "PinsSettings"))
              Spacer().frame(width: 4)
            }
            .frame(maxHeight: .infinity, alignment: .center)
            .padding(.trailing, 4)
          }
        }
      } else {
        // Non-editable display for non-text content
        Text("ContentIsNotText", tableName: "PinsSettings")
          .foregroundStyle(.secondary)
          .italic()
      }
    }
  }

  private func updateItemContent() {
    // Only update if we're dealing with text or rich text content
    guard isTextContent || isRichText else { return }

    // Remove all non-plain-text content
    let stringType = NSPasteboard.PasteboardType.string.rawValue
    item.contents.removeAll { $0.type != stringType }

    // Update or add the plain text content
    if let index = item.contents.firstIndex(where: { $0.type == stringType }) {
      if let data = editableValue.data(using: .utf8) {
        item.contents[index].value = data
      }
    } else {
      if let data = editableValue.data(using: .utf8) {
        let newContent = HistoryItemContent(type: stringType, value: data)
        item.contents.append(newContent)
      }
    }
    // We don't automatically update title here since we want to preserve
    // OCR-extracted titles for images and other non-text content
  }
}

struct PinsSettingsPane: View {
  @Environment(AppState.self) private var appState
  @Environment(\.modelContext) private var modelContext

  @Query(filter: #Predicate<HistoryItem> { $0.pin != nil }, sort: \.firstCopiedAt)
  private var items: [HistoryItem]

  @State private var availablePins: [String] = []
  @State private var selection: PersistentIdentifier?

  var body: some View {
    VStack(alignment: .leading) {
      Table(items, selection: $selection) {
        TableColumn(Text("Key", tableName: "PinsSettings")) { item in
          PinPickerView(item: item, availablePins: availablePins)
            .onChange(of: item.pin) {
              availablePins = HistoryItem.availablePins
            }
        }
        .width(60)

        TableColumn(Text("Alias", tableName: "PinsSettings")) { item in
          PinTitleView(item: item)
        }

        TableColumn(Text("Content", tableName: "PinsSettings")) { item in
          PinValueView(item: item)
        }
      }
      .onAppear {
        availablePins = HistoryItem.availablePins
      }
      .onDeleteCommand {
        guard let selection,
              let item = appState.history.items.first(where: { $0.item.id == selection }) else {
          return
        }

        appState.history.delete(item)
      }

      Text("PinCustomizationDescription", tableName: "PinsSettings")
        .foregroundStyle(.gray)
        .controlSize(.small)
    }
    .frame(minWidth: 500, minHeight: 400)
    .padding()
  }
}

#Preview {
  return PinsSettingsPane()
    .environment(\.locale, .init(identifier: "en"))
    .modelContainer(Storage.shared.container)
}


================================================
FILE: Maccy/Settings/StorageSettingsPane.swift
================================================
import SwiftUI
import Defaults
import Settings

struct StorageSettingsPane: View {
  @Observable
  class ViewModel {
    var saveFiles = false {
      didSet {
        Defaults.withoutPropagation {
          if saveFiles {
            Defaults[.enabledPasteboardTypes].formUnion(StorageType.files.types)
          } else {
            Defaults[.enabledPasteboardTypes].subtract(StorageType.files.types)
          }
        }
      }
    }

    var saveImages = false {
      didSet {
        Defaults.withoutPropagation {
          if saveImages {
            Defaults[.enabledPasteboardTypes].formUnion(StorageType.images.types)
          } else {
            Defaults[.enabledPasteboardTypes].subtract(StorageType.images.types)
          }
        }
      }
    }

    var saveText = false {
      didSet {
        Defaults.withoutPropagation {
          if saveText {
            Defaults[.enabledPasteboardTypes].formUnion(StorageType.text.types)
          } else {
            Defaults[.enabledPasteboardTypes].subtract(StorageType.text.types)
          }
        }
      }
    }

    private var observer: Defaults.Observation?

    init() {
      observer = Defaults.observe(.enabledPasteboardTypes) { change in
        self.saveFiles = change.newValue.isSuperset(of: StorageType.files.types)
        self.saveImages = change.newValue.isSuperset(of: StorageType.images.types)
        self.saveText = change.newValue.isSuperset(of: StorageType.text.types)
      }
    }

    deinit {
      observer?.invalidate()
    }
  }

  @Default(.size) private var size
  @Default(.sortBy) private var sortBy

  @State private var viewModel = ViewModel()
  @State private var storageSize = Storage.shared.size

  private let sizeFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.minimum = 1
    formatter.maximum = 999
    return formatter
  }()

  var body: some View {
    Settings.Container(contentWidth: 450) {
      Settings.Section(
        bottomDivider: true,
        label: { Text("Save", tableName: "StorageSettings") }
      ) {
        Toggle(
          isOn: $viewModel.saveFiles,
          label: { Text("Files", tableName: "StorageSettings") }
        )
        Toggle(
          isOn: $viewModel.saveImages,
          label: { Text("Images", tableName: "StorageSettings") }
        )
        Toggle(
          isOn: $viewModel.saveText,
          label: { Text("Text", tableName: "StorageSettings") }
        )
        Text("SaveDescription", tableName: "StorageSettings")
          .controlSize(.small)
          .foregroundStyle(.gray)
      }

      Settings.Section(label: { Text("Size", tableName: "StorageSettings") }) {
        HStack {
          TextField("", value: $size, formatter: sizeFormatter)
            .frame(width: 80)
            .help(Text("SizeTooltip", tableName: "StorageSettings"))
          Stepper("", value: $size, in: 1...999)
            .labelsHidden()
          Text(storageSize)
            .controlSize(.small)
            .foregroundStyle(.gray)
            .help(Text("CurrentSizeTooltip", tableName: "StorageSettings"))
            .onAppear {
              storageSize = Storage.shared.size
            }
        }
      }

      Settings.Section(label: { Text("SortBy", tableName: "StorageSettings") }) {
        Picker("", selection: $sortBy) {
          ForEach(Sorter.By.allCases) { mode in
            Text(mode.description)
          }
        }
        .labelsHidden()
        .frame(width: 160, alignment: .leading)
        .help(Text("SortByTooltip", tableName: "StorageSettings"))
      }
    }
  }
}

#Preview {
  StorageSettingsPane()
    .environment(\.locale, .init(identifier: "en"))
}


================================================
FILE: Maccy/Settings/ar.lproj/AdvancedSettings.strings
================================================
"Title" = "متقدم";
"TurnOff" = "إيقاف";
"TurnOffDescription" = "تجاهل جميع النسخ الجديدة مؤقتًا.\nمن المرجح أن تستخدمه برمجيًا وتعطل التطبيق أثناء نسخ البيانات الحساسة.";
"TurnOffShellScript" = "defaults write org.p0deje.Maccy ignoreEvents true\nنسخ البيانات #\ndefaults write org.p0deje.Maccy ignoreEvents false";
"TurnOffViaMenuIconDescription" = "يمكنك أيضًا النقر على أيقونة القائمة مع ⌥ مضغوط.\nلتجاهل النسخة التالية فقط، انقر بـ ⌥⇧.";
"TurnOffNextShellScript" = "defaults write org.p0deje.Maccy ignoreOnlyNextEvent true\nنسخ البيانات #";
"ClearHistoryOnQuit" = "مسح السجل عند الخروج";
"ClearHistoryOnQuitTooltip" = "إزالة جميع العناصر غير المثبتة تلقائيًا قبل إغلاق التطبيق.";
"ClearSystemClipboard" = "مسح حافظة النظام أيضًا";
"ClearSystemClipboardTooltip" = "عند التمكين، سيؤدي مسح السجل أيضًا إلى مسح حافظة النظام الحالية.";


================================================
FILE: Maccy/Settings/ar.lproj/AppearanceSettings.strings
================================================
"Title" = "المظهر";
"PopupAt" = "ظهور الإنبثاق عند:";
"PopupAtCursor" = "المؤشر";
"PopupAtMenuBarIcon" = "أيقونة القائمة";
"PopupAtWindowCenter" = "مركز النافذة";
"PopupAtScreenCenter" = "مركز الشاشة";
"PopupAtLastPosition" = "الموضع الأخير";
"PopupAtLastLocationReset" = "إعادة تعيين الموضع";
"PopupAtTooltip" = "تغيير موقع ظهور الإنبثاق.\nالافتراضي: المؤشر.";
"SearchVisibilityAlways" = "دائمًا";
"SearchVisibilityDuringSearch" = "أثناء البحث";
"ActiveScreen" = "شاشة نشطة";
"PinTo" = "تثبيت إلى:";
"PinToTop" = "الأعلى";
"PinToBottom" = "الأسفل";
"PinToTooltip" = "تغيير موقع العناصر المثبتة.\nالافتراضي: الأعلى.";
"ImageHeight" = "ارتفاع الصورة:";
"ImageHeightTooltip" = "أقصى ارتفاع معاينة الصورة.\nالافتراضي: 40.\nتلميح: قم بتعيينه إلى 16 ليبدو مثل عناصر النص.";
"PreviewDelay" = "تأخير المعاينة:";
"PreviewDelayTooltip" = "التأخير بالميللي ثانية حتى يتم عرض معاينة النافذة المنبثقة.\nالافتراضي: 1500.";
"HighlightMatches" = "تسليط الضوء على التطابقات:";
"HighlightMatchColor" = "اللون";
"HighlightMatchBold" = "عريض";
"HighlightMatchItalic" = "مائل";
"HighlightMatchUnderline" = "تسطير";
"HighlightMatchesTooltip" = "تغيير نمط التميز للبحث عن المطابقات.\nالافتراضي: عريض.";
"ShowSpecialSymbols" = "إظهار الرموز الخاصة";
"ShowSpecialSymbolsTooltip" = "إظهار الأسطر الجديدة، علامات التبويب، المسافات الأمامية والخلفية عبر الرموز الخاصة.";
"ShowMenuIcon" = "إظهار أيقونة القائمة";
"ShowRecentCopyInMenuBar" = "إظهار النسخة الأخيرة بجوار أيقونة القائمة";
"ShowSearchField" = "إظهار حقل البحث";
"ShowTitleBeforeSearchField" = "إظهار العنوان قبل حقل البحث";
"ShowFooter" = "إظهار التذييل";
"ShowApplicationIcons" = "إظهار أيقونات التطبيقات";
"OpenPreferencesWarning" = "⚠️ اضغط على ⌘، (command+comma) لفتح التفضيلات عندما يكون التذييل مخفيًا.";


================================================
FILE: Maccy/Settings/ar.lproj/GeneralSettings.strings
================================================
"Title" = "عام";
"LaunchAtLogin" = "التشغيل عند تسجيل الدخول";
"CheckForUpdates" = "التحقق من التحديثات تلقائيًا";
"CheckNow" = "التحقق الآن";
"Open" = "فتح:";
"OpenTooltip" = "مفتاح الاختصار العام لفتح التطبيق.\nسيؤدي الضغط المتكرر على المفتاح الرئيسي أثناء الضغط باستمرار على مفاتيح التعديل إلى تحديد العنصر التالي في القائمة. في هذا الوضع، سيؤدي تحرير مفاتيح التعديل إلى تأكيد التحديد وإغلاق النافذة المنبثقة.\nالوضع الافتراضي: ⇧⌘C.";
"Pin" = "تثبيت:";
"PinTooltip" = "مفتاح الاختصار لتثبيت عنصر السجل.\nالافتراضي: %@P.";
"Delete" = "حذف:";
"DeleteTooltip" = "مفتاح الاختصار لحذف عنصر السجل.\nالافتراضي: %@⌫.";
"ShowPreview" = "معاينة:";
"ShowPreviewTooltip" = "إظهار المعاينة مع معلومات إضافية.\nالافتراضي: ⌃Space.";
"Behavior" = "الإجراء:";
"PasteAutomatically" = "لصق تلقائيًا";
"PasteWithoutFormatting" = "لصق بدون تنسيق";
"Modifiers" = "تخصيص الإجراء عند تحديد العنصر:\n• حدد مع %@ ضغط لنسخ العنصر.\n• حدد مع %@ ضغط لنسخ ولصق العنصر.\n• حدد مع %@ ضغط لنسخ، مسح التنسيق ولصق العنصر.";
"Search" = "البحث:";
"Exact" = "دقيق";
"Fuzzy" = "غامض";
"Regex" = "التعبيرات العادية";
"Mixed" = "مختلط";
"NotificationsAndSounds" = "الإشعارات والأصوات 􀱁";


================================================
FILE: Maccy/Settings/ar.lproj/IgnoreSettings.strings
================================================
"Title" = "تجاهل";
"ApplicationsTab" = "التطبيقات";
"IgnoredAppsDescription" = "من الممكن تجاهل النسخ القادمة من بعض التطبيقات.\nيرجى ملاحظة أن الطريقة التي تعمل بها ليست مضمونة بنسبة 100٪، لذا من الأفضل استخدام أنواع الحافظة عند الإمكان.";
"IgnoredAllAppsExceptListed" = "تجاهل جميع التطبيقات ما عدا المُدرجة";
"PasteboardTypesTab" = "أنواع الحافظة";
"IgnoredPasteboardTypesDescription" = "من الممكن تجاهل بعض أنواع عناصر الحافظة من التذكر.\nبشكل افتراضي، تم تحديد بعض الأنواع المعروفة المحددة للتطبيق. يمكنك إزالتها وإضافة أي أنواع مخصصة ترغب فيها.";
"IgnoredPasteboardTypesReset" = "إعادة تعيين";
"RegexpTab" = "التعبيرات العادية";
"IgnoredRegexpsDescription" = "من الممكن تجاهل بعض النسخ من التذكر استنادًا إلى التعبيرات العادية المحددة.";


================================================
FILE: Maccy/Settings/ar.lproj/PinsSettings.strings
================================================
"Title" = "مثبتة";
"Key" = "المفتاح";
"Alias" = "العنوان";
"Content" = "المحتوى";
"ContentIsNotText" = "محتوى غير قابل للتحرير (صورة أو ملف)";
"RichTextEditWarning" = "سيؤدي التحرير إلى تجاهل جميع التنسيقات.";
"PinCustomizationDescription" = "يمكنك تخصيص مفتاح الاختصار، والعنوان، ومحتوى أي عنصر مثبت. للتعديل، انقر نقرًا مزدوجًا فوق العنصر وأدخل قيمة جديدة.\nيرجى ملاحظة أنه يمكن تغيير النص العادي فقط.";


================================================
FILE: Maccy/Settings/ar.lproj/StorageSettings.strings
================================================
"Title" = "التخزين";
"Save" = "حفظ:";
"Files" = "الملفات";
"Images" = "الصور";
"Text" = "النصوص";
"SaveDescription" = "تغيير أنواع المحتوى المنسوخة التي يجب حفظها.";
"Size" = "الحجم:";
"SizeTooltip" = "عدد عناصر التاريخ للحفاظ عليها.\nالافتراضي: 200.";
"CurrentSizeTooltip" = "الحجم الحالي على القرص.";
"SortBy" = "الترتيب حسب:";
"LastCopiedAt" = "وقت النسخة الأخيرة";
"FirstCopiedAt" = "وقت النسخة الأولى";
"NumberOfCopies" = "عدد النسخ";
"SortByTooltip" = "الافتراضي: وقت النسخة الأخيرة.";


================================================
FILE: Maccy/Settings/be.lproj/AdvancedSettings.strings
================================================
"Title" = "Прасунутыя";
"TurnOff" = "Выключыць";
"TurnOffShellScript" = "defaults write org.p0deje.Maccy ignoreEvents true\n# капіяваць дадзеныя\ndefaults write org.p0deje.Maccy ignoreEvents false";
"TurnOffNextShellScript" = "defaults write org.p0deje.Maccy ignoreOnlyNextEvent true\n# капіяваць дадзеныя";
"ClearHistoryOnQuit" = "Ачысціць гісторыю пры зачыненні";
"ClearSystemClipboard" = "Таксама ачысціць сістэмны буфер абмену";
"ClearSystemClipboardTooltip" = "Калі гэты параметр улучаны, ачыстка гісторыі таксама ачысціць бягучы сістэмны буфер абмену.";
"TurnOffDescription" = "Часова ігнараваць усе новыя капіяванні.\nВы можаце скарыстаць гэту наладу праграмна і адключыць дадатак на час капіявання прыватных дадзеных.";
"TurnOffViaMenuIconDescription" = "Вы таксама можаце клікнуць значок меню з націснутым ⌥.\nКаб ігнараваць толькі наступную копію, клікніце з ⌥⇧.";
"ClearHistoryOnQuitTooltip" = "Аўтаматычна падаляць усе незамацаваныя запісы перад зачыненнем дадатку.";


================================================
FILE: Maccy/Settings/be.lproj/AppearanceSettings.strings
================================================
"Title" = "Выгляд";
"PopupAtMenuBarIcon" = "Значка меню";
"PopupAtWindowCenter" = "Цэнтра акна";
"PopupAtScreenCenter" = "Цэнтра экрану";
"PopupAtLastLocationReset" = "Скінуць пазіцыю";
"PopupAtLastPosition" = "Апошняй пазіцыіі";
"SearchVisibilityDuringSearch" = "Падчас пошуку";
"ActiveScreen" = "Актыўны экран";
"PinToTop" = "Верху";
"PinToBottom" = "Нізу";
"ImageHeight" = "Вышыня выяў:";
"PreviewDelay" = "Затрымка прадпрагляду:";
"HighlightMatches" = "Вылучыць супадзенні:";
"HighlightMatchBold" = "Тоўсты";
"HighlightMatchItalic" = "Курсіў";
"HighlightMatchUnderline" = "Падкрэслены";
"ShowSpecialSymbols" = "Паказваць адмысловыя знакі";
"ShowMenuIcon" = "Паказваць значок меню";
"ShowRecentCopyInMenuBar" = "Паказваць апошні элемент поруч з значком меню";
"ShowFooter" = "Паказваць ніжні калонтытул";
"PopupAt" = "Усплываць каля:";
"PopupAtCursor" = "Курсору";
"SearchVisibilityAlways" = "Заўсёды";
"PinTo" = "Замацаваць да:";
"PinToTooltip" = "Змяніць месца замацаваных элементаў.\nПадставова: Верх.";
"HighlightMatchColor" = "Колер";
"OpenPreferencesWarning" = "⚠️ Націсніце ⌘, (command+comma) каб адкрыць налады калі ніжні калонтытул утоены.";
"ShowSpecialSymbolsTooltip" = "Паказваць знакі новага радка, табуляцыі, пачатковыя і канчатковыя прабелы з дапамогай адмысловых знакаў.";
"ShowSearchField" = "Паказваць поле пошуку";
"ShowTitleBeforeSearchField" = "Паказваць назву перад пошукам";
"ImageHeightTooltip" = "Максімальная вышыня прадпрагляду выяў.\nПадставова: 40.\nПадказка: Пастаўце 16 для падабенства з тэкставымі запісамі.";
"HighlightMatchesTooltip" = "Змяніце стыль вылучэння для супадзенняў пры пошуку.\nПадставова: Тоўсты.";
"PreviewDelayTooltip" = "Затрымка ў мілісекундах да з'яўлення ўсплыўнога акна прадпрагляду.\nПадставова: 1500.";
"PopupAtTooltip" = "Змяніць месца для з'яўлення ўсплыўнога акна.\nПадставова: Курсор.";
"ShowApplicationIcons" = "Паказаць значкі прыкладанняў";


================================================
FILE: Maccy/Settings/be.lproj/GeneralSettings.strings
================================================
"LaunchAtLogin" = "Запускаць пры логіне";
"CheckNow" = "Праверыць зараз";
"Open" = "Адчыніць:";
"PinTooltip" = "Гарачая клавіша для замацавання элементу.\nПадставова: %@P.";
"Delete" = "Выдаліць:";
"DeleteTooltip" = "Гарачая клавіша для выдалення элементу.\nПадставова: ⌥⌫.";
"ShowPreview" = "Перадпрагляд:";
"ShowPreviewTooltip" = "Паказаць перадпрагляд з дадатковай інфармацыяй.\nПадставова: ⌃Space.";
"Behavior" = "Паводзіны:";
"PasteAutomatically" = "Аўтаматычна ўстаўляць";
"PasteWithoutFormatting" = "Устаўляць без фарматавання";
"Modifiers" = "Наладзіць паводзіны пры выбары элемента:\n• Выберыце з %@, каб скапіяваць элемент.\n• Выберыце з %@, каб скапіяваць і ўставіць элемент.\n• Выберыце з %@, каб скапіяваць, ачысціць фарматаванне і ўставіць элемент.";
"Exact" = "Дакладны";
"Fuzzy" = "Недакладны";
"Regex" = "Рэгулярныя выразы";
"Mixed" = "Змяшаны";
"NotificationsAndSounds" = "Паведамленні і гукі 􀱁";
"Title" = "Асноўныя";
"CheckForUpdates" = "Аўтаматычна правяраць абнаўленні";
"OpenTooltip" = "Глабальная камбінацыя клавіш для адкрыцця праграмы.\nПаўторнае націсканне асноўнай клавішы з утрыманнем мадыфікатараў выбера наступны элемент у спісе. У гэтым рэжыме адпусканне клавіш-мадыфікатараў пацвердзіць выбар і закрые ўсплывальнае акно.\nПа змаўчанні: ⇧⌘C.";
"Search" = "Пошук:";
"Pin" = "Замацаваць:";


================================================
FILE: Maccy/Settings/be.lproj/IgnoreSettings.strings
================================================
"IgnoredAppsDescription" = "Капіяванні з пэўных дадаткаў можна ігнараваць.\nКалі ласка ўлічвайце, што гэтае вырашэнне не гарантуе стаадсадковага выніку, таму, па-магчымасці, рэкамендавана карыстацца з ігнараваных тыпаў.";
"ApplicationsTab" = "Дадаткі";
"Title" = "Ігнараванне";
"IgnoredAllAppsExceptListed" = "Ігнараваць усе дадаткі, апроч пералічаных";
"PasteboardTypesTab" = "Тыпы капіяваных дадзеных";
"IgnoredPasteboardTypesDescription" = "Капіяванні пэўных тыпаў капіяваных дадзеных можна ігнараваць.\nПа змаўчанні паказаны некаторыя вядомыя тыпы, спецыфічныя для некаторых дадаткаў. Вы можаце іх выдаліць і дадаць свае тыпы.";
"IgnoredPasteboardTypesReset" = "Скід";
"RegexpTab" = "Рэгулярныя выразы";
"IgnoredRegexpsDescription" = "Капіяванні, якія адпавядаюць некаторым рэгулярным выразам, можна ігнараваць.";


================================================
FILE: Maccy/Settings/be.lproj/PinsSettings.strings
================================================
"Title" = "Замацаваныя";
"Key" = "Клавіша";
"Alias" = "Назва";
"Content" = "Кантэнт";
"ContentIsNotText" = "Нерэдагавальны кантэнт (малюнак або файл)";
"RichTextEditWarning" = "Рэдагаванне адменіць усё фарматаванне.";
"PinCustomizationDescription" =
Download .txt
gitextract_l43svsy0/

├── .bartycrouch.toml
├── .github/
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       ├── bug_report.yml
│       ├── config.yml
│       └── feature_request.yml
├── .gitignore
├── .periphery.yml
├── .swiftlint.yml
├── Designs/
│   ├── App-Store/
│   │   ├── 01-Main.pxd
│   │   ├── 02-Types.pxd
│   │   ├── 03-Search.pxd
│   │   ├── 04-Pin.pxd
│   │   ├── 05-Shortcuts.pxd
│   │   ├── 06-Languages.pxd
│   │   └── Promo/
│   │       └── Maccy_1527619437_20240124_MacAppStore_SupportingImagery.psd
│   ├── Copies.txt
│   ├── Icons.sketch
│   ├── Instructions.pxd/
│   │   ├── QuickLook/
│   │   │   ├── Icon.tiff
│   │   │   └── Thumbnail.tiff
│   │   ├── data/
│   │   │   ├── CAE20F62-9DFC-4BD2-AE79-BE620A2ADE55
│   │   │   ├── DF48A8C2-D105-49EF-BF24-87B87BAECAC7-OriginalContentSource
│   │   │   └── selectionForContentTransform/
│   │   │       ├── meta
│   │   │       └── shapeSelection/
│   │   │           ├── meta
│   │   │           └── path
│   │   └── metadata.info
│   └── Storage-Types.pxd/
│       ├── QuickLook/
│       │   ├── Icon.tiff
│       │   └── Thumbnail.tiff
│       ├── data/
│       │   ├── 460814B1-E0F9-4E2C-B4CA-32C0CD866260-OriginalContentSource
│       │   ├── A2CD8EA6-822D-4757-B972-8653B2AABD6B
│       │   ├── selection/
│       │   │   ├── meta
│       │   │   └── shapeSelection/
│       │   │       ├── meta
│       │   │       └── path
│       │   └── selectionForContentTransform/
│       │       ├── meta
│       │       └── shapeSelection/
│       │           ├── meta
│       │           └── path
│       └── metadata.info
├── LICENSE
├── Maccy/
│   ├── About.swift
│   ├── Accessibility.swift
│   ├── AppDelegate.swift
│   ├── AppStoreReview.swift
│   ├── ApplicationImage.swift
│   ├── ApplicationImageCache.swift
│   ├── Assets.xcassets/
│   │   ├── AppIcon.appiconset/
│   │   │   └── Contents.json
│   │   ├── Contents.json
│   │   ├── StatusBarMenuImage.imageset/
│   │   │   └── Contents.json
│   │   ├── clipboard.fill.imageset/
│   │   │   └── Contents.json
│   │   ├── paperclip.imageset/
│   │   │   └── Contents.json
│   │   └── scissors.imageset/
│   │       └── Contents.json
│   ├── Clipboard.swift
│   ├── ColorImage.swift
│   ├── Extensions/
│   │   ├── Collection+Surrounding.swift
│   │   ├── Color+Random.swift
│   │   ├── Defaults.Keys+Names.swift
│   │   ├── Dictionary+RemoveItem.swift
│   │   ├── KeyEquivalent+Keys.swift
│   │   ├── KeyboardShortcuts.Name+Shortcuts.swift
│   │   ├── ModifierFlags+Description.swift
│   │   ├── NSApplication+Windows.swift
│   │   ├── NSImage+Names.swift
│   │   ├── NSImage+Resized.swift
│   │   ├── NSPasteboard.PasteboardType+Types.swift
│   │   ├── NSPoint+DefaultsSerializable.swift
│   │   ├── NSRect+Centered.swift
│   │   ├── NSRunningApplication+WindowFrame.swift
│   │   ├── NSScreen+ForPopup.swift
│   │   ├── NSSize+DefaultsSerializable.swift
│   │   ├── NSSound+Named.swift
│   │   ├── NSWorkspace+ApplicationName.swift
│   │   ├── Sauce+KeyboardShortcuts.swift
│   │   ├── Settings.PaneIdentifier+Panes.swift
│   │   ├── String+Identifiable.swift
│   │   └── String+Shortened.swift
│   ├── FloatingPanel.swift
│   ├── GlobalHotKey.swift
│   ├── HighlightMatch.swift
│   ├── History.xcdatamodeld/
│   │   └── History.xcdatamodel/
│   │       └── contents
│   ├── HistoryItemAction.swift
│   ├── Info.plist
│   ├── Intents/
│   │   ├── AppIntentError.swift
│   │   ├── Clear.swift
│   │   ├── Delete.swift
│   │   ├── Get.swift
│   │   ├── HistoryItemAppEntity.swift
│   │   └── Select.swift
│   ├── ItemsProtocol.swift
│   ├── KeyChord.swift
│   ├── KeyShortcut.swift
│   ├── KeyboardLayout.swift
│   ├── Maccy.entitlements
│   ├── MaccyApp.swift
│   ├── MenuIcon.swift
│   ├── Models/
│   │   ├── HistoryItem.swift
│   │   └── HistoryItemContent.swift
│   ├── Notifier.swift
│   ├── Observables/
│   │   ├── AppState.swift
│   │   ├── Footer.swift
│   │   ├── FooterItem.swift
│   │   ├── History.swift
│   │   ├── HistoryItemDecorator.swift
│   │   ├── ModifierFlags.swift
│   │   ├── NavigationManager.swift
│   │   ├── Popup.swift
│   │   └── SlideoutController.swift
│   ├── PasteStack.swift
│   ├── PinsPosition.swift
│   ├── PopupPosition.swift
│   ├── Search.swift
│   ├── SearchVisibility.swift
│   ├── Selection.swift
│   ├── Settings/
│   │   ├── AdvancedSettingsPane.swift
│   │   ├── AppearanceSettingsPane.swift
│   │   ├── GeneralSettingsPane.swift
│   │   ├── IgnoreSettingsPane/
│   │   │   ├── IgnoreApplicationsSettingsView.swift
│   │   │   ├── IgnorePasteboardTypesSettingsView.swift
│   │   │   └── IgnoreRegexpsSettingsView.swift
│   │   ├── IgnoreSettingsPane.swift
│   │   ├── PinsSettingsPane.swift
│   │   ├── StorageSettingsPane.swift
│   │   ├── ar.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── be.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── bn.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── bs.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ca.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ckb.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── cs.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── de.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── el.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── en.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── eo.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── es.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── fa.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── fr.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── he.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── hi.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── hr.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── hu.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── id.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── it.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ja.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ko.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── lt.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── lv.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── nb.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── nl.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── pl.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── pt-BR.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── pt.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ro.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ru.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── sl.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── sv.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── ta.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── th.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── tr.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── uk.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── uz.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── vi.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   ├── zh-Hans.lproj/
│   │   │   ├── AdvancedSettings.strings
│   │   │   ├── AppearanceSettings.strings
│   │   │   ├── GeneralSettings.strings
│   │   │   ├── IgnoreSettings.strings
│   │   │   ├── PinsSettings.strings
│   │   │   └── StorageSettings.strings
│   │   └── zh-Hant.lproj/
│   │       ├── AdvancedSettings.strings
│   │       ├── AppearanceSettings.strings
│   │       ├── GeneralSettings.strings
│   │       ├── IgnoreSettings.strings
│   │       ├── PinsSettings.strings
│   │       └── StorageSettings.strings
│   ├── SoftwareUpdater.swift
│   ├── Sorter.swift
│   ├── Sounds/
│   │   ├── Knock.caf
│   │   └── Write.caf
│   ├── Storage.swift
│   ├── Storage.xcdatamodeld/
│   │   └── Storage.xcdatamodel/
│   │       └── contents
│   ├── Throttler.swift
│   ├── Views/
│   │   ├── AppImageView.swift
│   │   ├── AsyncView.swift
│   │   ├── ConfirmationView.swift
│   │   ├── ContentView.swift
│   │   ├── FooterItemView.swift
│   │   ├── FooterView.swift
│   │   ├── HeaderView.swift
│   │   ├── HeightReaderModifier.swift
│   │   ├── HistoryItemView.swift
│   │   ├── HistoryListView.swift
│   │   ├── HoverSelectionModifier.swift
│   │   ├── KeyHandlingView.swift
│   │   ├── KeyboardShortcutView.swift
│   │   ├── ListHeaderView.swift
│   │   ├── ListItemTitleView.swift
│   │   ├── ListItemView.swift
│   │   ├── MouseMovedViewModifer.swift
│   │   ├── MultipleSelectionListView.swift
│   │   ├── PasteStackItemView.swift
│   │   ├── PasteStackPreviewView.swift
│   │   ├── PasteStackView.swift
│   │   ├── PinsView.swift
│   │   ├── PreviewItemView.swift
│   │   ├── SearchFieldView.swift
│   │   ├── SlideoutContentView.swift
│   │   ├── SlideoutView.swift
│   │   ├── ToolbarView.swift
│   │   ├── VisualEffectView.swift
│   │   ├── WrappingTextView.swift
│   │   ├── ar.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── be.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── bn.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── bs.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ca.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ckb.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── cs.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── de.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── el.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── en.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── eo.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── es.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── fa.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── fr.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── he.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── hi.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── hr.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── hu.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── id.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── it.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ja.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ko.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── lt.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── lv.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── nb.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── nl.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── pl.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── pt-BR.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── pt.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ro.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ru.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── sl.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── sv.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── ta.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── th.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── tr.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── uk.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── uz.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── vi.lproj/
│   │   │   └── PreviewItemView.strings
│   │   ├── zh-Hans.lproj/
│   │   │   └── PreviewItemView.strings
│   │   └── zh-Hant.lproj/
│   │       └── PreviewItemView.strings
│   ├── ar.lproj/
│   │   └── Localizable.strings
│   ├── be.lproj/
│   │   └── Localizable.strings
│   ├── bn.lproj/
│   │   └── Localizable.strings
│   ├── bs.lproj/
│   │   └── Localizable.strings
│   ├── ca.lproj/
│   │   └── Localizable.strings
│   ├── ckb.lproj/
│   │   └── Localizable.strings
│   ├── cs.lproj/
│   │   ├── Localizable.strings
│   │   └── Preview.strings
│   ├── de.lproj/
│   │   └── Localizable.strings
│   ├── el.lproj/
│   │   └── Localizable.strings
│   ├── en.lproj/
│   │   └── Localizable.strings
│   ├── eo.lproj/
│   │   └── Localizable.strings
│   ├── es.lproj/
│   │   └── Localizable.strings
│   ├── fa.lproj/
│   │   └── Localizable.strings
│   ├── fr.lproj/
│   │   └── Localizable.strings
│   ├── he.lproj/
│   │   └── Localizable.strings
│   ├── hi.lproj/
│   │   └── Localizable.strings
│   ├── hr.lproj/
│   │   └── Localizable.strings
│   ├── hu.lproj/
│   │   └── Localizable.strings
│   ├── id.lproj/
│   │   └── Localizable.strings
│   ├── it.lproj/
│   │   └── Localizable.strings
│   ├── ja.lproj/
│   │   └── Localizable.strings
│   ├── ko.lproj/
│   │   └── Localizable.strings
│   ├── lt.lproj/
│   │   └── Localizable.strings
│   ├── lv.lproj/
│   │   └── Localizable.strings
│   ├── nb.lproj/
│   │   └── Localizable.strings
│   ├── nl.lproj/
│   │   └── Localizable.strings
│   ├── pl.lproj/
│   │   └── Localizable.strings
│   ├── pt-BR.lproj/
│   │   ├── Localizable.strings
│   │   └── Preview.strings
│   ├── pt.lproj/
│   │   └── Localizable.strings
│   ├── ro.lproj/
│   │   └── Localizable.strings
│   ├── ru.lproj/
│   │   └── Localizable.strings
│   ├── sl.lproj/
│   │   └── Localizable.strings
│   ├── sv.lproj/
│   │   └── Localizable.strings
│   ├── ta.lproj/
│   │   └── Localizable.strings
│   ├── th.lproj/
│   │   └── Localizable.strings
│   ├── tr.lproj/
│   │   └── Localizable.strings
│   ├── uk.lproj/
│   │   └── Localizable.strings
│   ├── uz.lproj/
│   │   └── Localizable.strings
│   ├── vi.lproj/
│   │   └── Localizable.strings
│   ├── zh-Hans.lproj/
│   │   └── Localizable.strings
│   └── zh-Hant.lproj/
│       └── Localizable.strings
├── Maccy.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   └── contents.xcworkspacedata
│   └── xcshareddata/
│       └── xcschemes/
│           └── Maccy.xcscheme
├── Maccy.xctestplan
├── MaccyTests/
│   ├── ClipboardTests.swift
│   ├── ColorImageTests.swift
│   ├── HistoryDecoratorTests.swift
│   ├── HistoryItemTests.swift
│   ├── HistoryTests.swift
│   ├── Info.plist
│   ├── SearchTests.swift
│   └── SorterTests.swift
├── MaccyUITests/
│   ├── Info.plist
│   └── MaccyUITests.swift
├── README.md
├── appcast.xml
└── docs/
    └── keyboard-shortcut-password-fields.md
Condensed preview — 502 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (840K chars).
[
  {
    "path": ".bartycrouch.toml",
    "chars": 807,
    "preview": "[update]\ntasks = [\"interfaces\", \"translate\", \"normalize\"]\n\n[update.interfaces]\npaths = [\"Maccy\"]\nsubpathsToIgnore = [\".g"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 24,
    "preview": "buy_me_a_coffee: p0deje\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 1759,
    "preview": "---\nname: 🐛 Bug Report\ndescription: Submit a Bug Report\nlabels: [bug]\nbody:\n  - type: markdown\n    attributes:\n      val"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 27,
    "preview": "blank_issues_enabled: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "chars": 1007,
    "preview": "---\nname: 💪 Feature request\ndescription: Suggest an idea for this project\nlabels: [enhancement]\nbody:\n  - type: checkbox"
  },
  {
    "path": ".gitignore",
    "chars": 93,
    "preview": "xcuserdata/\nMaccy.xcodeproj/project.xcworkspace/xcshareddata\n.idea\n.DS_Store\nMaccy/.DS_Store\n"
  },
  {
    "path": ".periphery.yml",
    "chars": 88,
    "preview": "project: Maccy.xcodeproj\nretain_objc_accessible: true\nschemes:\n- Maccy\ntargets:\n- Maccy\n"
  },
  {
    "path": ".swiftlint.yml",
    "chars": 147,
    "preview": "disabled_rules:\n  - multiple_closures_with_trailing_closure\n  - non_optional_string_data_conversion\n  - todo\nline_length"
  },
  {
    "path": "Designs/Copies.txt",
    "chars": 103,
    "preview": "Hello! 👋\nThis is Maccy.\nClipboard manager for Mac. 💻\nSearch as you type. 🔍\nOpen source. ⚙️\nNo fluff! 😛\n"
  },
  {
    "path": "Designs/Instructions.pxd/data/selectionForContentTransform/meta",
    "chars": 802,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Designs/Instructions.pxd/data/selectionForContentTransform/shapeSelection/meta",
    "chars": 319,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Designs/Storage-Types.pxd/data/selection/meta",
    "chars": 737,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Designs/Storage-Types.pxd/data/selection/shapeSelection/meta",
    "chars": 319,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Designs/Storage-Types.pxd/data/selectionForContentTransform/meta",
    "chars": 737,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Designs/Storage-Types.pxd/data/selectionForContentTransform/shapeSelection/meta",
    "chars": 319,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "LICENSE",
    "chars": 1080,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2025 Alex Rodionov\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "Maccy/About.swift",
    "chars": 1927,
    "preview": "import Cocoa\n\nclass About {\n  private let familyCredits = NSAttributedString(\n    string: \"Special thank you to Tonia, A"
  },
  {
    "path": "Maccy/Accessibility.swift",
    "chars": 188,
    "preview": "import AppKit\n\nstruct Accessibility {\n  private static var allowed: Bool { AXIsProcessTrustedWithOptions(nil) }\n\n  stati"
  },
  {
    "path": "Maccy/AppDelegate.swift",
    "chars": 5684,
    "preview": "import Defaults\nimport KeyboardShortcuts\nimport Sparkle\nimport SwiftUI\n\nclass AppDelegate: NSObject, NSApplicationDelega"
  },
  {
    "path": "Maccy/AppStoreReview.swift",
    "chars": 597,
    "preview": "import StoreKit\nimport Defaults\n\nclass AppStoreReview {\n  class func ask() {\n    Defaults[.numberOfUsages] += 1\n    guar"
  },
  {
    "path": "Maccy/ApplicationImage.swift",
    "chars": 2371,
    "preview": "import Defaults\nimport SwiftUI\n\nclass ApplicationImage {\n  fileprivate static let fallbackImage = NSImage(\n    systemSym"
  },
  {
    "path": "Maccy/ApplicationImageCache.swift",
    "chars": 898,
    "preview": "class ApplicationImageCache {\n  static let shared = ApplicationImageCache()\n\n  private let universalClipboardIdentifier:"
  },
  {
    "path": "Maccy/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1397,
    "preview": "{\n  \"images\" : [\n    {\n      \"filename\" : \"AppIcon (Big Sur)-16w.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\",\n    "
  },
  {
    "path": "Maccy/Assets.xcassets/Contents.json",
    "chars": 63,
    "preview": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "Maccy/Assets.xcassets/StatusBarMenuImage.imageset/Contents.json",
    "chars": 786,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"mac\",\n      \"filename\" : \"DarkMenuBar-16w.png\",\n      \"scale\" : \"1x\"\n    },\n    "
  },
  {
    "path": "Maccy/Assets.xcassets/clipboard.fill.imageset/Contents.json",
    "chars": 815,
    "preview": "{\n  \"images\" : [\n    {\n      \"filename\" : \"clipboard.fill.light_16.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\"\n   "
  },
  {
    "path": "Maccy/Assets.xcassets/paperclip.imageset/Contents.json",
    "chars": 730,
    "preview": "{\n  \"images\" : [\n    {\n      \"filename\" : \"clip.fill.light_16.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\"\n    },\n "
  },
  {
    "path": "Maccy/Assets.xcassets/scissors.imageset/Contents.json",
    "chars": 791,
    "preview": "{\n  \"images\" : [\n    {\n      \"filename\" : \"scissors_light_16.png\",\n      \"idiom\" : \"mac\",\n      \"scale\" : \"1x\"\n    },\n  "
  },
  {
    "path": "Maccy/Clipboard.swift",
    "chars": 10297,
    "preview": "import AppKit\nimport Defaults\nimport Sauce\n\nclass Clipboard {\n  static let shared = Clipboard()\n\n  typealias OnNewCopyHo"
  },
  {
    "path": "Maccy/ColorImage.swift",
    "chars": 390,
    "preview": "import AppKit\nimport SwiftHEXColors\n\nclass ColorImage {\n  static func from(_ colorHex: String) -> NSImage? {\n    guard l"
  },
  {
    "path": "Maccy/Extensions/Collection+Surrounding.swift",
    "chars": 2230,
    "preview": "extension Collection where Element: Equatable {\n  func item(after: Element, where predicate: (Element) -> Bool) -> Eleme"
  },
  {
    "path": "Maccy/Extensions/Color+Random.swift",
    "chars": 269,
    "preview": "import SwiftUI\n\n// Useful to debug SwiftUI view redraws: .background(.random).\nextension ShapeStyle where Self == Color "
  },
  {
    "path": "Maccy/Extensions/Defaults.Keys+Names.swift",
    "chars": 3517,
    "preview": "import AppKit\nimport Defaults\n\nstruct StorageType {\n  static let files = StorageType(types: [.fileURL])\n  static let ima"
  },
  {
    "path": "Maccy/Extensions/Dictionary+RemoveItem.swift",
    "chars": 276,
    "preview": "extension Dictionary {\n  // Removes all key-value pairs where the value satisfies the given predicate.\n  mutating func r"
  },
  {
    "path": "Maccy/Extensions/KeyEquivalent+Keys.swift",
    "chars": 93,
    "preview": "import SwiftUI\n\nextension KeyEquivalent {\n  static let backspace = KeyEquivalent(\"\\u{7F}\")\n}\n"
  },
  {
    "path": "Maccy/Extensions/KeyboardShortcuts.Name+Shortcuts.swift",
    "chars": 416,
    "preview": "import KeyboardShortcuts\n\nextension KeyboardShortcuts.Name {\n  static let popup = Self(\"popup\", default: Shortcut(.c, mo"
  },
  {
    "path": "Maccy/Extensions/ModifierFlags+Description.swift",
    "chars": 621,
    "preview": "import AppKit.NSEvent\nimport Carbon.HIToolbox\n\n// https://github.com/sindresorhus/KeyboardShortcuts/blob/e6b60117ec266e1"
  },
  {
    "path": "Maccy/Extensions/NSApplication+Windows.swift",
    "chars": 223,
    "preview": "import AppKit\n\nextension NSApplication {\n  var alertWindow: NSWindow? { windows.first { $0.className == \"_NSAlertPanel\" "
  },
  {
    "path": "Maccy/Extensions/NSImage+Names.swift",
    "chars": 921,
    "preview": "import Cocoa\n\nextension NSImage {\n  static let gearshape = NSImage(systemSymbolName: \"gearshape\", accessibilityDescripti"
  },
  {
    "path": "Maccy/Extensions/NSImage+Resized.swift",
    "chars": 886,
    "preview": "import AppKit.NSImage\n\n// Based on https://stackoverflow.com/questions/73062803/resizing-nsimage-keeping-aspect-ratio-re"
  },
  {
    "path": "Maccy/Extensions/NSPasteboard.PasteboardType+Types.swift",
    "chars": 2155,
    "preview": "import AppKit.NSPasteboard\nimport Defaults\n\nextension NSPasteboard.PasteboardType: Defaults.Serializable {\n  static let "
  },
  {
    "path": "Maccy/Extensions/NSPoint+DefaultsSerializable.swift",
    "chars": 100,
    "preview": "import CoreGraphics\nimport Defaults\nimport Foundation\n\nextension NSPoint: Defaults.Serializable {\n}\n"
  },
  {
    "path": "Maccy/Extensions/NSRect+Centered.swift",
    "chars": 355,
    "preview": "import Foundation\n\nextension NSRect {\n  static func centered(ofSize size: NSSize, in frame: NSRect) -> NSRect {\n    let "
  },
  {
    "path": "Maccy/Extensions/NSRunningApplication+WindowFrame.swift",
    "chars": 1257,
    "preview": "import AppKit.NSRunningApplication\nimport Carbon\n\nextension NSRunningApplication {\n  var windowFrame: NSRect? {\n    let "
  },
  {
    "path": "Maccy/Extensions/NSScreen+ForPopup.swift",
    "chars": 314,
    "preview": "import AppKit.NSScreen\nimport Defaults\n\nextension NSScreen {\n  static var forPopup: NSScreen? {\n    let desiredScreen = "
  },
  {
    "path": "Maccy/Extensions/NSSize+DefaultsSerializable.swift",
    "chars": 99,
    "preview": "import CoreGraphics\nimport Defaults\nimport Foundation\n\nextension NSSize: Defaults.Serializable {\n}\n"
  },
  {
    "path": "Maccy/Extensions/NSSound+Named.swift",
    "chars": 299,
    "preview": "import AppKit.NSSound\n\nextension NSSound {\n  static let knock = NSSound(\n    contentsOf: Bundle.main.url(forResource: \"K"
  },
  {
    "path": "Maccy/Extensions/NSWorkspace+ApplicationName.swift",
    "chars": 455,
    "preview": "import AppKit.NSWorkspace\n\nextension NSWorkspace {\n  func applicationName(url: URL) -> String {\n    if let bundle = Bund"
  },
  {
    "path": "Maccy/Extensions/Sauce+KeyboardShortcuts.swift",
    "chars": 280,
    "preview": "import KeyboardShortcuts\nimport Sauce\n\nextension Sauce {\n  func key(shortcut: KeyboardShortcuts.Name) -> Key? {\n    if l"
  },
  {
    "path": "Maccy/Extensions/Settings.PaneIdentifier+Panes.swift",
    "chars": 289,
    "preview": "import Settings\n\nextension Settings.PaneIdentifier {\n  static let advanced = Self(\"advanced\")\n  static let appearance = "
  },
  {
    "path": "Maccy/Extensions/String+Identifiable.swift",
    "chars": 79,
    "preview": "extension String: @retroactive Identifiable {\n  public var id: Self { self }\n}\n"
  },
  {
    "path": "Maccy/Extensions/String+Shortened.swift",
    "chars": 200,
    "preview": "extension String {\n  func shortened(to maxLength: Int) -> String {\n    guard count > maxLength else {\n      return self\n"
  },
  {
    "path": "Maccy/FloatingPanel.swift",
    "chars": 6580,
    "preview": "import Defaults\nimport SwiftUI\n\n// An NSPanel subclass that implements floating panel traits.\n// https://stackoverflow.c"
  },
  {
    "path": "Maccy/GlobalHotKey.swift",
    "chars": 512,
    "preview": "import AppKit\nimport KeyboardShortcuts\nimport Sauce\nimport SwiftUI\n\nclass GlobalHotKey {\n  typealias Handler = () -> Voi"
  },
  {
    "path": "Maccy/HighlightMatch.swift",
    "chars": 757,
    "preview": "import Foundation\nimport Defaults\n\nenum HighlightMatch: String, CaseIterable, Identifiable, CustomStringConvertible, Def"
  },
  {
    "path": "Maccy/History.xcdatamodeld/History.xcdatamodel/contents",
    "chars": 301,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<model type=\"com.apple.IDECoreDataModeler.DataModel\" documentVer"
  },
  {
    "path": "Maccy/HistoryItemAction.swift",
    "chars": 2990,
    "preview": "import AppKit.NSEvent\nimport Defaults\n\nenum HistoryItemAction {\n  case unknown\n  case copy\n  case paste\n  case pasteWith"
  },
  {
    "path": "Maccy/Info.plist",
    "chars": 1276,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Maccy/Intents/AppIntentError.swift",
    "chars": 254,
    "preview": "import Foundation\n\nenum AppIntentError: Swift.Error, CustomLocalizedStringResourceConvertible {\n  case notFound\n\n  var l"
  },
  {
    "path": "Maccy/Intents/Clear.swift",
    "chars": 625,
    "preview": "import AppIntents\nimport Defaults\n\nstruct Clear: AppIntent, CustomIntentMigratedAppIntent {\n  static let intentClassName"
  },
  {
    "path": "Maccy/Intents/Delete.swift",
    "chars": 823,
    "preview": "import AppIntents\n\nstruct Delete: AppIntent, CustomIntentMigratedAppIntent {\n  static let intentClassName = \"DeleteInten"
  },
  {
    "path": "Maccy/Intents/Get.swift",
    "chars": 1896,
    "preview": "import Foundation\nimport AppIntents\n\nstruct Get: AppIntent, CustomIntentMigratedAppIntent {\n  static let intentClassName"
  },
  {
    "path": "Maccy/Intents/HistoryItemAppEntity.swift",
    "chars": 516,
    "preview": "import AppIntents\n\nstruct HistoryItemAppEntity: TransientAppEntity {\n  static var typeDisplayRepresentation = TypeDispla"
  },
  {
    "path": "Maccy/Intents/Select.swift",
    "chars": 1030,
    "preview": "import AppIntents\n\nstruct Select: AppIntent, CustomIntentMigratedAppIntent {\n  static let intentClassName = \"SelectInten"
  },
  {
    "path": "Maccy/ItemsProtocol.swift",
    "chars": 1406,
    "preview": "protocol HasVisibility {\n  var isVisible: Bool { get }\n}\n\nprotocol ItemsContainer {\n  associatedtype Item\n  var containe"
  },
  {
    "path": "Maccy/KeyChord.swift",
    "chars": 4434,
    "preview": "import AppKit.NSEvent\nimport KeyboardShortcuts\nimport Sauce\n\nenum KeyChord: CaseIterable {\n  static var pasteKey: Key { "
  },
  {
    "path": "Maccy/KeyShortcut.swift",
    "chars": 1269,
    "preview": "import AppKit.NSEvent\nimport Defaults\nimport Sauce\n\nstruct KeyShortcut: Identifiable {\n  static func create(character: S"
  },
  {
    "path": "Maccy/KeyboardLayout.swift",
    "chars": 701,
    "preview": "import Carbon\nimport Sauce\n\nclass KeyboardLayout {\n  static var current: KeyboardLayout { KeyboardLayout() }\n\n  // Dvora"
  },
  {
    "path": "Maccy/Maccy.entitlements",
    "chars": 516,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Maccy/MaccyApp.swift",
    "chars": 408,
    "preview": "import SwiftUI\n\n@main\nstruct MaccyApp: App {\n  @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate\n\n  // It'"
  },
  {
    "path": "Maccy/MenuIcon.swift",
    "chars": 495,
    "preview": "import AppKit\nimport Defaults\n\nenum MenuIcon: String, CaseIterable, Identifiable, Defaults.Serializable {\n  case maccy\n "
  },
  {
    "path": "Maccy/Models/HistoryItem.swift",
    "chars": 7050,
    "preview": "import AppKit\nimport Defaults\nimport Sauce\nimport SwiftData\nimport Vision\n\n@Model\nclass HistoryItem {\n  static var suppo"
  },
  {
    "path": "Maccy/Models/HistoryItemContent.swift",
    "chars": 249,
    "preview": "import Foundation\nimport SwiftData\n\n@Model\nclass HistoryItemContent {\n  var type: String = \"\"\n  var value: Data?\n\n  @Rel"
  },
  {
    "path": "Maccy/Notifier.swift",
    "chars": 1185,
    "preview": "import AppKit\nimport UserNotifications\n\nclass Notifier {\n  private static var center: UNUserNotificationCenter { UNUserN"
  },
  {
    "path": "Maccy/Observables/AppState.swift",
    "chars": 5031,
    "preview": "import AppKit\nimport Defaults\nimport Foundation\nimport Settings\nimport SwiftUI\n\n@Observable\nclass AppState: Sendable {\n "
  },
  {
    "path": "Maccy/Observables/Footer.swift",
    "chars": 2116,
    "preview": "import Defaults\nimport SwiftUI\n\n@Observable\nclass Footer: ItemsContainer {\n  var items: [FooterItem] = []\n\n  var selecte"
  },
  {
    "path": "Maccy/Observables/FooterItem.swift",
    "chars": 1082,
    "preview": "import SwiftUI\n\n@Observable\nclass FooterItem: Equatable, Identifiable, HasVisibility {\n  struct Confirmation {\n    var m"
  },
  {
    "path": "Maccy/Observables/History.swift",
    "chars": 14040,
    "preview": "// swiftlint:disable file_length\nimport AppKit.NSRunningApplication\nimport Defaults\nimport Foundation\nimport Logging\nimp"
  },
  {
    "path": "Maccy/Observables/HistoryItemDecorator.swift",
    "chars": 5434,
    "preview": "import AppKit.NSWorkspace\nimport Defaults\nimport Foundation\nimport Observation\nimport Sauce\n\n@Observable\nclass HistoryIt"
  },
  {
    "path": "Maccy/Observables/ModifierFlags.swift",
    "chars": 310,
    "preview": "import AppKit.NSEvent\nimport Defaults\n\n@Observable\nclass ModifierFlags {\n  var flags: NSEvent.ModifierFlags = []\n\n  init"
  },
  {
    "path": "Maccy/Observables/NavigationManager.swift",
    "chars": 9230,
    "preview": "import Foundation\nimport SwiftUI\n\n@Observable\nclass NavigationManager { // swiftlint:disable:this type_body_length\n  pri"
  },
  {
    "path": "Maccy/Observables/Popup.swift",
    "chars": 5497,
    "preview": "import AppKit.NSRunningApplication\nimport Defaults\nimport KeyboardShortcuts\nimport Observation\n\nenum PopupState {\n  // D"
  },
  {
    "path": "Maccy/Observables/SlideoutController.swift",
    "chars": 6609,
    "preview": "import Defaults\nimport Logging\nimport Observation\nimport SwiftUI\n\nenum SlideoutState {\n  case opening\n  case closing\n  c"
  },
  {
    "path": "Maccy/PasteStack.swift",
    "chars": 1409,
    "preview": "import Foundation\nimport AppKit\n\n@Observable\nclass PasteStack: Identifiable, Hashable {\n  private static var listener: A"
  },
  {
    "path": "Maccy/PinsPosition.swift",
    "chars": 462,
    "preview": "import Foundation\nimport Defaults\n\nenum PinsPosition: String, CaseIterable, Identifiable, CustomStringConvertible, Defau"
  },
  {
    "path": "Maccy/PopupPosition.swift",
    "chars": 2476,
    "preview": "import AppKit.NSEvent\nimport Defaults\nimport Foundation\n\nenum PopupPosition: String, CaseIterable, Identifiable, CustomS"
  },
  {
    "path": "Maccy/Search.swift",
    "chars": 4027,
    "preview": "import AppKit\nimport Defaults\nimport Fuse\n\nclass Search {\n  enum Mode: String, CaseIterable, Identifiable, CustomStringC"
  },
  {
    "path": "Maccy/SearchVisibility.swift",
    "chars": 515,
    "preview": "import Defaults\nimport Foundation\n\nenum SearchVisibility: String, CaseIterable, Identifiable, CustomStringConvertible, D"
  },
  {
    "path": "Maccy/Selection.swift",
    "chars": 632,
    "preview": "import AppKit\n\nstruct Selection<Item: Equatable> {\n  var items: [Item]\n\n  init(items: [Item] = []) {\n    self.items = it"
  },
  {
    "path": "Maccy/Settings/AdvancedSettingsPane.swift",
    "chars": 1701,
    "preview": "import SwiftUI\nimport Defaults\n\nstruct AdvancedSettingsPane: View {\n  var body: some View {\n    VStack(alignment: .leadi"
  },
  {
    "path": "Maccy/Settings/AppearanceSettingsPane.swift",
    "chars": 7325,
    "preview": "import AppKit\nimport SwiftUI\nimport Defaults\nimport Settings\n\nstruct AppearanceSettingsPane: View {\n  @Default(.popupPos"
  },
  {
    "path": "Maccy/Settings/GeneralSettingsPane.swift",
    "chars": 4249,
    "preview": "import SwiftUI\nimport Defaults\nimport KeyboardShortcuts\nimport LaunchAtLogin\nimport Settings\n\nstruct GeneralSettingsPane"
  },
  {
    "path": "Maccy/Settings/IgnoreSettingsPane/IgnoreApplicationsSettingsView.swift",
    "chars": 2528,
    "preview": "import SwiftUI\nimport Defaults\n\nstruct IgnoreApplicationsSettingsView: View {\n  @Default(.ignoredApps) private var ignor"
  },
  {
    "path": "Maccy/Settings/IgnoreSettingsPane/IgnorePasteboardTypesSettingsView.swift",
    "chars": 1792,
    "preview": "import Defaults\nimport SwiftUI\n\nstruct IgnorePasteboardTypesSettingsView: View {\n  @Default(.ignoredPasteboardTypes) pri"
  },
  {
    "path": "Maccy/Settings/IgnoreSettingsPane/IgnoreRegexpsSettingsView.swift",
    "chars": 1483,
    "preview": "import SwiftUI\nimport Defaults\n\nstruct IgnoreRegexpsSettingsView: View {\n  @Default(.ignoreRegexp) private var ignoredRe"
  },
  {
    "path": "Maccy/Settings/IgnoreSettingsPane.swift",
    "chars": 634,
    "preview": "import SwiftUI\n\nstruct IgnoreSettingsPane: View {\n  var body: some View {\n    TabView {\n      IgnoreApplicationsSettings"
  },
  {
    "path": "Maccy/Settings/PinsSettingsPane.swift",
    "chars": 5180,
    "preview": "import SwiftData\nimport SwiftUI\n\nstruct PinPickerView: View {\n  @Bindable var item: HistoryItem\n  var availablePins: [St"
  },
  {
    "path": "Maccy/Settings/StorageSettingsPane.swift",
    "chars": 3683,
    "preview": "import SwiftUI\nimport Defaults\nimport Settings\n\nstruct StorageSettingsPane: View {\n  @Observable\n  class ViewModel {\n   "
  },
  {
    "path": "Maccy/Settings/ar.lproj/AdvancedSettings.strings",
    "chars": 834,
    "preview": "\"Title\" = \"متقدم\";\n\"TurnOff\" = \"إيقاف\";\n\"TurnOffDescription\" = \"تجاهل جميع النسخ الجديدة مؤقتًا.\\nمن المرجح أن تستخدمه ب"
  },
  {
    "path": "Maccy/Settings/ar.lproj/AppearanceSettings.strings",
    "chars": 1746,
    "preview": "\"Title\" = \"المظهر\";\n\"PopupAt\" = \"ظهور الإنبثاق عند:\";\n\"PopupAtCursor\" = \"المؤشر\";\n\"PopupAtMenuBarIcon\" = \"أيقونة القائمة"
  },
  {
    "path": "Maccy/Settings/ar.lproj/GeneralSettings.strings",
    "chars": 1150,
    "preview": "\"Title\" = \"عام\";\n\"LaunchAtLogin\" = \"التشغيل عند تسجيل الدخول\";\n\"CheckForUpdates\" = \"التحقق من التحديثات تلقائيًا\";\n\"Chec"
  },
  {
    "path": "Maccy/Settings/ar.lproj/IgnoreSettings.strings",
    "chars": 744,
    "preview": "\"Title\" = \"تجاهل\";\n\"ApplicationsTab\" = \"التطبيقات\";\n\"IgnoredAppsDescription\" = \"من الممكن تجاهل النسخ القادمة من بعض الت"
  },
  {
    "path": "Maccy/Settings/ar.lproj/PinsSettings.strings",
    "chars": 406,
    "preview": "\"Title\" = \"مثبتة\";\n\"Key\" = \"المفتاح\";\n\"Alias\" = \"العنوان\";\n\"Content\" = \"المحتوى\";\n\"ContentIsNotText\" = \"محتوى غير قابل ل"
  },
  {
    "path": "Maccy/Settings/ar.lproj/StorageSettings.strings",
    "chars": 492,
    "preview": "\"Title\" = \"التخزين\";\n\"Save\" = \"حفظ:\";\n\"Files\" = \"الملفات\";\n\"Images\" = \"الصور\";\n\"Text\" = \"النصوص\";\n\"SaveDescription\" = \"ت"
  },
  {
    "path": "Maccy/Settings/be.lproj/AdvancedSettings.strings",
    "chars": 980,
    "preview": "\"Title\" = \"Прасунутыя\";\n\"TurnOff\" = \"Выключыць\";\n\"TurnOffShellScript\" = \"defaults write org.p0deje.Maccy ignoreEvents tr"
  },
  {
    "path": "Maccy/Settings/be.lproj/AppearanceSettings.strings",
    "chars": 1907,
    "preview": "\"Title\" = \"Выгляд\";\n\"PopupAtMenuBarIcon\" = \"Значка меню\";\n\"PopupAtWindowCenter\" = \"Цэнтра акна\";\n\"PopupAtScreenCenter\" ="
  },
  {
    "path": "Maccy/Settings/be.lproj/GeneralSettings.strings",
    "chars": 1320,
    "preview": "\"LaunchAtLogin\" = \"Запускаць пры логіне\";\n\"CheckNow\" = \"Праверыць зараз\";\n\"Open\" = \"Адчыніць:\";\n\"PinTooltip\" = \"Гарачая "
  },
  {
    "path": "Maccy/Settings/be.lproj/IgnoreSettings.strings",
    "chars": 818,
    "preview": "\"IgnoredAppsDescription\" = \"Капіяванні з пэўных дадаткаў можна ігнараваць.\\nКалі ласка ўлічвайце, што гэтае вырашэнне не"
  },
  {
    "path": "Maccy/Settings/be.lproj/PinsSettings.strings",
    "chars": 465,
    "preview": "\"Title\" = \"Замацаваныя\";\n\"Key\" = \"Клавіша\";\n\"Alias\" = \"Назва\";\n\"Content\" = \"Кантэнт\";\n\"ContentIsNotText\" = \"Нерэдагаваль"
  },
  {
    "path": "Maccy/Settings/be.lproj/StorageSettings.strings",
    "chars": 538,
    "preview": "\"Save\" = \"Захоўваць:\";\n\"Files\" = \"Файлы\";\n\"Images\" = \"Выявы\";\n\"Text\" = \"Тэкст\";\n\"SaveDescription\" = \"Змяніць тыпы элемен"
  },
  {
    "path": "Maccy/Settings/bn.lproj/AdvancedSettings.strings",
    "chars": 974,
    "preview": "\"ClearHistoryOnQuit\" = \"বন্ধ করে ছেড়ে যাওয়ার সময় ইতিহাস সাফ করুন\";\n\"ClearHistoryOnQuitTooltip\" = \"অ্যাপ্লিকেশনটি ছাড়ার "
  },
  {
    "path": "Maccy/Settings/bn.lproj/AppearanceSettings.strings",
    "chars": 901,
    "preview": "\"Title\" = \"\";\n\"PopupAt\" = \"\";\n\"PopupAtCursor\" = \"\";\n\"PopupAtMenuBarIcon\" = \"\";\n\"PopupAtWindowCenter\" = \"\";\n\"PopupAtScree"
  },
  {
    "path": "Maccy/Settings/bn.lproj/GeneralSettings.strings",
    "chars": 1117,
    "preview": "\"CheckForUpdates\" = \"স্বয়ংক্রিয়ভাবে আপডেটের জন্য সন্ধান করুন\";\n\"Title\" = \"সাধারণ\";\n\"LaunchAtLogin\" = \"লগইন করার সময় চ"
  },
  {
    "path": "Maccy/Settings/bn.lproj/IgnoreSettings.strings",
    "chars": 843,
    "preview": "\"Title\" = \"উপেক্ষা করুন\";\n\"ApplicationsTab\" = \"অ্যাপ্লিকেশন\";\n\"IgnoredAppsDescription\" = \"নির্দিষ্ট অ্যাপ্লিকেশন থেকে আস"
  },
  {
    "path": "Maccy/Settings/bn.lproj/PinsSettings.strings",
    "chars": 296,
    "preview": "\"Key\" = \"মূল শব্দ\";\n\"Alias\" = \"শিরোনাম\";\n\"PinCustomizationDescription\" = \"আপনি প্রতিটি আলপিন করা আইটেমের শিরোনাম এবং হটক"
  },
  {
    "path": "Maccy/Settings/bn.lproj/StorageSettings.strings",
    "chars": 256,
    "preview": "\"Title\" = \"\";\n\"Save\" = \"\";\n\"Files\" = \"\";\n\"Images\" = \"\";\n\"Text\" = \"\";\n\"SaveDescription\" = \"\";\n\"Size\" = \"\";\n\"SizeTooltip\" "
  },
  {
    "path": "Maccy/Settings/bs.lproj/AdvancedSettings.strings",
    "chars": 942,
    "preview": "\"Title\" = \"Napredno\";\n\"TurnOff\" = \"Ugasi\";\n\"TurnOffDescription\" = \"Privremeno zanemari sve nove kopije.\\nKoristi program"
  },
  {
    "path": "Maccy/Settings/bs.lproj/AppearanceSettings.strings",
    "chars": 1862,
    "preview": "\"Title\" = \"Izgled\";\n\"PopupAt\" = \"Popup na:\";\n\"PopupAtCursor\" = \"Kursor\";\n\"PopupAtMenuBarIcon\" = \"Meni ikona\";\n\"PopupAtWi"
  },
  {
    "path": "Maccy/Settings/bs.lproj/GeneralSettings.strings",
    "chars": 1270,
    "preview": "\"Title\" = \"Opšte\";\n\"LaunchAtLogin\" = \"Započni aplikacjiu pri prijavi\";\n\"CheckForUpdates\" = \"Provjeri dostupna ažuriranja"
  },
  {
    "path": "Maccy/Settings/bs.lproj/IgnoreSettings.strings",
    "chars": 859,
    "preview": "\"Title\" = \"Ignoriši\";\n\"ApplicationsTab\" = \"Aplikacije\";\n\"IgnoredAppsDescription\" = \"Moguće je zanemariti kopije koje dol"
  },
  {
    "path": "Maccy/Settings/bs.lproj/PinsSettings.strings",
    "chars": 463,
    "preview": "\"Title\" = \"Zakačke\";\n\"Key\" = \"Dugme\";\n\"Alias\" = \"Naziv\";\n\"Content\" = \"Sadržaj\";\n\"ContentIsNotText\" = \"Sadržaj koji se ne"
  },
  {
    "path": "Maccy/Settings/bs.lproj/StorageSettings.strings",
    "chars": 526,
    "preview": "\"Title\" = \"Pohrana\";\n\"Save\" = \"Snimi:\";\n\"Files\" = \"Datoteke\";\n\"Images\" = \"Slike\";\n\"Text\" = \"Tekst\";\n\"SaveDescription\" = "
  },
  {
    "path": "Maccy/Settings/ca.lproj/AdvancedSettings.strings",
    "chars": 279,
    "preview": "\"Title\" = \"\";\n\"TurnOff\" = \"\";\n\"TurnOffDescription\" = \"\";\n\"TurnOffShellScript\" = \"\";\n\"TurnOffViaMenuIconDescription\" = \"\""
  },
  {
    "path": "Maccy/Settings/ca.lproj/AppearanceSettings.strings",
    "chars": 901,
    "preview": "\"Title\" = \"\";\n\"PopupAt\" = \"\";\n\"PopupAtCursor\" = \"\";\n\"PopupAtMenuBarIcon\" = \"\";\n\"PopupAtWindowCenter\" = \"\";\n\"PopupAtScree"
  },
  {
    "path": "Maccy/Settings/ca.lproj/GeneralSettings.strings",
    "chars": 420,
    "preview": "\"Title\" = \"\";\n\"LaunchAtLogin\" = \"\";\n\"CheckForUpdates\" = \"\";\n\"CheckNow\" = \"\";\n\"Open\" = \"\";\n\"OpenTooltip\" = \"\";\n\"Pin\" = \"\""
  },
  {
    "path": "Maccy/Settings/ca.lproj/IgnoreSettings.strings",
    "chars": 261,
    "preview": "\"Title\" = \"\";\n\"ApplicationsTab\" = \"\";\n\"IgnoredAppsDescription\" = \"\";\n\"IgnoredAllAppsExceptListed\" = \"\";\n\"PasteboardTypes"
  },
  {
    "path": "Maccy/Settings/ca.lproj/PinsSettings.strings",
    "chars": 145,
    "preview": "\"Title\" = \"\";\n\"Key\" = \"\";\n\"Alias\" = \"\";\n\"Content\" = \"\";\n\"ContentIsNotText\" = \"\";\n\"RichTextEditWarning\" = \"\";\n\"PinCustomi"
  },
  {
    "path": "Maccy/Settings/ca.lproj/StorageSettings.strings",
    "chars": 526,
    "preview": "\"Title\" = \"Emmagatzematge\";\n\"Save\" = \"Desa:\";\n\"Files\" = \"Arxius\";\n\"Images\" = \"Imatges\";\n\"Text\" = \"Text\";\n\"FirstCopiedAt\""
  },
  {
    "path": "Maccy/Settings/ckb.lproj/AdvancedSettings.strings",
    "chars": 971,
    "preview": "\"Title\" = \"پێشکەوتوو\";\n\"TurnOff\" = \"ناچالاککردن\";\n\"TurnOffDescription\" = \"پشتگوێخستنی کاتیی هەموو کۆپییە نوێیەکان.\\nئەگە"
  },
  {
    "path": "Maccy/Settings/ckb.lproj/AppearanceSettings.strings",
    "chars": 1818,
    "preview": "\"Title\" = \"ڕووکار\";\n\"PopupAt\" = \"شوێنی دەرکەوتنی پۆپئەپ:\";\n\"PopupAtCursor\" = \"نیشاندەر\";\n\"PopupAtMenuBarIcon\" = \"ئایکۆنی"
  },
  {
    "path": "Maccy/Settings/ckb.lproj/GeneralSettings.strings",
    "chars": 1291,
    "preview": "\"Title\" = \"گشتی\";\n\"LaunchAtLogin\" = \"کارپێکردن لەکاتی چوونەژوورەوەدا\";\n\"CheckForUpdates\" = \"پشکنینی خۆکارانە بۆ نوێکاریی"
  },
  {
    "path": "Maccy/Settings/ckb.lproj/IgnoreSettings.strings",
    "chars": 868,
    "preview": "\"Title\" = \"پشتگوێخستن\";\n\"ApplicationsTab\" = \"بەرنامەکان\";\n\"IgnoredAppsDescription\" = \"دەکرێت ئەو کۆپیانەی لە هەندێک بەرن"
  },
  {
    "path": "Maccy/Settings/ckb.lproj/PinsSettings.strings",
    "chars": 465,
    "preview": "\"Title\" = \"چەسپێنراوەکان\";\n\"Key\" = \"دوگمە\";\n\"Alias\" = \"ناونیشان\";\n\"Content\" = \"ناوەڕۆک\";\n\"ContentIsNotText\" = \"ناوەڕۆکی "
  },
  {
    "path": "Maccy/Settings/ckb.lproj/StorageSettings.strings",
    "chars": 520,
    "preview": "\"Title\" = \"کۆگا\";\n\"Save\" = \"پاشەکەوتکردن:\";\n\"Files\" = \"فایلەکان\";\n\"Images\" = \"وێنەکان\";\n\"Text\" = \"دەق\";\n\"SaveDescription"
  },
  {
    "path": "Maccy/Settings/cs.lproj/AdvancedSettings.strings",
    "chars": 916,
    "preview": "\"Title\" = \"Pokročilé\";\n\"TurnOff\" = \"Vypnout\";\n\"TurnOffDescription\" = \"Dočasně ignorovat všechny nové kopie.\\nPravděpodob"
  },
  {
    "path": "Maccy/Settings/cs.lproj/AppearanceSettings.strings",
    "chars": 1782,
    "preview": "\"Title\" = \"Vzhled\";\n\"PopupAt\" = \"Zobrazovat popup vedle:\";\n\"PopupAtCursor\" = \"Kurzoru\";\n\"PopupAtMenuBarIcon\" = \"Menu iko"
  },
  {
    "path": "Maccy/Settings/cs.lproj/GeneralSettings.strings",
    "chars": 1256,
    "preview": "\"Title\" = \"Obecné\";\n\"LaunchAtLogin\" = \"Spustit při přihlášení\";\n\"CheckForUpdates\" = \"Automaticky kontrolovat aktualizace"
  },
  {
    "path": "Maccy/Settings/cs.lproj/IgnoreSettings.strings",
    "chars": 785,
    "preview": "\"Title\" = \"Ignorovat\";\n\"ApplicationsTab\" = \"Aplikace\";\n\"IgnoredAppsDescription\" = \"Je možné ignorovat kopie z určitých a"
  },
  {
    "path": "Maccy/Settings/cs.lproj/PinsSettings.strings",
    "chars": 462,
    "preview": "\"Title\" = \"Připnuté\";\n\"Key\" = \"Key\";\n\"Alias\" = \"Title\";\n\"Content\" = \"Obsah\";\n\"ContentIsNotText\" = \"Neupravitelný obsah ("
  },
  {
    "path": "Maccy/Settings/cs.lproj/StorageSettings.strings",
    "chars": 543,
    "preview": "\"Title\" = \"Úložistě\";\n\"Save\" = \"Ukládat:\";\n\"Files\" = \"Soubory\";\n\"Images\" = \"Obrázky\";\n\"Text\" = \"Text\";\n\"SaveDescription\""
  },
  {
    "path": "Maccy/Settings/de.lproj/AdvancedSettings.strings",
    "chars": 1120,
    "preview": "\"Title\" = \"Erweitert\";\n\"TurnOff\" = \"Deaktivieren\";\n\"TurnOffDescription\" = \"Vorrübergehend alle neue Einträge ignorieren."
  },
  {
    "path": "Maccy/Settings/de.lproj/AppearanceSettings.strings",
    "chars": 1964,
    "preview": "\"Title\" = \"Erscheinungsbild\";\n\"PopupAt\" = \"Position des Popup-Fensters:\";\n\"PopupAtCursor\" = \"Mauszeiger\";\n\"PopupAtMenuBa"
  },
  {
    "path": "Maccy/Settings/de.lproj/GeneralSettings.strings",
    "chars": 1409,
    "preview": "\"Title\" = \"Allgemein\";\n\"LaunchAtLogin\" = \"Beim Anmelden starten\";\n\"CheckForUpdates\" = \"Automatisch nach Updates suchen\";"
  },
  {
    "path": "Maccy/Settings/de.lproj/IgnoreSettings.strings",
    "chars": 930,
    "preview": "\"Title\" = \"Ignorieren\";\n\"ApplicationsTab\" = \"Anwendungen\";\n\"IgnoredAppsDescription\" = \"Es ist möglich, kopierte Elemente"
  },
  {
    "path": "Maccy/Settings/de.lproj/PinsSettings.strings",
    "chars": 499,
    "preview": "\"Title\" = \"Pins\";\n\"Key\" = \"Hotkey\";\n\"Alias\" = \"Titel\";\n\"Content\" = \"Inhalt\";\n\"ContentIsNotText\" = \"Nicht editierbarer In"
  },
  {
    "path": "Maccy/Settings/de.lproj/StorageSettings.strings",
    "chars": 578,
    "preview": "\"Title\" = \"Speicher\";\n\"Save\" = \"Sichern:\";\n\"Files\" = \"Dateien\";\n\"Images\" = \"Bilder\";\n\"Text\" = \"Text\";\n\"SaveDescription\" "
  },
  {
    "path": "Maccy/Settings/el.lproj/AdvancedSettings.strings",
    "chars": 279,
    "preview": "\"Title\" = \"\";\n\"TurnOff\" = \"\";\n\"TurnOffDescription\" = \"\";\n\"TurnOffShellScript\" = \"\";\n\"TurnOffViaMenuIconDescription\" = \"\""
  },
  {
    "path": "Maccy/Settings/el.lproj/AppearanceSettings.strings",
    "chars": 901,
    "preview": "\"Title\" = \"\";\n\"PopupAt\" = \"\";\n\"PopupAtCursor\" = \"\";\n\"PopupAtMenuBarIcon\" = \"\";\n\"PopupAtWindowCenter\" = \"\";\n\"PopupAtScree"
  },
  {
    "path": "Maccy/Settings/el.lproj/GeneralSettings.strings",
    "chars": 420,
    "preview": "\"Title\" = \"\";\n\"LaunchAtLogin\" = \"\";\n\"CheckForUpdates\" = \"\";\n\"CheckNow\" = \"\";\n\"Open\" = \"\";\n\"OpenTooltip\" = \"\";\n\"Pin\" = \"\""
  },
  {
    "path": "Maccy/Settings/el.lproj/IgnoreSettings.strings",
    "chars": 803,
    "preview": "\"ApplicationsTab\" = \"Εφαρμογές\";\n\"IgnoredAppsDescription\" = \"Υπάρχει δυνατότητα να αγνοήσεις αντιγραφές που προέρχονται "
  },
  {
    "path": "Maccy/Settings/el.lproj/PinsSettings.strings",
    "chars": 145,
    "preview": "\"Title\" = \"\";\n\"Key\" = \"\";\n\"Alias\" = \"\";\n\"Content\" = \"\";\n\"ContentIsNotText\" = \"\";\n\"RichTextEditWarning\" = \"\";\n\"PinCustomi"
  },
  {
    "path": "Maccy/Settings/el.lproj/StorageSettings.strings",
    "chars": 256,
    "preview": "\"Title\" = \"\";\n\"Save\" = \"\";\n\"Files\" = \"\";\n\"Images\" = \"\";\n\"Text\" = \"\";\n\"SaveDescription\" = \"\";\n\"Size\" = \"\";\n\"SizeTooltip\" "
  },
  {
    "path": "Maccy/Settings/en.lproj/AdvancedSettings.strings",
    "chars": 907,
    "preview": "\"Title\" = \"Advanced\";\n\"TurnOff\" = \"Turn off\";\n\"TurnOffDescription\" = \"Temporarily ignore all new copies.\\nYou are likely"
  },
  {
    "path": "Maccy/Settings/en.lproj/AppearanceSettings.strings",
    "chars": 1720,
    "preview": "\"Title\" = \"Appearance\";\n\"PopupAt\" = \"Popup at:\";\n\"PopupAtCursor\" = \"Cursor\";\n\"PopupAtMenuBarIcon\" = \"Menu icon\";\n\"PopupA"
  },
  {
    "path": "Maccy/Settings/en.lproj/GeneralSettings.strings",
    "chars": 1217,
    "preview": "\"Title\" = \"General\";\n\"LaunchAtLogin\" = \"Launch at login\";\n\"CheckForUpdates\" = \"Check for updates automatically\";\n\"CheckN"
  },
  {
    "path": "Maccy/Settings/en.lproj/IgnoreSettings.strings",
    "chars": 813,
    "preview": "\"Title\" = \"Ignore\";\n\"ApplicationsTab\" = \"Applications\";\n\"IgnoredAppsDescription\" = \"It's possible to ignore copies comin"
  },
  {
    "path": "Maccy/Settings/en.lproj/PinsSettings.strings",
    "chars": 408,
    "preview": "\"Title\" = \"Pins\";\n\"Key\" = \"Key\";\n\"Alias\" = \"Title\";\n\"Content\" = \"Content\";\n\"ContentIsNotText\" = \"Non-editable content (i"
  },
  {
    "path": "Maccy/Settings/en.lproj/StorageSettings.strings",
    "chars": 495,
    "preview": "\"Title\" = \"Storage\";\n\"Save\" = \"Save:\";\n\"Files\" = \"Files\";\n\"Images\" = \"Images\";\n\"Text\" = \"Text\";\n\"SaveDescription\" = \"Cha"
  },
  {
    "path": "Maccy/Settings/eo.lproj/AdvancedSettings.strings",
    "chars": 840,
    "preview": "\"Title\" = \"Altnivelaj agordoj\";\n\"TurnOff\" = \"Malŝalti\";\n\"TurnOffDescription\" = \"Provizore ignori ĉiujn novajn kopiojn.\\n"
  },
  {
    "path": "Maccy/Settings/eo.lproj/AppearanceSettings.strings",
    "chars": 1544,
    "preview": "\"Title\" = \"Aspekto\";\n\"PopupAtLastPosition\" = \"Lasta pozicio\";\n\"SearchVisibilityAlways\" = \"Ĉiam\";\n\"SearchVisibilityDuring"
  },
  {
    "path": "Maccy/Settings/eo.lproj/GeneralSettings.strings",
    "chars": 1077,
    "preview": "\"CheckNow\" = \"Kontroli nun\";\n\"Open\" = \"Malfermi:\";\n\"Pin\" = \"Fiksi:\";\n\"Delete\" = \"Forigi:\";\n\"Behavior\" = \"Konduto:\";\n\"Pas"
  },
  {
    "path": "Maccy/Settings/eo.lproj/IgnoreSettings.strings",
    "chars": 421,
    "preview": "\"Title\" = \"Ignori\";\n\"ApplicationsTab\" = \"Aplikaĵoj\";\n\"IgnoredAppsDescription\" = \"\";\n\"IgnoredAllAppsExceptListed\" = \"Igno"
  },
  {
    "path": "Maccy/Settings/eo.lproj/PinsSettings.strings",
    "chars": 250,
    "preview": "\"Title\" = \"Fiksitaj eroj\";\n\"Key\" = \"Klavo\";\n\"Alias\" = \"Titolo\";\n\"Content\" = \"Enhavo\";\n\"ContentIsNotText\" = \"Ne-redaktebl"
  },
  {
    "path": "Maccy/Settings/eo.lproj/StorageSettings.strings",
    "chars": 538,
    "preview": "\"Text\" = \"Teksto\";\n\"Images\" = \"Bildoj\";\n\"Files\" = \"Dosieroj\";\n\"Save\" = \"Konservi:\";\n\"SortBy\" = \"Ordigi laŭ:\";\n\"Title\" = "
  },
  {
    "path": "Maccy/Settings/es.lproj/AdvancedSettings.strings",
    "chars": 1018,
    "preview": "\"Title\" = \"Avanzado\";\n\"TurnOff\" = \"Desactivar\";\n\"TurnOffDescription\" = \"Ignorar temporalmente los nuevos elementos copia"
  },
  {
    "path": "Maccy/Settings/es.lproj/AppearanceSettings.strings",
    "chars": 2037,
    "preview": "\"Title\" = \"Apariencia\";\n\"PopupAt\" = \"Ventana emergente en:\";\n\"PopupAtCursor\" = \"Cursor\";\n\"PopupAtMenuBarIcon\" = \"Icono d"
  },
  {
    "path": "Maccy/Settings/es.lproj/GeneralSettings.strings",
    "chars": 1476,
    "preview": "\"Title\" = \"General\";\n\"LaunchAtLogin\" = \"Abrir al iniciar sesión\";\n\"CheckForUpdates\" = \"Buscar actualizaciones automática"
  },
  {
    "path": "Maccy/Settings/es.lproj/IgnoreSettings.strings",
    "chars": 835,
    "preview": "\"Title\" = \"Exclusiones\";\n\"ApplicationsTab\" = \"Aplicaciones\";\n\"IgnoredAppsDescription\" = \"Es posible excluir la copia des"
  },
  {
    "path": "Maccy/Settings/es.lproj/PinsSettings.strings",
    "chars": 427,
    "preview": "\"Title\" = \"Anclas\";\n\"Key\" = \"Clave\";\n\"Alias\" = \"Título\";\n\"Content\" = \"Contenido\";\n\"ContentIsNotText\" = \"Contenido no edi"
  },
  {
    "path": "Maccy/Settings/es.lproj/StorageSettings.strings",
    "chars": 560,
    "preview": "\"Title\" = \"Almacenamiento\";\n\"Save\" = \"Almacenar:\";\n\"Files\" = \"Archivos\";\n\"Images\" = \"Imágenes\";\n\"Text\" = \"Texto\";\n\"SaveD"
  },
  {
    "path": "Maccy/Settings/fa.lproj/AdvancedSettings.strings",
    "chars": 783,
    "preview": "\"Title\" = \"پیشرفته\";\n\"TurnOff\" = \"خاموش کردن\";\n\"TurnOffDescription\" = \"برای مدتی همهٔ کپی‌های جدید را نادیده بگیرید.\\nاح"
  },
  {
    "path": "Maccy/Settings/fa.lproj/AppearanceSettings.strings",
    "chars": 975,
    "preview": "\"Title\" = \"ظاهر\";\n\"PopupAt\" = \"مکان باز شدن پنجره:\";\n\"PopupAtCursor\" = \"مکان‌نما (Cursor)\";\n\"PopupAtMenuBarIcon\" = \"آیکو"
  },
  {
    "path": "Maccy/Settings/fa.lproj/GeneralSettings.strings",
    "chars": 1000,
    "preview": "\"Title\" = \"عمومی\";\n\"CheckForUpdates\" = \"بررسی خودکار به روز رسانی\";\n\"CheckNow\" = \"بررسی کن\";\n\"Open\" = \"باز:\";\n\"LaunchAtL"
  },
  {
    "path": "Maccy/Settings/fa.lproj/IgnoreSettings.strings",
    "chars": 835,
    "preview": "\"Title\" = \"نادیده گرفتن\";\n\"ApplicationsTab\" = \"اپلیکیشن\";\n\"IgnoredAppsDescription\" = \"می‌توانید کپی‌هایی را که از بعضی ب"
  },
  {
    "path": "Maccy/Settings/fa.lproj/PinsSettings.strings",
    "chars": 144,
    "preview": "\"Title\" = \"\";\n\"Key\" = \"\";\n\"Alias\" = \"\";\n\"Content\" = \"\";\n\"ContentIsNotText\" = \"\";\n\"RichTextEditWarning\" = \"\";\n\"PinCustomi"
  },
  {
    "path": "Maccy/Settings/fa.lproj/StorageSettings.strings",
    "chars": 336,
    "preview": "\"Title\" = \"حافظه\";\n\"Save\" = \"ذخیره:\";\n\"Files\" = \"فایل‌ها\";\n\"Images\" = \"تصاویر\";\n\"Text\" = \"متن\";\n\"SaveDescription\" = \"تعی"
  },
  {
    "path": "Maccy/Settings/fr.lproj/AdvancedSettings.strings",
    "chars": 1045,
    "preview": "\"Title\" = \"Avancé\";\n\"TurnOff\" = \"Désactiver\";\n\"TurnOffDescription\" = \"Ignorer temporairement toute nouvelle copie.\\nVous"
  },
  {
    "path": "Maccy/Settings/fr.lproj/AppearanceSettings.strings",
    "chars": 2074,
    "preview": "\"Title\" = \"Apparence\";\n\"PopupAt\" = \"Popup sur :\";\n\"PopupAtCursor\" = \"Curseur\";\n\"PopupAtMenuBarIcon\" = \"Icône du menu\";\n\""
  },
  {
    "path": "Maccy/Settings/fr.lproj/GeneralSettings.strings",
    "chars": 1520,
    "preview": "\"Title\" = \"Général\";\n\"LaunchAtLogin\" = \"Lancer au démarrage\";\n\"CheckForUpdates\" = \"Vérifier les mises à jour automatique"
  },
  {
    "path": "Maccy/Settings/fr.lproj/IgnoreSettings.strings",
    "chars": 926,
    "preview": "\"Title\" = \"Ignorer\";\n\"ApplicationsTab\" = \"Applications\";\n\"IgnoredAppsDescription\" = \"Il est possible d’ignorer les copie"
  },
  {
    "path": "Maccy/Settings/fr.lproj/PinsSettings.strings",
    "chars": 495,
    "preview": "\"Title\" = \"Épingles\";\n\"Key\" = \"Clé\";\n\"Alias\" = \"Titre\";\n\"Content\" = \"Contenu\";\n\"ContentIsNotText\" = \"Contenu non modifia"
  },
  {
    "path": "Maccy/Settings/fr.lproj/StorageSettings.strings",
    "chars": 547,
    "preview": "\"Title\" = \"Stockage\";\n\"Save\" = \"Sauver :\";\n\"Files\" = \"Fichiers\";\n\"Images\" = \"Images\";\n\"Text\" = \"Textes\";\n\"SaveDescriptio"
  },
  {
    "path": "Maccy/Settings/he.lproj/AdvancedSettings.strings",
    "chars": 870,
    "preview": "\"Title\" = \"מתקדם\";\n\"TurnOff\" = \"כיבוי\";\n\"TurnOffDescription\" = \"להתעלם זמנית מכל העותקים החדשים.\\nכנראה שזה ישמש אותך במ"
  },
  {
    "path": "Maccy/Settings/he.lproj/AppearanceSettings.strings",
    "chars": 1681,
    "preview": "\"Title\" = \"מראה\";\n\"PopupAt\" = \"הקפצת חלונית ב־:\";\n\"PopupAtCursor\" = \"סמן\";\n\"PopupAtMenuBarIcon\" = \"סמל תפריט\";\n\"PopupAtW"
  },
  {
    "path": "Maccy/Settings/he.lproj/GeneralSettings.strings",
    "chars": 1139,
    "preview": "\"Title\" = \"כללי\";\n\"LaunchAtLogin\" = \"להפעיל עם הכניסה למערכת\";\n\"CheckForUpdates\" = \"לבדוק אוטומטית אם יש עדכונים\";\n\"Chec"
  },
  {
    "path": "Maccy/Settings/he.lproj/IgnoreSettings.strings",
    "chars": 692,
    "preview": "\"Title\" = \"התעלמות\";\n\"ApplicationsTab\" = \"יישומים\";\n\"IgnoredAppsDescription\" = \"אפשר להתעלם מעותקים שמגיעים מיישומים מסו"
  },
  {
    "path": "Maccy/Settings/he.lproj/PinsSettings.strings",
    "chars": 376,
    "preview": "\"Title\" = \"נעוצים\";\n\"Key\" = \"מקש קישור\";\n\"Alias\" = \"כותרת\";\n\"Content\" = \"תוכן\";\n\"ContentIsNotText\" = \"תוכן שאינו ניתן לע"
  },
  {
    "path": "Maccy/Settings/he.lproj/StorageSettings.strings",
    "chars": 474,
    "preview": "\"Title\" = \"אחסון\";\n\"Save\" = \"שמירה:\";\n\"Files\" = \"קבצים\";\n\"Images\" = \"תמונות\";\n\"Text\" = \"טקסט\";\n\"SaveDescription\" = \"לשנו"
  },
  {
    "path": "Maccy/Settings/hi.lproj/AdvancedSettings.strings",
    "chars": 279,
    "preview": "\"Title\" = \"\";\n\"TurnOff\" = \"\";\n\"TurnOffDescription\" = \"\";\n\"TurnOffShellScript\" = \"\";\n\"TurnOffViaMenuIconDescription\" = \"\""
  },
  {
    "path": "Maccy/Settings/hi.lproj/AppearanceSettings.strings",
    "chars": 901,
    "preview": "\"Title\" = \"\";\n\"PopupAt\" = \"\";\n\"PopupAtCursor\" = \"\";\n\"PopupAtMenuBarIcon\" = \"\";\n\"PopupAtWindowCenter\" = \"\";\n\"PopupAtScree"
  },
  {
    "path": "Maccy/Settings/hi.lproj/GeneralSettings.strings",
    "chars": 427,
    "preview": "\"Title\" = \"सामान्य\";\n\"LaunchAtLogin\" = \"\";\n\"CheckForUpdates\" = \"\";\n\"CheckNow\" = \"\";\n\"Open\" = \"\";\n\"OpenTooltip\" = \"\";\n\"Pi"
  },
  {
    "path": "Maccy/Settings/hi.lproj/IgnoreSettings.strings",
    "chars": 261,
    "preview": "\"Title\" = \"\";\n\"ApplicationsTab\" = \"\";\n\"IgnoredAppsDescription\" = \"\";\n\"IgnoredAllAppsExceptListed\" = \"\";\n\"PasteboardTypes"
  },
  {
    "path": "Maccy/Settings/hi.lproj/PinsSettings.strings",
    "chars": 145,
    "preview": "\"Title\" = \"\";\n\"Key\" = \"\";\n\"Alias\" = \"\";\n\"Content\" = \"\";\n\"ContentIsNotText\" = \"\";\n\"RichTextEditWarning\" = \"\";\n\"PinCustomi"
  },
  {
    "path": "Maccy/Settings/hi.lproj/StorageSettings.strings",
    "chars": 256,
    "preview": "\"Title\" = \"\";\n\"Save\" = \"\";\n\"Files\" = \"\";\n\"Images\" = \"\";\n\"Text\" = \"\";\n\"SaveDescription\" = \"\";\n\"Size\" = \"\";\n\"SizeTooltip\" "
  },
  {
    "path": "Maccy/Settings/hr.lproj/AdvancedSettings.strings",
    "chars": 974,
    "preview": "\"Title\" = \"Napredno\";\n\"TurnOff\" = \"Isključi\";\n\"TurnOffDescription\" = \"Privremeno zanemari sve nove kopije.\\nVjerojatno ć"
  },
  {
    "path": "Maccy/Settings/hr.lproj/AppearanceSettings.strings",
    "chars": 1885,
    "preview": "\"Title\" = \"Izgled\";\n\"PopupAt\" = \"Skočni prozor:\";\n\"PopupAtCursor\" = \"Kursor\";\n\"PopupAtMenuBarIcon\" = \"Ikona u izborniku\""
  },
  {
    "path": "Maccy/Settings/hr.lproj/GeneralSettings.strings",
    "chars": 1379,
    "preview": "\"Title\" = \"Opće\";\n\"LaunchAtLogin\" = \"Pokreni nakon prijave\";\n\"CheckForUpdates\" = \"Automatski provjeri aktualnost\";\n\"Chec"
  },
  {
    "path": "Maccy/Settings/hr.lproj/IgnoreSettings.strings",
    "chars": 823,
    "preview": "\"Title\" = \"Zanemari\";\n\"ApplicationsTab\" = \"Programi\";\n\"IgnoredAppsDescription\" = \"Moguće je zanemariti kopije koje dolaz"
  },
  {
    "path": "Maccy/Settings/hr.lproj/PinsSettings.strings",
    "chars": 463,
    "preview": "\"Title\" = \"Pribadače\";\n\"Key\" = \"Tipka\";\n\"Alias\" = \"Naslov\";\n\"Content\" = \"Sadržaj\";\n\"ContentIsNotText\" = \"Sadržaj koji se"
  },
  {
    "path": "Maccy/Settings/hr.lproj/StorageSettings.strings",
    "chars": 540,
    "preview": "\"Title\" = \"Skladištenje\";\n\"Save\" = \"Spremi:\";\n\"Files\" = \"Datoteke\";\n\"Images\" = \"Slike\";\n\"Text\" = \"Tekst\";\n\"SaveDescripti"
  }
]

// ... and 302 more files (download for full content)

About this extraction

This page contains the full source code of the p0deje/Maccy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 502 files (31.3 MB), approximately 243.7k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!