From f5f5757d0e1b78470429ae7cb9f742c95662849b Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Mon, 13 Apr 2026 13:09:57 -0500 Subject: release: v3.0.0 — navigation overhaul, Work view, and multi-pin support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reworks the app's core navigation and home screen for v3.0.0: - Replace Inbox with Work view: unified dashboard showing unread threads and assigned tickets, with All/Unread/Assigned scope picker - Overhaul Home screen: redesigned with pinned items grid (trackers, repos, mailing lists, users), recent activity section, and system status banner; backed by HomePinStore supporting all resource types - Simplify navigation bars across list screens: default toolbar shows only the primary action (+) and an overflow menu (…); pin, share, and select moved into the overflow menu; selection mode gets its own nav bar with Cancel / "N Selected" / All - Consolidate repo detail toolbars: pin and share moved into the existing actions menu for both Git and Mercurial detail views - Add recent activity tracking via RecentActivityStore - Add work and inbox deep link aliases (hutch://work, hutch://inbox) Implements: https://todo.sr.ht/~ccleberg/hutch/55 --- Hutch/Views/Projects/ProjectPinStore.swift | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'Hutch/Views/Projects/ProjectPinStore.swift') diff --git a/Hutch/Views/Projects/ProjectPinStore.swift b/Hutch/Views/Projects/ProjectPinStore.swift index 77a4172..ed7e386 100644 --- a/Hutch/Views/Projects/ProjectPinStore.swift +++ b/Hutch/Views/Projects/ProjectPinStore.swift @@ -5,6 +5,11 @@ enum ProjectPinStore { for userKey: String, defaults: UserDefaults = .standard ) -> [String] { + let generalizedPins = HomePinStore.pinnedProjectIDs(for: userKey, defaults: defaults) + if !generalizedPins.isEmpty { + return generalizedPins + } + let pinnedProjects = loadAll(defaults: defaults) return normalizedProjectIDs(pinnedProjects[userKey] ?? []) } @@ -22,6 +27,22 @@ enum ProjectPinStore { for userKey: String, defaults: UserDefaults = .standard ) { + let trimmed = projectID.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return } + + HomePinStore.togglePin( + HomePinRecord( + kind: .project, + value: trimmed, + title: "Pinned Project", + subtitle: "Project", + ownerUsername: nil, + service: nil + ), + for: userKey, + defaults: defaults + ) + var pinnedProjects = loadAll(defaults: defaults) var projectIDs = normalizedProjectIDs(pinnedProjects[userKey] ?? []) @@ -37,6 +58,14 @@ enum ProjectPinStore { save(pinnedProjects, defaults: defaults) } + static func loadLegacyPinnedProjectIDs( + for userKey: String, + defaults: UserDefaults = .standard + ) -> [String] { + let pinnedProjects = loadAll(defaults: defaults) + return normalizedProjectIDs(pinnedProjects[userKey] ?? []) + } + private static func loadAll(defaults: UserDefaults) -> [String: [String]] { guard let data = defaults.data(forKey: AppStorageKeys.pinnedHomeProjects) else { return [:] -- cgit v1.2.3