From ae2601ba734f7bee22ac1adf7048c617085e2085 Mon Sep 17 00:00:00 2001 From: Aksell Date: Mon, 4 May 2026 22:59:26 +0200 Subject: [PATCH] Improved Settings entry. removeOldestItem() function Added Background cleanup Cleanup interval (Time set / 2) to avoid unnecessary cpu cycles --- Maccy/Clipboard.swift | 11 ++++++++ Maccy/Extensions/Defaults.Keys+Names.swift | 1 + Maccy/Observables/History.swift | 28 ++++++++++++++++--- Maccy/Settings/StorageSettingsPane.swift | 15 ++++++++++ .../Settings/en.lproj/StorageSettings.strings | 2 ++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/Maccy/Clipboard.swift b/Maccy/Clipboard.swift index 389afb9bd..baed6f950 100644 --- a/Maccy/Clipboard.swift +++ b/Maccy/Clipboard.swift @@ -9,6 +9,7 @@ class Clipboard { private var onNewCopyHooks: [OnNewCopyHook] = [] var changeCount: Int + var lastCleanup: Date private let pasteboard = NSPasteboard.general @@ -37,6 +38,7 @@ class Clipboard { init() { changeCount = pasteboard.changeCount + lastCleanup = Date() } func onNewCopy(_ hook: @escaping OnNewCopyHook) { @@ -148,6 +150,15 @@ class Clipboard { @objc @MainActor func checkForChangesInPasteboard() { // swiftlint:disable:this cyclomatic_complexity + + let cleanUpInterval = (Defaults[.time] * 3600) / 2 + + if (Date().timeIntervalSince(lastCleanup) > cleanUpInterval) { + // Remove items older than time limit in background + History.shared.removeOldestItem(to: Defaults[.time]) + lastCleanup = Date() + } + guard pasteboard.changeCount != changeCount else { return } diff --git a/Maccy/Extensions/Defaults.Keys+Names.swift b/Maccy/Extensions/Defaults.Keys+Names.swift index 4a08a4bc2..6454e74ed 100644 --- a/Maccy/Extensions/Defaults.Keys+Names.swift +++ b/Maccy/Extensions/Defaults.Keys+Names.swift @@ -53,6 +53,7 @@ extension Defaults.Keys { static let showSpecialSymbols = Key("showSpecialSymbols", default: true) static let showTitle = Key("showTitle", default: true) static let size = Key("historySize", default: 200) + static let time = Key("timeLimit", default: 8) static let sortBy = Key("sortBy", default: .lastCopiedAt) static let suppressClearAlert = Key("suppressClearAlert", default: false) static let windowSize = Key("windowSize", default: NSSize(width: 450, height: 800)) diff --git a/Maccy/Observables/History.swift b/Maccy/Observables/History.swift index e5804ad19..fdbeeb758 100644 --- a/Maccy/Observables/History.swift +++ b/Maccy/Observables/History.swift @@ -107,7 +107,10 @@ class History: ItemsContainer { // swiftlint:disable:this type_body_length let results = try Storage.shared.context.fetch(descriptor) all = sorter.sort(results).map { HistoryItemDecorator($0) } items = all - + + // check and remove older items + removeOldestItem(to: Defaults[.time]) + limitHistorySize(to: Defaults[.size]) updateShortcuts() @@ -116,6 +119,23 @@ class History: ItemsContainer { // swiftlint:disable:this type_body_length AppState.shared.popup.needsResize = true } } + + @MainActor + func removeOldestItem(to timeInHours: Double) { + if (timeInHours == 0) { + return + } + if (all.isEmpty) { + return + } + let timeInSeconds = timeInHours * 3600 + let oldest = all.filter{ + $0.isUnpinned && (Date().timeIntervalSince($0.item.lastCopiedAt) > timeInSeconds) + }; + if oldest.count != 0 { + oldest.forEach(delete) + } + } @MainActor private func limitHistorySize(to maxSize: Int) { @@ -170,7 +190,9 @@ class History: ItemsContainer { // swiftlint:disable:this type_body_length // 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) - + + removeOldestItem(to: Defaults[.time]) + sessionLog[Clipboard.shared.changeCount] = item var itemDecorator: HistoryItemDecorator @@ -473,7 +495,6 @@ class History: ItemsContainer { // swiftlint:disable:this type_body_length return item } - updateUnpinnedShortcuts() } @@ -483,7 +504,6 @@ class History: ItemsContainer { // swiftlint:disable:this type_body_length item.shortcuts = KeyShortcut.create(character: pin) } } - updateUnpinnedShortcuts() } diff --git a/Maccy/Settings/StorageSettingsPane.swift b/Maccy/Settings/StorageSettingsPane.swift index 143032554..d83e28784 100644 --- a/Maccy/Settings/StorageSettingsPane.swift +++ b/Maccy/Settings/StorageSettingsPane.swift @@ -57,6 +57,7 @@ struct StorageSettingsPane: View { } @Default(.size) private var size + @Default(.time) private var time @Default(.sortBy) private var sortBy @State private var viewModel = ViewModel() @@ -108,6 +109,20 @@ struct StorageSettingsPane: View { } } } + + Settings.Section(label: { Text("Time", tableName: "StorageSettings") }) { + HStack { + TextField("", value: $time, formatter: sizeFormatter) + .frame(width: 80) + .help(Text("TimeToolTip", tableName: "StorageSettings")) + Stepper("", value: $time, in: 0...48) + .labelsHidden() + Text(time != 1 ? "hours" : "hour") + .controlSize(.small) + .foregroundStyle(.gray) + .help(Text("TimeToolTip", tableName: "StorageSettings")) + } + } Settings.Section(label: { Text("SortBy", tableName: "StorageSettings") }) { Picker("", selection: $sortBy) { diff --git a/Maccy/Settings/en.lproj/StorageSettings.strings b/Maccy/Settings/en.lproj/StorageSettings.strings index 571a68d03..febe59c0c 100644 --- a/Maccy/Settings/en.lproj/StorageSettings.strings +++ b/Maccy/Settings/en.lproj/StorageSettings.strings @@ -7,6 +7,8 @@ "Size" = "Size:"; "SizeTooltip" = "Number of history items to keep.\nDefault: 200."; "CurrentSizeTooltip" = "Current size on disk."; +"Time" = "Keep for:"; +"TimeToolTip" = "How long to keep items in history.\nDefault: 8 hours."; "SortBy" = "Sort by:"; "LastCopiedAt" = "Time of last copy"; "FirstCopiedAt" = "Time of first copy";