adds the ability to rename chats

This commit is contained in:
2026-05-28 22:22:55 -07:00
parent f79e5e02c5
commit cb8ea935fa
10 changed files with 455 additions and 59 deletions

View File

@@ -111,56 +111,100 @@ struct SybilSidebarItemList: View {
@Bindable var viewModel: SybilViewModel
var isSelected: (SidebarItem) -> Bool
var onSelect: (SidebarItem) -> Void
@State private var renameTarget: SidebarItem?
@State private var renameTitle = ""
private var isRenameAlertPresented: Binding<Bool> {
Binding {
renameTarget != nil
} set: { isPresented in
if !isPresented {
renameTarget = nil
renameTitle = ""
}
}
}
var body: some View {
if viewModel.isLoadingCollections && viewModel.sidebarItems.isEmpty {
VStack(alignment: .leading, spacing: 8) {
ProgressView()
.tint(SybilTheme.primary)
Text("Loading conversations…")
.font(.sybil(.footnote))
.foregroundStyle(SybilTheme.textMuted)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.padding(16)
} else if viewModel.sidebarItems.isEmpty {
VStack(spacing: 10) {
Image(systemName: "message.badge")
.font(.system(size: 20, weight: .medium))
.foregroundStyle(SybilTheme.textMuted)
Text("Start a chat or run your first search.")
.font(.sybil(.footnote))
.multilineTextAlignment(.center)
.foregroundStyle(SybilTheme.textMuted)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding(16)
} else {
ScrollView {
LazyVStack(alignment: .leading, spacing: 8) {
ForEach(viewModel.sidebarItems) { item in
Button {
onSelect(item)
} label: {
SybilSidebarRow(item: item, isSelected: isSelected(item))
}
.buttonStyle(.plain)
.contextMenu {
Button(role: .destructive) {
Task {
await viewModel.deleteItem(item.selection)
}
Group {
if viewModel.isLoadingCollections && viewModel.sidebarItems.isEmpty {
VStack(alignment: .leading, spacing: 8) {
ProgressView()
.tint(SybilTheme.primary)
Text("Loading conversations…")
.font(.sybil(.footnote))
.foregroundStyle(SybilTheme.textMuted)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.padding(16)
} else if viewModel.sidebarItems.isEmpty {
VStack(spacing: 10) {
Image(systemName: "message.badge")
.font(.system(size: 20, weight: .medium))
.foregroundStyle(SybilTheme.textMuted)
Text("Start a chat or run your first search.")
.font(.sybil(.footnote))
.multilineTextAlignment(.center)
.foregroundStyle(SybilTheme.textMuted)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding(16)
} else {
ScrollView {
LazyVStack(alignment: .leading, spacing: 8) {
ForEach(viewModel.sidebarItems) { item in
Button {
onSelect(item)
} label: {
Label("Delete", systemImage: "trash")
SybilSidebarRow(item: item, isSelected: isSelected(item))
}
.buttonStyle(.plain)
.contextMenu {
if item.kind == .chat {
Button {
renameTarget = item
renameTitle = item.title
} label: {
Label("Rename", systemImage: "pencil")
}
}
Button(role: .destructive) {
Task {
await viewModel.deleteItem(item.selection)
}
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}
.padding(10)
}
.refreshable {
await viewModel.refreshSidebarCollectionsFromPullToRefresh()
}
.padding(10)
}
.refreshable {
await viewModel.refreshSidebarCollectionsFromPullToRefresh()
}
.alert("Rename Chat", isPresented: isRenameAlertPresented) {
TextField("Title", text: $renameTitle)
Button("Cancel", role: .cancel) {
renameTarget = nil
renameTitle = ""
}
Button("Save") {
let target = renameTarget
let title = renameTitle
renameTarget = nil
renameTitle = ""
if let target, case let .chat(chatID) = target.selection {
Task {
await viewModel.renameChat(chatID: chatID, title: title)
}
}
}
.disabled(renameTitle.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
}
}
}