summaryrefslogtreecommitdiff
path: root/Hutch/Views/Projects/ProjectPinStore.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-12 22:06:16 -0500
committerChristian Cleberg <[email protected]>2026-04-12 22:06:16 -0500
commit86bcd9452d3107f68aca085e03e69b02667c0dbb (patch)
tree8b0adece5cb0f8ffb178eaab2cd12d025c9ebf0a /Hutch/Views/Projects/ProjectPinStore.swift
parent31cbca674957eea7ae2529012e20a9d95158e561 (diff)
downloadhutch-86bcd9452d3107f68aca085e03e69b02667c0dbb.tar.gz
hutch-86bcd9452d3107f68aca085e03e69b02667c0dbb.tar.bz2
hutch-86bcd9452d3107f68aca085e03e69b02667c0dbb.zip
feat: polish read-only project views and home integration
Refs: https://todo.sr.ht/~ccleberg/hutch/36 Refs: https://todo.sr.ht/~ccleberg/hutch/37 Refs: https://todo.sr.ht/~ccleberg/hutch/38
Diffstat (limited to 'Hutch/Views/Projects/ProjectPinStore.swift')
-rw-r--r--Hutch/Views/Projects/ProjectPinStore.swift32
1 files changed, 28 insertions, 4 deletions
diff --git a/Hutch/Views/Projects/ProjectPinStore.swift b/Hutch/Views/Projects/ProjectPinStore.swift
index cd3d961..77a4172 100644
--- a/Hutch/Views/Projects/ProjectPinStore.swift
+++ b/Hutch/Views/Projects/ProjectPinStore.swift
@@ -6,7 +6,7 @@ enum ProjectPinStore {
defaults: UserDefaults = .standard
) -> [String] {
let pinnedProjects = loadAll(defaults: defaults)
- return pinnedProjects[userKey] ?? []
+ return normalizedProjectIDs(pinnedProjects[userKey] ?? [])
}
static func isPinned(
@@ -23,12 +23,14 @@ enum ProjectPinStore {
defaults: UserDefaults = .standard
) {
var pinnedProjects = loadAll(defaults: defaults)
- var projectIDs = pinnedProjects[userKey] ?? []
+ var projectIDs = normalizedProjectIDs(pinnedProjects[userKey] ?? [])
if let index = projectIDs.firstIndex(of: projectID) {
projectIDs.remove(at: index)
} else {
- projectIDs.append(projectID)
+ if let normalizedProjectID = normalizedProjectID(projectID) {
+ projectIDs.append(normalizedProjectID)
+ }
}
pinnedProjects[userKey] = projectIDs
@@ -40,11 +42,33 @@ enum ProjectPinStore {
return [:]
}
- return (try? JSONDecoder().decode([String: [String]].self, from: data)) ?? [:]
+ let decoded = (try? JSONDecoder().decode([String: [String]].self, from: data)) ?? [:]
+ return decoded.reduce(into: [String: [String]]()) { result, entry in
+ let normalizedUserKey = entry.key.trimmingCharacters(in: .whitespacesAndNewlines)
+ guard !normalizedUserKey.isEmpty else { return }
+ let normalizedProjectIDs = normalizedProjectIDs(entry.value)
+ if !normalizedProjectIDs.isEmpty {
+ result[normalizedUserKey] = normalizedProjectIDs
+ }
+ }
}
private static func save(_ pinnedProjects: [String: [String]], defaults: UserDefaults) {
guard let data = try? JSONEncoder().encode(pinnedProjects) else { return }
defaults.set(data, forKey: AppStorageKeys.pinnedHomeProjects)
}
+
+ private static func normalizedProjectIDs(_ projectIDs: [String]) -> [String] {
+ var seen = Set<String>()
+ return projectIDs.compactMap { projectID in
+ guard let normalizedProjectID = normalizedProjectID(projectID) else { return nil }
+ guard seen.insert(normalizedProjectID).inserted else { return nil }
+ return normalizedProjectID
+ }
+ }
+
+ private static func normalizedProjectID(_ projectID: String) -> String? {
+ let trimmed = projectID.trimmingCharacters(in: .whitespacesAndNewlines)
+ return trimmed.isEmpty ? nil : trimmed
+ }
}