From 86bcd9452d3107f68aca085e03e69b02667c0dbb Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Sun, 12 Apr 2026 22:06:16 -0500 Subject: 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 --- Hutch/Views/Projects/ProjectPinStore.swift | 32 ++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'Hutch/Views/Projects/ProjectPinStore.swift') 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() + 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 + } } -- cgit v1.2.3