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:
@@ -10,6 +10,10 @@ struct StartChatComposer: View {
|
||||
@State private var auto = false
|
||||
@State private var model: String?
|
||||
@State private var effort = MobileEfforts.fallback
|
||||
// Advanced options (the Mac new-session sheet's base branch + worktree fields).
|
||||
@State private var showOptions = false
|
||||
@State private var baseBranch = ""
|
||||
@State private var useWorktree = true
|
||||
|
||||
private var projects: [WireProject] { store.dashboard.projects }
|
||||
private var selected: WireProject? {
|
||||
@@ -42,6 +46,32 @@ struct StartChatComposer: View {
|
||||
ModelMenu(model: $model, catalog: store.modelCatalog, backend: nil)
|
||||
Spacer()
|
||||
EffortMenu(effort: $effort, catalog: store.modelCatalog, modelSKU: model, controlled: controlled)
|
||||
Button {
|
||||
withAnimation(.easeInOut(duration: 0.18)) { showOptions.toggle() }
|
||||
} label: {
|
||||
Image(systemName: showOptions ? "chevron.up.circle" : "ellipsis.circle")
|
||||
.font(.caption)
|
||||
.foregroundStyle(Palette.accent)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
if showOptions {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "arrow.triangle.branch").foregroundStyle(.secondary)
|
||||
TextField(selected?.defaultBranch ?? "Base branch", text: $baseBranch)
|
||||
.textInputAutocapitalization(.never)
|
||||
.autocorrectionDisabled()
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.font(.caption)
|
||||
}
|
||||
Toggle(isOn: $useWorktree) {
|
||||
Label("Run in a worktree", systemImage: "square.stack.3d.up")
|
||||
.font(.caption)
|
||||
}
|
||||
.tint(Palette.accent)
|
||||
}
|
||||
.transition(.move(edge: .top).combined(with: .opacity))
|
||||
}
|
||||
HStack(alignment: .bottom, spacing: 8) {
|
||||
TextField("Describe a task…", text: $draft, axis: .vertical)
|
||||
@@ -51,7 +81,11 @@ struct StartChatComposer: View {
|
||||
.keyboardDismissable()
|
||||
Button {
|
||||
if let project = selected {
|
||||
store.startChat(in: project.id, message: draft, model: model, effort: effort, auto: auto)
|
||||
let branch = baseBranch.trimmingCharacters(in: .whitespaces)
|
||||
store.startChat(
|
||||
in: project.id, message: draft, model: model, effort: effort,
|
||||
baseBranch: branch.isEmpty ? nil : branch,
|
||||
useWorktree: useWorktree, auto: auto)
|
||||
draft = ""
|
||||
}
|
||||
} label: {
|
||||
|
||||
Reference in New Issue
Block a user