Merge branch 'dev' into canary

This commit is contained in:
2026-07-05 18:00:23 -07:00
3 changed files with 11 additions and 12 deletions
@@ -16,7 +16,6 @@ struct StartChatComposer: View {
@State private var auto = false @State private var auto = false
@State private var model: String? @State private var model: String?
@State private var effort = MobileEfforts.fallback @State private var effort = MobileEfforts.fallback
@FocusState private var draftFocused: Bool
// Advanced options (the Mac new-session sheet's base branch + worktree fields). // Advanced options (the Mac new-session sheet's base branch + worktree fields).
@State private var showOptions = false @State private var showOptions = false
@State private var baseBranch = "" @State private var baseBranch = ""
@@ -86,15 +85,14 @@ struct StartChatComposer: View {
.transition(.move(edge: .top).combined(with: .opacity)) .transition(.move(edge: .top).combined(with: .opacity))
} }
HStack(alignment: .bottom, spacing: 8) { HStack(alignment: .bottom, spacing: 8) {
// Plain, borderless field over the glass — matching the open session's chat bar // Plain, borderless field — matching the open session's chat bar rather than a
// rather than a boxed form control. // boxed form control.
TextField("Describe a task…", text: $draft, axis: .vertical) TextField("Describe a task…", text: $draft, axis: .vertical)
.textFieldStyle(.plain) .textFieldStyle(.plain)
.lineLimit(1...5) .lineLimit(1...5)
.padding(.vertical, 3) .padding(.vertical, 3)
.orchestraGlow(active: MobileEfforts.isOrchestra(effort) && controlled) .orchestraGlow(active: MobileEfforts.isOrchestra(effort) && controlled)
.keyboardDismissable() .keyboardDismissable()
.focused($draftFocused)
Button { Button {
if let project = selected { if let project = selected {
let branch = baseBranch.trimmingCharacters(in: .whitespaces) let branch = baseBranch.trimmingCharacters(in: .whitespaces)
@@ -115,9 +113,8 @@ struct StartChatComposer: View {
Text("This device is view-only.").font(.caption2).foregroundStyle(.secondary) Text("This device is view-only.").font(.caption2).foregroundStyle(.secondary)
} }
} }
.padding(.horizontal, 14) // No surface of its own — the controls sit directly on the sheet, which is already a
.padding(.vertical, 12) // distinct panel; a glass card here would just be a card-on-card.
.glassSurface(cornerRadius: 26)
// Switching to a model with a lower effort cap can't leave an unsupported level selected. // Switching to a model with a lower effort cap can't leave an unsupported level selected.
.onChange(of: model) { _, newModel in .onChange(of: model) { _, newModel in
let levels = store.modelCatalog.offeredEfforts(forModel: newModel) let levels = store.modelCatalog.offeredEfforts(forModel: newModel)
@@ -106,13 +106,14 @@ struct HomeView: View {
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.scrollDismissesKeyboard(.interactively) .scrollDismissesKeyboard(.interactively)
.refreshable { store.refreshSessions() } .refreshable { store.refreshSessions() }
// A floating "+" replaces the old inline start-chat card; opens the glass composer
// sheet. An iPad ⌘N (via focusNewChat) opens the same sheet.
.newChatAffordance(isPresented: $showNewChat)
.onChange(of: focusNewChat.wrappedValue) { _, want in .onChange(of: focusNewChat.wrappedValue) { _, want in
if want { showNewChat = true; focusNewChat.wrappedValue = false } if want { showNewChat = true; focusNewChat.wrappedValue = false }
} }
.safeAreaInset(edge: .bottom) { ConnectionChip().padding(.bottom, 8) } .safeAreaInset(edge: .bottom) { ConnectionChip().padding(.bottom, 8) }
// A floating "+" replaces the old inline start-chat card; opens the glass composer
// sheet. An iPad ⌘N (via focusNewChat) opens the same sheet. Applied after the chip
// inset so it anchors to the true bottom — matching the project page's tight spacing.
.newChatAffordance(isPresented: $showNewChat)
} }
} }
@@ -85,11 +85,12 @@ struct SessionsView: View {
} }
} }
} }
.safeAreaInset(edge: .bottom) { ConnectionChip().padding(.bottom, 8) }
// A floating "new chat" affordance in the lower-right, mirroring the Mac's per-project // A floating "new chat" affordance in the lower-right, mirroring the Mac's per-project
// "New chat" button. Picks a project + prompt in a glass sheet, then kicks off the chat. // "New chat" button. Picks a project + prompt in a glass sheet, then kicks off the chat.
// Applied before the chip inset so it floats clear above the connection chip. // Applied after the chip inset so it anchors to the true bottom — the same low spacing
// above the tab bar the project page has, rather than floating high above the chip.
.newChatAffordance(isPresented: $showNewChat) .newChatAffordance(isPresented: $showNewChat)
.safeAreaInset(edge: .bottom) { ConnectionChip().padding(.bottom, 8) }
} }
} }