ios: full feature/appearance parity with the macOS app (client-side)

Port the Mac's MarkdownText renderer, AppPalette (color-vision modes +
night-softening), appearance settings (theme/text size/color vision),
and BuildBanner channel strip to the iPhone remote. Add session-row
attention/unseen-completion washes and marker icons, Discard action,
branch/worktree options in the new-chat composer, and a transient
error bubble for host wire errors. Stamp the build channel via
NucleicChannel in Info.plist (ios-release.sh passes NUCLEIC_CHANNEL,
default beta). Demo mode gains NUCLEIC_DEMO_SESSION and skips the
notifications prompt so UI previews are scriptable.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
2026-07-02 16:06:32 -07:00
co-authored by Claude Fable 5
parent 79a28605b3
commit a33ab80313
11 changed files with 843 additions and 47 deletions
@@ -11,6 +11,7 @@ struct SessionDetailView: View {
@State private var showRename = false
@State private var renameDraft = ""
@State private var showIntegrate = false
@State private var showDiscard = false
private var summary: WireSessionSummary? {
store.sessions.first { $0.sessionID == sessionID }
@@ -56,6 +57,13 @@ struct SessionDetailView: View {
Button("Rebase") { store.integrate(sessionID, .rebase) }
Button("Cancel", role: .cancel) {}
}
.confirmationDialog(
"Discard this session's branch and worktree? Unmerged work is lost.",
isPresented: $showDiscard, titleVisibility: .visible
) {
Button("Discard", role: .destructive) { store.discard(sessionID) }
Button("Cancel", role: .cancel) {}
}
.onAppear { store.open(sessionID) }
.onDisappear { store.closeOpen() }
}
@@ -147,6 +155,9 @@ struct SessionDetailView: View {
}
Section {
Button { showIntegrate = true } label: { Label("Integrate…", systemImage: "arrow.triangle.merge") }
Button(role: .destructive) { showDiscard = true } label: {
Label("Discard…", systemImage: "xmark.bin")
}
Button { store.setArchived(sessionID, !summary.archived) } label: {
Label(summary.archived ? "Unarchive" : "Archive",
systemImage: summary.archived ? "tray.and.arrow.up" : "archivebox")