diff --git a/Maccy.xcodeproj/project.pbxproj b/Maccy.xcodeproj/project.pbxproj index 7dd4b982..0e3ce9dc 100644 --- a/Maccy.xcodeproj/project.pbxproj +++ b/Maccy.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 2F39CB042AD9A93C00B749FD /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 2F39CB032AD9A93C00B749FD /* Sparkle */; }; 2F39CB0A2AD9AE1F00B749FD /* Settings in Frameworks */ = {isa = PBXBuildFile; productRef = 2F39CB092AD9AE1F00B749FD /* Settings */; }; 2F8B9DE62C5D6E5D0046EF69 /* NSPoint+DefaultsSerializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F8B9DE52C5D6E5D0046EF69 /* NSPoint+DefaultsSerializable.swift */; }; + 2FB5BCA02CD8F73F008B33F4 /* ApplicationImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB5BC9F2CD8F73C008B33F4 /* ApplicationImage.swift */; }; 4762D6972467226100B3A2BA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4762D6992467226100B3A2BA /* Localizable.strings */; }; DA009931256411F90030E697 /* appcast.xml in Resources */ = {isa = PBXBuildFile; fileRef = DA00992C256411F90030E697 /* appcast.xml */; }; DA009932256411F90030E697 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = DA00992D256411F90030E697 /* README.md */; }; @@ -64,6 +65,7 @@ DA49EE7528B59468002752E0 /* NSRect+Centered.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA49EE7428B59468002752E0 /* NSRect+Centered.swift */; }; DA49EE7928B594DC002752E0 /* NSRunningApplication+WindowFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA49EE7828B594DC002752E0 /* NSRunningApplication+WindowFrame.swift */; }; DA5154D82564102900C01004 /* Sauce in Frameworks */ = {isa = PBXBuildFile; productRef = DA5154D72564102900C01004 /* Sauce */; }; + DA555F082CF0F994009608BD /* ApplicationImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA555F072CF0F98F009608BD /* ApplicationImageCache.swift */; }; DA5E62802C39E53F00F4C710 /* PreviewItemView.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA5E627E2C39E53F00F4C710 /* PreviewItemView.strings */; }; DA5F46512020E9FB00425C11 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5F464F2020E4DF00425C11 /* Carbon.framework */; }; DA6373981E4AB9BB00263391 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA6373971E4AB9BB00263391 /* Assets.xcassets */; }; @@ -160,6 +162,7 @@ 11EB892C281DADFF00A78CB4 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; 2F1A79BF2C6DFB7800C98EBD /* SearchVisibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchVisibility.swift; sourceTree = ""; }; 2F8B9DE52C5D6E5D0046EF69 /* NSPoint+DefaultsSerializable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSPoint+DefaultsSerializable.swift"; sourceTree = ""; }; + 2FB5BC9F2CD8F73C008B33F4 /* ApplicationImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationImage.swift; sourceTree = ""; }; 3EBDD1E32BBEF22800C57500 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; 4762D6982467226100B3A2BA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 4762D69A2467226400B3A2BA /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; @@ -236,6 +239,7 @@ DA49EE7828B594DC002752E0 /* NSRunningApplication+WindowFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSRunningApplication+WindowFrame.swift"; sourceTree = ""; }; DA4B706A271B7B5300FF324C /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; DA4C056C2BD416F000FE5FEC /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; }; + DA555F072CF0F98F009608BD /* ApplicationImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationImageCache.swift; sourceTree = ""; }; DA5E627F2C39E53F00F4C710 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/PreviewItemView.strings; sourceTree = ""; }; DA5E62812C39E54A00F4C710 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/PreviewItemView.strings; sourceTree = ""; }; DA5E62822C39E54B00F4C710 /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/PreviewItemView.strings; sourceTree = ""; }; @@ -699,6 +703,8 @@ DA6D98E12AEABE03008A77CE /* Accessibility.swift */, DAEE38461E3DBEB100DD2966 /* AppDelegate.swift */, DAB082952A2B7B850053E463 /* AppStoreReview.swift */, + 2FB5BC9F2CD8F73C008B33F4 /* ApplicationImage.swift */, + DA555F072CF0F98F009608BD /* ApplicationImageCache.swift */, DA0EF1871E444B2A00E58577 /* Clipboard.swift */, DAE284FF232257D20080E394 /* ColorImage.swift */, DAA54BF92C3C951900B7FDD8 /* FloatingPanel.swift */, @@ -713,6 +719,7 @@ DA689FC72C1D15140009B887 /* PinsPosition.swift */, DA689FC52C1D14F10009B887 /* PopupPosition.swift */, DAC14123232367B200FCFA30 /* Search.swift */, + 2F1A79BF2C6DFB7800C98EBD /* SearchVisibility.swift */, DAA5ACC92C1BEE8A00B58513 /* SoftwareUpdater.swift */, DA696BCD240177E800DE80CF /* Sorter.swift */, DA243D132C2F66DD0012A27F /* Storage.swift */, @@ -721,7 +728,6 @@ DAEE384D1E3DBEB100DD2966 /* Info.plist */, DA6373971E4AB9BB00263391 /* Assets.xcassets */, 4762D6992467226100B3A2BA /* Localizable.strings */, - 2F1A79BF2C6DFB7800C98EBD /* SearchVisibility.swift */, ); path = Maccy; sourceTree = ""; @@ -947,6 +953,7 @@ DA1969142C3F11D600258481 /* PreviewItemView.swift in Sources */, DAA072D52C40AC52006DDFD2 /* HistoryListView.swift in Sources */, DAB082962A2B7B850053E463 /* AppStoreReview.swift in Sources */, + 2FB5BCA02CD8F73F008B33F4 /* ApplicationImage.swift in Sources */, DA13D7D22C19F91B00FA9E23 /* Defaults.Keys+Names.swift in Sources */, DA1969102C3F0AAC00258481 /* KeyShortcut.swift in Sources */, DA9C3C622C20E1BF0056795D /* IgnoreRegexpsSettingsView.swift in Sources */, @@ -983,6 +990,7 @@ DA1969212C3F6C6800258481 /* HistoryItemAction.swift in Sources */, 0ABDD5122BB47F1E0054963B /* NSWorkspace+ApplicationName.swift in Sources */, DA19691A2C3F369800258481 /* HeaderView.swift in Sources */, + DA555F082CF0F994009608BD /* ApplicationImageCache.swift in Sources */, DA44C5E42C1C858400819834 /* StorageSettingsPane.swift in Sources */, DA05B5142C234DCF006980FE /* HistoryItemContent.swift in Sources */, DAA072D32C40A961006DDFD2 /* Color+Random.swift in Sources */, diff --git a/Maccy/ApplicationImage.swift b/Maccy/ApplicationImage.swift new file mode 100644 index 00000000..bedaf6d4 --- /dev/null +++ b/Maccy/ApplicationImage.swift @@ -0,0 +1,81 @@ +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 + } +} diff --git a/Maccy/ApplicationImageCache.swift b/Maccy/ApplicationImageCache.swift new file mode 100644 index 00000000..e3068e35 --- /dev/null +++ b/Maccy/ApplicationImageCache.swift @@ -0,0 +1,35 @@ +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 + } +} diff --git a/Maccy/Extensions/Defaults.Keys+Names.swift b/Maccy/Extensions/Defaults.Keys+Names.swift index b6790d08..6f79907d 100644 --- a/Maccy/Extensions/Defaults.Keys+Names.swift +++ b/Maccy/Extensions/Defaults.Keys+Names.swift @@ -57,4 +57,5 @@ extension Defaults.Keys { static let suppressClearAlert = Key("suppressClearAlert", default: false) static let windowSize = Key("windowSize", default: NSSize(width: 450, height: 800)) static let windowPosition = Key("windowPosition", default: NSPoint(x: 0.5, y: 0.8)) + static let showApplicationIcons = Key("showApplicationIcons", default: false) } diff --git a/Maccy/Observables/HistoryItemDecorator.swift b/Maccy/Observables/HistoryItemDecorator.swift index 437ebe36..220228ad 100644 --- a/Maccy/Observables/HistoryItemDecorator.swift +++ b/Maccy/Observables/HistoryItemDecorator.swift @@ -52,6 +52,7 @@ class HistoryItemDecorator: Identifiable, Hashable { var previewImage: NSImage? var thumbnailImage: NSImage? + var applicationImage: ApplicationImage var text: String { item.previewableText } @@ -70,6 +71,7 @@ class HistoryItemDecorator: Identifiable, Hashable { self.item = item self.shortcuts = shortcuts self.title = item.title + self.applicationImage = ApplicationImageCache.shared.getImage(item: item) synchronizeItemPin() synchronizeItemTitle() diff --git a/Maccy/Settings/AppearanceSettingsPane.swift b/Maccy/Settings/AppearanceSettingsPane.swift index 6d0e3693..e8f6cc83 100644 --- a/Maccy/Settings/AppearanceSettingsPane.swift +++ b/Maccy/Settings/AppearanceSettingsPane.swift @@ -16,6 +16,7 @@ struct AppearanceSettingsPane: View { @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 @@ -181,6 +182,9 @@ struct AppearanceSettingsPane: View { Defaults.Toggle(key: .showTitle) { Text("ShowTitleBeforeSearchField", tableName: "AppearanceSettings") } + Defaults.Toggle(key: .showApplicationIcons) { + Text("ShowApplicationIcons", tableName: "AppearanceSettings") + } Defaults.Toggle(key: .showFooter) { Text("ShowFooter", tableName: "AppearanceSettings") diff --git a/Maccy/Settings/ar.lproj/AppearanceSettings.strings b/Maccy/Settings/ar.lproj/AppearanceSettings.strings index ceca7026..9343faee 100644 --- a/Maccy/Settings/ar.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/ar.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "إظهار حقل البحث"; "ShowTitleBeforeSearchField" = "إظهار العنوان قبل حقل البحث"; "ShowFooter" = "إظهار التذييل"; +"ShowApplicationIcons" = "إظهار أيقونات التطبيقات"; "OpenPreferencesWarning" = "⚠️ اضغط ⌘، لفتح التفضيلات عندما يكون التذييل مخفيًا."; diff --git a/Maccy/Settings/bs.lproj/AppearanceSettings.strings b/Maccy/Settings/bs.lproj/AppearanceSettings.strings index 9df1b5bb..b2f43621 100644 --- a/Maccy/Settings/bs.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/bs.lproj/AppearanceSettings.strings @@ -32,3 +32,4 @@ "ShowTitleBeforeSearchField" = "Prikaži naslov prije polja za pretraživanje"; "ShowFooter" = "Prikaži footer"; "OpenPreferencesWarning" = "⚠️ Pritisni ⌘, da otvorite postavke kada je podnožje skriveno."; +"ShowApplicationIcons" = "Prikaži ikone aplikacija"; diff --git a/Maccy/Settings/cs.lproj/AppearanceSettings.strings b/Maccy/Settings/cs.lproj/AppearanceSettings.strings index 15ae8d62..d7dd6cb7 100644 --- a/Maccy/Settings/cs.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/cs.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Zobrazovat vyhledávací pole"; "ShowTitleBeforeSearchField" = "Zobrazovat název aplikace před vyhledávacím polem"; "ShowFooter" = "Zobrazovat patičku"; +"ShowApplicationIcons" = "Zobrazení ikon aplikací"; "OpenPreferencesWarning" = "⚠️ Stiskni ⌘ pro otevření předvoleb, když je skrytá patička."; diff --git a/Maccy/Settings/de.lproj/AppearanceSettings.strings b/Maccy/Settings/de.lproj/AppearanceSettings.strings index 42edd151..2e64e250 100644 --- a/Maccy/Settings/de.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/de.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Suchfeld anzeigen"; "ShowTitleBeforeSearchField" = "Titel neben dem Suchfeld anzeigen"; "ShowFooter" = "Menü anzeigen"; +"ShowApplicationIcons" = "Anwendungssymbole anzeigen"; "OpenPreferencesWarning" = "⚠️ Um die Einstellungen zu öffnen, halte ⌘, gedrückt."; diff --git a/Maccy/Settings/en.lproj/AppearanceSettings.strings b/Maccy/Settings/en.lproj/AppearanceSettings.strings index 32bb9a35..c8940667 100644 --- a/Maccy/Settings/en.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/en.lproj/AppearanceSettings.strings @@ -30,5 +30,6 @@ "ShowRecentCopyInMenuBar" = "Show recent copy next to menu icon"; "ShowSearchField" = "Show search field"; "ShowTitleBeforeSearchField" = "Show title before search field"; +"ShowApplicationIcons" = "Show application icons"; "ShowFooter" = "Show footer"; "OpenPreferencesWarning" = "⚠️ Press ⌘, to open preferences when footer is hidden."; diff --git a/Maccy/Settings/es.lproj/AppearanceSettings.strings b/Maccy/Settings/es.lproj/AppearanceSettings.strings index 0e657b0e..a8875835 100644 --- a/Maccy/Settings/es.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/es.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Mostrar campo de búsqueda"; "ShowTitleBeforeSearchField" = "Mostrar título antes del buscador"; "ShowFooter" = "Mostrar footer"; +"ShowApplicationIcons" = "Mostrar iconos de aplicaciones"; "OpenPreferencesWarning" = "⚠️ Presiona ⌘, para abrir las preferencias cuando el footer esté oculto."; diff --git a/Maccy/Settings/fr.lproj/AppearanceSettings.strings b/Maccy/Settings/fr.lproj/AppearanceSettings.strings index 507e2632..57cc7d28 100644 --- a/Maccy/Settings/fr.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/fr.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Afficher le champ de recherche"; "ShowTitleBeforeSearchField" = "Afficher le titre avant la barre de recherche"; "ShowFooter" = "Afficher le bas de l'application"; +"ShowApplicationIcons" = "Afficher les icônes des applications"; "OpenPreferencesWarning" = "⚠️ Pressez ⌘, pour ouvrir les préférences quand le bas de l'application est caché."; diff --git a/Maccy/Settings/he.lproj/AppearanceSettings.strings b/Maccy/Settings/he.lproj/AppearanceSettings.strings index fb73f411..24981cae 100644 --- a/Maccy/Settings/he.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/he.lproj/AppearanceSettings.strings @@ -32,3 +32,4 @@ "ShowTitleBeforeSearchField" = "הצגת כותרת לפני שדה החיפוש"; "ShowFooter" = "הצגת כותרת תחתונה"; "OpenPreferencesWarning" = "⚠️ יש ללחוץ על ⌘, כדי לפתוח העדפות כאשר הכותרת התחתונה מוסתרת."; +"ShowApplicationIcons" = "הצג סמלי יישומים"; diff --git a/Maccy/Settings/hr.lproj/AppearanceSettings.strings b/Maccy/Settings/hr.lproj/AppearanceSettings.strings index 5e362fcd..dcedc39b 100644 --- a/Maccy/Settings/hr.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/hr.lproj/AppearanceSettings.strings @@ -32,3 +32,4 @@ "ShowTitleBeforeSearchField" = "Prikaži naslov prije polja pretrage"; "ShowFooter" = "Prikaži podnožje"; "OpenPreferencesWarning" = "⚠️ Za otvaranje postavaka kad je podnožje skriveno, pritisni ⌘."; +"ShowApplicationIcons" = "Prikaži ikone aplikacija"; diff --git a/Maccy/Settings/hu.lproj/AppearanceSettings.strings b/Maccy/Settings/hu.lproj/AppearanceSettings.strings index eeffadb7..b08216e5 100644 --- a/Maccy/Settings/hu.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/hu.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Keresőmező megjelenítése"; "ShowTitleBeforeSearchField" = "Cím megjelenítése a keresőmező előtt"; "ShowFooter" = "Lábléc megjelenítése"; +"ShowApplicationIcons" = "Alkalmazás ikonok megjelenítése"; "OpenPreferencesWarning" = "⚠️ Nyomd meg a ⌘ gombot a Preferenciák megnyitásához, ha a lábléc el van rejtve."; diff --git a/Maccy/Settings/it.lproj/AppearanceSettings.strings b/Maccy/Settings/it.lproj/AppearanceSettings.strings index 38ebe8b8..957a1774 100644 --- a/Maccy/Settings/it.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/it.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Mostra campo ricerca"; "ShowTitleBeforeSearchField" = "Mostra il titolo prima del campo ricerca"; "ShowFooter" = "Mostra footer"; +"ShowApplicationIcons" = "Mostra le icone delle applicazioni"; "OpenPreferencesWarning" = "⚠️ Premi ⌘, per aprire le preferenze quando il footer è nascosto."; diff --git a/Maccy/Settings/ja.lproj/AppearanceSettings.strings b/Maccy/Settings/ja.lproj/AppearanceSettings.strings index ed683182..ade0737c 100644 --- a/Maccy/Settings/ja.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/ja.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "検索フィールド表示"; "ShowTitleBeforeSearchField" = "検索フィールドの前にタイトル表示"; "ShowFooter" = "フッター表示"; +"ShowApplicationIcons" = "アプリケーションのアイコンを表示する"; "OpenPreferencesWarning" = "⚠️ フッターが隠されている時に設定を開くには⌘,を押してください。"; diff --git a/Maccy/Settings/ko.lproj/AppearanceSettings.strings b/Maccy/Settings/ko.lproj/AppearanceSettings.strings index 376c2012..20fefa71 100644 --- a/Maccy/Settings/ko.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/ko.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "검색 필드 표시"; "ShowTitleBeforeSearchField" = "검색 필드 앞에 타이틀 표시"; "ShowFooter" = "푸터 표시"; +"ShowApplicationIcons" = "애플리케이션 아이콘 표시"; "OpenPreferencesWarning" = "⚠️ 푸터가 숨겨져 있을 때 설정을 열려면 ⌘,를 누르세요."; diff --git a/Maccy/Settings/lt.lproj/AppearanceSettings.strings b/Maccy/Settings/lt.lproj/AppearanceSettings.strings index 7bb420e9..358a4fce 100644 --- a/Maccy/Settings/lt.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/lt.lproj/AppearanceSettings.strings @@ -1,34 +1,35 @@ "Title" = "Išvaizda"; "PopupAt" = "Iššokančio lango vieta:"; "PopupAtCursor" = "Pelės žymeklis"; +"PopupAtMenuBarIcon" = "Meniu piktograma"; "PopupAtWindowCenter" = "Lango centras"; "PopupAtScreenCenter" = "Ekrano centras"; "PopupAtLastPosition" = "Paskutinė vieta"; "PopupAtLastLocationReset" = "Iš naujo nustatyti vietą"; "PopupAtTooltip" = "Pakeiskite vietą, kurioje rodomas iššokantis langas.\nNumatytoji reikšmė: Pelės žymeklis."; "SearchVisibilityAlways" = "Visada"; +"SearchVisibilityDuringSearch" = "Paieškos metu"; "ActiveScreen" = "Aktyvus ekranas"; +"PinTo" = "Prisegti:"; "PinToTop" = "Viršuje"; "PinToBottom" = "Apačioje"; +"PinToTooltip" = "Pakeiskite prisegtų elementų vietą.\nNumatytoji reikšmė: Viršuje."; "ImageHeight" = "Paveikslėlio aukštis:"; "ImageHeightTooltip" = "Didžiausias paveikslėlio peržiūros aukštis.\nNumatytoji reikšmė: 40.\nPatarimas: Nustatykite 16, kad atrodytų kaip teksto elementai."; +"PreviewDelay" = "Peržiūros vėlavimas:"; "PreviewDelayTooltip" = "Vėlavimas milisekundėmis, kol bus parodytas iškylantysis peržiūros langas.\nNumatytoji reikšmė: 1500."; "HighlightMatches" = "Paryškinti atitikimus:"; "HighlightMatchColor" = "Spalva"; "HighlightMatchBold" = "Paryškintu šriftu"; "HighlightMatchItalic" = "Kursyvu"; "HighlightMatchUnderline" = "Pabraukimu"; +"HighlightMatchesTooltip" = "Pakeiskite paieškos atitikmenų paryškinimo stilių.\nNumatytoji reikšmė: Paryškintu šriftu."; "ShowSpecialSymbols" = "Rodyti specialiuosius simbolius"; -"PinTo" = "Prisegti:"; +"ShowSpecialSymbolsTooltip" = "Rodyti naujas eilutes, skirtukus, pradinius ir galinius tarpus naudojant specialius simbolius."; "ShowMenuIcon" = "Rodyti meniu piktogramą"; "ShowRecentCopyInMenuBar" = "Rodyti naujausią kopiją šalia meniu piktogramos"; "ShowSearchField" = "Rodyti paieškos laukelį"; "ShowTitleBeforeSearchField" = "Rodyti pavadinimą prieš paieškos laukelį"; "ShowFooter" = "Rodyti paraštę"; +"ShowApplicationIcons" = "Rodyti programų piktogramas"; "OpenPreferencesWarning" = "⚠️ Paspauskite ⌘ ir , norėdami atidaryti nustatymus, kai paraštė yra paslėpta."; -"PopupAtMenuBarIcon" = "Meniu piktograma"; -"SearchVisibilityDuringSearch" = "Paieškos metu"; -"PinToTooltip" = "Pakeiskite prisegtų elementų vietą.\nNumatytoji reikšmė: Viršuje."; -"PreviewDelay" = "Peržiūros vėlavimas:"; -"HighlightMatchesTooltip" = "Pakeiskite paieškos atitikmenų paryškinimo stilių.\nNumatytoji reikšmė: Paryškintu šriftu."; -"ShowSpecialSymbolsTooltip" = "Rodyti naujas eilutes, skirtukus, pradinius ir galinius tarpus naudojant specialius simbolius."; diff --git a/Maccy/Settings/lv.lproj/AppearanceSettings.strings b/Maccy/Settings/lv.lproj/AppearanceSettings.strings index 7f397cd5..7a35128b 100644 --- a/Maccy/Settings/lv.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/lv.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Rādīt meklēšanas lauku"; "ShowTitleBeforeSearchField" = "Rādīt virsrakstu pirms meklēšanas lauka"; "ShowFooter" = "Rādīt kājeni"; +"ShowApplicationIcons" = "Rādīt lietojumprogrammu ikonas"; "OpenPreferencesWarning" = "⚠️ Nospiediet taustiņu ⌘, lai atvērtu preferences, ja kājene ir paslēpta."; diff --git a/Maccy/Settings/nb.lproj/AppearanceSettings.strings b/Maccy/Settings/nb.lproj/AppearanceSettings.strings index ae71cca8..dfbbb71d 100644 --- a/Maccy/Settings/nb.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/nb.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Vis søkefelt"; "ShowTitleBeforeSearchField" = "Vis tittel før søkefelt"; "ShowFooter" = "Vis bunntekst"; +"ShowApplicationIcons" = "Vis applikasjonsikoner"; "OpenPreferencesWarning" = "⚠️ Trykk ⌘, for å åpne valg når bunntekst er skjult."; diff --git a/Maccy/Settings/nl.lproj/AppearanceSettings.strings b/Maccy/Settings/nl.lproj/AppearanceSettings.strings index 39136c67..7e98a05c 100644 --- a/Maccy/Settings/nl.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/nl.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Toon zoekveld"; "ShowTitleBeforeSearchField" = "Toon titel voor zoekveld"; "ShowFooter" = "Toon voettekst"; +"ShowApplicationIcons" = "Toepassingspictogrammen weergeven"; "OpenPreferencesWarning" = "⚠️ Druk op ⌘, om voorkeuren te openen wanneer de voettekst verborgen is."; diff --git a/Maccy/Settings/pl.lproj/AppearanceSettings.strings b/Maccy/Settings/pl.lproj/AppearanceSettings.strings index 6e2b04eb..a04880ab 100644 --- a/Maccy/Settings/pl.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/pl.lproj/AppearanceSettings.strings @@ -1,8 +1,11 @@ -"PopupAtLastPosition" = "Ostatnia pozycja"; +"Title" = "Wygląd"; "PopupAt" = "Pozycja wyskakującego okienka:"; "PopupAtCursor" = "Wskaźnik myszy"; "PopupAtMenuBarIcon" = "Ikona menu"; "PopupAtWindowCenter" = "Środek okna"; +"PopupAtScreenCenter" = "Środek ekranu"; +"PopupAtLastPosition" = "Ostatnia pozycja"; +"PopupAtLastLocationReset" = "Zresetuj pozycję"; "PopupAtTooltip" = "Zmień miejsce gdzie pokazuje się wyskakujące okienko.\nDomyślnie: Wskaźnik myszy."; "SearchVisibilityAlways" = "Zawsze"; "SearchVisibilityDuringSearch" = "Podczas wyszukiwania"; @@ -13,6 +16,8 @@ "PinToTooltip" = "Zmień pozycję przypiętych wpisów.\nDomyślnie: góra."; "ImageHeight" = "Wysokość obrazków:"; "ImageHeightTooltip" = "Maksymalna wysokość podglądu obrazka.\nDomyślnie: 40.\nWskazówka: Wybierz 16 aby obrazek był takiej samej wysokości jak wpis tekstowy."; +"PreviewDelay" = "Opóźnienie podglądu:"; +"PreviewDelayTooltip" = "Opóźnienie w milisekundach zanim pojawi się okienko podglądu.\nDomyślnie: 1500."; "HighlightMatches" = "Podkreśl dopasowania:"; "HighlightMatchColor" = "Kolor"; "HighlightMatchBold" = "Pogrubione"; @@ -26,9 +31,5 @@ "ShowSearchField" = "Pokaż pole wyszukiwania"; "ShowTitleBeforeSearchField" = "Pokaż tytuł przed polem wyszukiwania"; "ShowFooter" = "Pokaż stopkę"; +"ShowApplicationIcons" = "Pokaż ikony aplikacji"; "OpenPreferencesWarning" = "⚠️ Naciśnij ⌘, aby otworzyć ustawienia, kiedy stopka jest ukryta."; -"Title" = "Wygląd"; -"PopupAtScreenCenter" = "Środek ekranu"; -"PopupAtLastLocationReset" = "Zresetuj pozycję"; -"PreviewDelay" = "Opóźnienie podglądu:"; -"PreviewDelayTooltip" = "Opóźnienie w milisekundach zanim pojawi się okienko podglądu.\nDomyślnie: 1500."; diff --git a/Maccy/Settings/pt-BR.lproj/AppearanceSettings.strings b/Maccy/Settings/pt-BR.lproj/AppearanceSettings.strings index 691ef92c..0858d62a 100644 --- a/Maccy/Settings/pt-BR.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/pt-BR.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Mostrar campo de busca"; "ShowTitleBeforeSearchField" = "Mostrar título antes do campo de pesquisa"; "ShowFooter" = "Mostrar rodapé"; +"ShowApplicationIcons" = "Mostrar ícones de aplicações"; "OpenPreferencesWarning" = "⚠️ Pressione ⌘, para abrir as preferências quando o rodapé estiver oculto."; diff --git a/Maccy/Settings/ru.lproj/AppearanceSettings.strings b/Maccy/Settings/ru.lproj/AppearanceSettings.strings index 399d9edd..81814d5e 100644 --- a/Maccy/Settings/ru.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/ru.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Показывать поле поиска"; "ShowTitleBeforeSearchField" = "Показывать название перед поиском"; "ShowFooter" = "Показывать нижний колонтитул"; +"ShowApplicationIcons" = "Показать значки приложений"; "OpenPreferencesWarning" = "⚠️ Нажмите ⌘, чтобы открыть настройки когда нижний колонтитул скрыт."; diff --git a/Maccy/Settings/th.lproj/AppearanceSettings.strings b/Maccy/Settings/th.lproj/AppearanceSettings.strings index b90fc444..3d58ef36 100644 --- a/Maccy/Settings/th.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/th.lproj/AppearanceSettings.strings @@ -32,3 +32,4 @@ "ShowTitleBeforeSearchField" = "แสดงหัวข้อก่อนช่องค้นหา"; "ShowFooter" = "แสดงส่วนท้าย"; "OpenPreferencesWarning" = "⚠️ กด ⌘, เพื่อเปิดการตั้งค่าเมื่อส่วนท้ายซ่อน"; +"ShowApplicationIcons" = "แสดงไอคอนแอปพลิเคชั่น"; diff --git a/Maccy/Settings/tr.lproj/AppearanceSettings.strings b/Maccy/Settings/tr.lproj/AppearanceSettings.strings index caf80ef1..6cae24dd 100644 --- a/Maccy/Settings/tr.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/tr.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Arama alanını göster"; "ShowTitleBeforeSearchField" = "Arama alanı öncesi başlığı göster"; "ShowFooter" = "Altbilgiyi göster"; +"ShowApplicationIcons" = "Uygulama simgelerini göster"; "OpenPreferencesWarning" = "⚠️ Altbilgi gizliyken ayarları açmak için ⌘,'a basın."; diff --git a/Maccy/Settings/uk.lproj/AppearanceSettings.strings b/Maccy/Settings/uk.lproj/AppearanceSettings.strings index 1f2ee743..2b4343b5 100644 --- a/Maccy/Settings/uk.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/uk.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "Показати поле пошуку"; "ShowTitleBeforeSearchField" = "Показати назву перед полем пошуку"; "ShowFooter" = "Показати нижній колонтитул"; +"ShowApplicationIcons" = "Показати іконки програм"; "OpenPreferencesWarning" = "⚠️ Натисніть ⌘, щоб відкрити параметри, коли нижній колонтитул приховано."; diff --git a/Maccy/Settings/zh-Hans.lproj/AppearanceSettings.strings b/Maccy/Settings/zh-Hans.lproj/AppearanceSettings.strings index 0711f09b..9c0302e4 100644 --- a/Maccy/Settings/zh-Hans.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/zh-Hans.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "显示搜索框"; "ShowTitleBeforeSearchField" = "在搜索框前显示应用名"; "ShowFooter" = "显示底部菜单"; +"ShowApplicationIcons" = "显示应用程序图标"; "OpenPreferencesWarning" = "⚠️ 隐藏底部菜单时仍可按 ⌘, 打开偏好设置。"; diff --git a/Maccy/Settings/zh-Hant.lproj/AppearanceSettings.strings b/Maccy/Settings/zh-Hant.lproj/AppearanceSettings.strings index 13d91165..edfe3776 100644 --- a/Maccy/Settings/zh-Hant.lproj/AppearanceSettings.strings +++ b/Maccy/Settings/zh-Hant.lproj/AppearanceSettings.strings @@ -31,4 +31,5 @@ "ShowSearchField" = "顯示搜尋框"; "ShowTitleBeforeSearchField" = "搜尋列旁顯示 Maccy"; "ShowFooter" = "顯示底部操作選單"; +"ShowApplicationIcons" = "顯示應用程式圖示"; "OpenPreferencesWarning" = "⚠️ 隱藏底部選單時,可按 ⌘, 顯示偏好設定。"; diff --git a/Maccy/Views/HistoryItemView.swift b/Maccy/Views/HistoryItemView.swift index 7bb9af14..0c4e18e4 100644 --- a/Maccy/Views/HistoryItemView.swift +++ b/Maccy/Views/HistoryItemView.swift @@ -9,6 +9,7 @@ struct HistoryItemView: View { var body: some View { ListItemView( id: item.id, + appIcon: item.applicationImage, image: item.thumbnailImage ?? ColorImage.from(item.title), attributedTitle: item.attributedTitle, shortcuts: item.shortcuts, diff --git a/Maccy/Views/ListItemTitleView.swift b/Maccy/Views/ListItemTitleView.swift index c5ce5fc6..98965b7e 100644 --- a/Maccy/Views/ListItemTitleView.swift +++ b/Maccy/Views/ListItemTitleView.swift @@ -10,13 +10,13 @@ struct ListItemTitleView: View { .accessibilityIdentifier("copy-history-item") .lineLimit(1) .truncationMode(.middle) - .padding(.leading, 10) + .padding(.leading, 5) } else { title() .accessibilityIdentifier("copy-history-item") .lineLimit(1) .truncationMode(.middle) - .padding(.leading, 10) + .padding(.leading, 5) } } } diff --git a/Maccy/Views/ListItemView.swift b/Maccy/Views/ListItemView.swift index f326113c..e23a8eae 100644 --- a/Maccy/Views/ListItemView.swift +++ b/Maccy/Views/ListItemView.swift @@ -3,6 +3,7 @@ import SwiftUI struct ListItemView: View { var id: UUID + var appIcon: ApplicationImage? var image: NSImage? var attributedTitle: AttributedString? var shortcuts: [KeyShortcut] @@ -10,19 +11,37 @@ struct ListItemView: View { var help: LocalizedStringKey? @ViewBuilder var title: () -> Title + @Default(.showApplicationIcons) private var showIcons @Environment(AppState.self) private var appState @Environment(ModifierFlags.self) private var modifierFlags var body: some View { HStack(spacing: 0) { + if showIcons, let appIcon { + VStack { + Spacer(minLength: 0) + Image(nsImage: appIcon.nsImage) + .resizable() + .frame(width: 15, height: 15) + Spacer(minLength: 0) + } + .padding(.leading, 10) + .padding(.vertical, 5) + } + if let image { Image(nsImage: image) .accessibilityIdentifier("copy-history-item") - .padding(.leading, 10) + .padding(.leading, showIcons ? 5 : 10) + .padding(.trailing, 5) .padding(.vertical, 5) } + ListItemTitleView(attributedTitle: attributedTitle, title: title) + .padding(.leading, showIcons ? 0 : 5) + Spacer() + if !shortcuts.isEmpty { ZStack { ForEach(shortcuts) { shortcut in diff --git a/Maccy/Views/PreviewItemView.swift b/Maccy/Views/PreviewItemView.swift index ff0a8869..e4a3dcb9 100644 --- a/Maccy/Views/PreviewItemView.swift +++ b/Maccy/Views/PreviewItemView.swift @@ -23,6 +23,9 @@ struct PreviewItemView: View { if let application = item.application { HStack(spacing: 3) { Text("Application", tableName: "PreviewItemView") + Image(nsImage: item.applicationImage.nsImage) + .resizable() + .frame(width: 11, height: 11) Text(application) } }