Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions Sources/Pesty/Settings/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,42 @@ private struct HistoryRetentionSettings: View {
@State private var draftDays = Settings.shared.historyRetentionDays
@State private var pendingRemovalCount = 0
@State private var confirmingChange = false
@State private var storageBytes: Int64?

private static let dayChoices: [(days: Int, label: String)] = [
(1, "1 Day"), (7, "1 Week"), (14, "2 Weeks"), (30, "1 Month"),
(90, "3 Months"), (180, "6 Months"), (365, "1 Year")
]

private var storageSummary: String {
let count = ClipboardStore.shared.history.count
let clips = "\(count) clip\(count == 1 ? "" : "s")"
guard let storageBytes else { return clips }
return "\(clips) · \(ByteCountFormatter.string(fromByteCount: storageBytes, countStyle: .file))"
}

private func refreshStorageSize() async {
let dir = ClipboardStore.shared.dataDirectory
storageBytes = await Task.detached(priority: .utility) {
Self.directorySize(at: dir)
}.value
}

/// Walks the store directory off the main actor; images can make it
/// large enough that a synchronous walk would hitch the Settings window.
nonisolated private static func directorySize(at url: URL) -> Int64 {
let keys: Set<URLResourceKey> = [.totalFileAllocatedSizeKey, .fileAllocatedSizeKey, .isRegularFileKey]
guard let enumerator = FileManager.default.enumerator(at: url,
includingPropertiesForKeys: Array(keys)) else { return 0 }
var total: Int64 = 0
for case let file as URL in enumerator {
guard let values = try? file.resourceValues(forKeys: keys),
values.isRegularFile == true else { continue }
total += Int64(values.totalFileAllocatedSize ?? values.fileAllocatedSize ?? 0)
}
return total
}

var body: some View {
Section("History") {
Picker("Limit history by", selection: $draftMode) {
Expand All @@ -270,7 +300,9 @@ private struct HistoryRetentionSettings: View {
Text(footnote)
.font(.caption)
.foregroundStyle(.secondary)
LabeledContent("Currently storing", value: storageSummary)
}
.task { await refreshStorageSize() }
.onChange(of: draftMode) { evaluateDraft() }
.onChange(of: draftLimit) { evaluateDraft() }
.onChange(of: draftDays) { evaluateDraft() }
Expand Down
4 changes: 4 additions & 0 deletions Sources/Pesty/Store/ClipboardStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ final class ClipboardStore {

var iCloudAvailable: Bool { ClipboardStore.iCloudBase != nil }

/// The on-disk store root (history JSON plus saved images), exposed so
/// Settings can report how much space history actually uses.
var dataDirectory: URL { baseDir }

private init() {
let base = (Settings.shared.iCloudSync ? ClipboardStore.iCloudBase : nil) ?? ClipboardStore.localBase
baseDir = base
Expand Down
Loading