chore: import upstream snapshot with attribution
FreeBSD Smoke / FreeBSD Smoke (x86_64) (push) Has been cancelled
CI / Quality Guardrails (push) Has been cancelled
CI / Build & Test (macos-latest) (push) Has been cancelled
CI / Build & Test (ubuntu-latest) (push) Has been cancelled
CI / Build & Test (windows-latest) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / PowerShell Syntax (push) Has been cancelled
CI / Windows Cross-Target Check (Linux) (push) Has been cancelled
FreeBSD Smoke / FreeBSD Smoke (x86_64) (push) Has been cancelled
CI / Quality Guardrails (push) Has been cancelled
CI / Build & Test (macos-latest) (push) Has been cancelled
CI / Build & Test (ubuntu-latest) (push) Has been cancelled
CI / Build & Test (windows-latest) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / PowerShell Syntax (push) Has been cancelled
CI / Windows Cross-Target Check (Linux) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
import JCodeKit
|
||||
import SwiftUI
|
||||
|
||||
/// Sessions, servers, and info sections, split out to keep view files small.
|
||||
struct SettingsSessionsSection: View {
|
||||
@Environment(AppModel.self) private var model
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Binding var renameDraft: String
|
||||
@Binding var showRename: Bool
|
||||
|
||||
var body: some View {
|
||||
Section("Sessions") {
|
||||
ForEach(model.session.allSessions, id: \.self) { sessionID in
|
||||
sessionRow(sessionID)
|
||||
}
|
||||
Button {
|
||||
renameDraft = model.session.sessionTitle ?? ""
|
||||
showRename = true
|
||||
} label: {
|
||||
Label("Rename current session", systemImage: "pencil")
|
||||
.foregroundStyle(Theme.textPrimary)
|
||||
}
|
||||
.listRowBackground(Theme.surface)
|
||||
.accessibilityHint("Opens a field to rename the active session")
|
||||
Button {
|
||||
model.compactConversation()
|
||||
} label: {
|
||||
Label("Compact conversation", systemImage: "arrow.down.right.and.arrow.up.left")
|
||||
.foregroundStyle(Theme.textPrimary)
|
||||
}
|
||||
.listRowBackground(Theme.surface)
|
||||
.accessibilityHint("Summarizes older messages to free context")
|
||||
Button {
|
||||
model.clearConversation()
|
||||
dismiss()
|
||||
} label: {
|
||||
Label("New session (clear)", systemImage: "square.and.pencil")
|
||||
.foregroundStyle(Theme.mint)
|
||||
}
|
||||
.listRowBackground(Theme.surface)
|
||||
.accessibilityHint("Clears the conversation and starts fresh")
|
||||
}
|
||||
}
|
||||
|
||||
private func sessionRow(_ sessionID: String) -> some View {
|
||||
let isActive = sessionID == model.session.sessionID
|
||||
let title = model.session.title(forSession: sessionID)
|
||||
return Button {
|
||||
model.switchSession(sessionID)
|
||||
dismiss()
|
||||
} label: {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
if let title {
|
||||
Text(title)
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textPrimary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
Text(shortSessionID(sessionID))
|
||||
.font(Theme.mono(title == nil ? 13 : 11))
|
||||
.foregroundStyle(title == nil ? Theme.textPrimary : Theme.textTertiary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
Spacer()
|
||||
if isActive {
|
||||
Image(systemName: "checkmark")
|
||||
.font(.caption)
|
||||
.foregroundStyle(Theme.mint)
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
.listRowBackground(Theme.surface)
|
||||
.accessibilityLabel("Session \(title ?? shortSessionID(sessionID))")
|
||||
.accessibilityValue(isActive ? "Current" : "")
|
||||
.accessibilityHint("Switches to this session")
|
||||
.accessibilityAddTraits(isActive ? [.isSelected] : [])
|
||||
}
|
||||
|
||||
private func shortSessionID(_ id: String) -> String {
|
||||
if id.count > 24 {
|
||||
return String(id.prefix(24)) + "…"
|
||||
}
|
||||
return id
|
||||
}
|
||||
}
|
||||
|
||||
struct SettingsServersSection: View {
|
||||
@Environment(AppModel.self) private var model
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Binding var showPairNew: Bool
|
||||
|
||||
var body: some View {
|
||||
Section("Servers") {
|
||||
ForEach(model.servers) { server in
|
||||
let isActive = server.id == model.activeServer?.id
|
||||
Button {
|
||||
model.connect(to: server)
|
||||
dismiss()
|
||||
} label: {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text(server.serverName)
|
||||
.font(.body)
|
||||
.foregroundStyle(Theme.textPrimary)
|
||||
Text("\(server.host):\(String(server.port))")
|
||||
.font(Theme.mono(11))
|
||||
.foregroundStyle(Theme.textTertiary)
|
||||
}
|
||||
Spacer()
|
||||
if isActive {
|
||||
Circle()
|
||||
.fill(Theme.mint)
|
||||
.frame(width: 8, height: 8)
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
.listRowBackground(Theme.surface)
|
||||
.accessibilityLabel(server.serverName)
|
||||
.accessibilityValue(isActive ? "Connected" : "")
|
||||
.accessibilityHint("Connects to this server")
|
||||
.accessibilityAddTraits(isActive ? [.isSelected] : [])
|
||||
.swipeActions {
|
||||
Button(role: .destructive) {
|
||||
model.removeServer(server)
|
||||
} label: {
|
||||
Label("Remove", systemImage: "trash")
|
||||
}
|
||||
}
|
||||
}
|
||||
Button {
|
||||
showPairNew = true
|
||||
} label: {
|
||||
Label("Pair new server", systemImage: "plus")
|
||||
.foregroundStyle(Theme.mint)
|
||||
}
|
||||
.listRowBackground(Theme.surface)
|
||||
.accessibilityHint("Opens pairing to add a server")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SettingsInfoSection: View {
|
||||
@Environment(AppModel.self) private var model
|
||||
|
||||
var body: some View {
|
||||
Section("Info") {
|
||||
row("Server version", model.session.serverVersion ?? "unknown")
|
||||
row("Provider", model.session.providerName ?? "unknown")
|
||||
row(
|
||||
"Tokens",
|
||||
"\(model.session.tokenInput) in / \(model.session.tokenOutput) out"
|
||||
)
|
||||
if let detail = model.session.statusDetail {
|
||||
row("Status", detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func row(_ label: String, _ value: String) -> some View {
|
||||
HStack {
|
||||
Text(label)
|
||||
.font(.callout)
|
||||
.foregroundStyle(Theme.textSecondary)
|
||||
Spacer()
|
||||
Text(value)
|
||||
.font(Theme.mono(12))
|
||||
.foregroundStyle(Theme.textTertiary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.listRowBackground(Theme.surface)
|
||||
.accessibilityElement(children: .combine)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user