- Merge button: use the proper SF Symbol 'arrow.triangle.merge' instead of
the download icon 'arrow.down.circle'.
- Add a Settings toggle 'Delete branch after merge'. When on, the merge call
passes delete_branch_after_merge=true and the head branch is deleted after
a successful merge (best-effort).
- PR detail bottom tab bar: floating capsule style (regularMaterial + shadow)
like the latest iOS tab bars, instead of a full-width bar.
- Bump to 2.0.
- Remove the Commits tab (not useful).
- Move the section switcher to a bottom tab bar with icons (Overview /
Conversation / Files / Checks) instead of a top segmented control.
- Move Review (menu) and Merge into the navigation toolbar, removing the
bottom action bar.
- Add an Overview tab that renders the PR body as markdown via SwiftUI's
built-in AttributedString(markdown:) (no third-party dependency).
- Bump to 1.9.
- Checks: only show the Logs button once a job has actually run (terminal
conclusion). Queued/running jobs are grey with no logs, so the button was
useless there.
- Inbox: remove the segmented filter bar (All/Assigned/By me/Review) — not
useful yet. Bump to 1.8.
Commits tab was empty: Gitea PR commits have no 'id' field (only sha), but
PRCommit.id was a non-optional let decoded from 'id', so decoding [PRCommit]
always threw and the tab silently showed nothing. Make PRCommit.id a computed
sha-based identity so the array decodes and renders.
CI: add a Logs button per job that fetches the job's raw log text
(/actions/jobs/{id}/logs) into a viewable, shareable screen. Bump to 1.7.
The diff data was fine, but the render collapsed: a LazyVStack inside a
dual-axis ScrollView([.horizontal, .vertical]) gets an unbounded proposal and
rows collapse to near-zero width — the green addition background rendered but
the monospaced text was laid out at ~0 width and disappeared. Use a plain
VStack inside nested vertical→horizontal ScrollViews (the stable pattern for
diff text) and give each line fixedSize(horizontal:) so the text isn't
clipped. Bump to 1.6.
DiffLine.id was a computed property returning a fresh UUID() on every access.
SwiftUI's ForEach requires stable identities; regenerating each read churned
the main thread, hanging the diff screen and eventually crashing. Store the
UUID once per line. Also add a 30s URLRequest timeout so a hung request can't
leave the 'Loading diff...' spinner forever. Bump to 1.5.
This Gitea instance never returns a 'patch' field from /pulls/{n}/files (the
field is absent for all files, regardless of size), so the diff viewer always
fell back to 'Diff too large to preview'. Now DiffView fetches the PR's .diff
endpoint (plain-text unified diff), extracts the hunks for the selected file,
and renders them colour-coded. Bump to 1.4.
Opening a PR could fail the whole screen when any one detail sub-request
returns 401/403 (e.g. a token scope the repo's Actions endpoint needs).
Refactor load() so the PR fetch is the only fatal call; comments/reviews/
files/commits/runs each fail independently, are logged, and the rest still
render. Also log actions/runs failures for visibility. Bump to 1.3.
LogStore is @MainActor; GiteaClient.request is not main-actor-isolated, so the
5 LogStore.shared.log calls in the request handler need 'await' under Swift 5
strict concurrency. Without them the build fails at compile time.
- LogStore: bounded in-memory + persisted log of API calls and errors,
viewable and shareable from Settings → View logs.
- GiteaClient: log every request/response status (esp. 404s).
- Inbox: a single failing repo no longer wipes the whole inbox — per-repo
errors are caught, logged, and the rest still load.
- Bump to 1.2 so SideStore offers the update.
SideStore only shows an update when the version changes; the previous build
stayed at 1.0 so no update appeared. Bump MARKETING_VERSION to 1.1 and have
the workflow read CFBundleShortVersionString from the built app's Info.plist
instead of a hardcoded VERSION, so the metadata can never drift from the
pbxproj again.
Gitea returns dates like 2026-08-12T11:09:13+02:00. The default JSONDecoder
date strategy expects a Unix timestamp number, so decoding any Date? field
threw and the whole [PullRequest] array failed — the inbox showed no PRs.
Add a shared decoder with a custom ISO8601 strategy (with and without
fractional seconds) and use it for all get/post decoding.
Multi-repo PR inbox, review (approve/request changes/comment), merge with
gating toggle, read-only diff viewer, and Gitea Actions check status with
one-tap re-run. Ships unsigned via the iMac runner to the SideStore source.