Compare commits
1 Commits
wip/spacer
...
ios-pull-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9572d0320f |
@@ -5,6 +5,7 @@ struct SybilChatTranscriptView: View {
|
||||
var messages: [Message]
|
||||
var isLoading: Bool
|
||||
var isSending: Bool
|
||||
var onRefresh: (() async -> Void)? = nil
|
||||
@State private var hasHandledInitialTranscriptScroll = false
|
||||
|
||||
private var hasPendingAssistant: Bool {
|
||||
@@ -51,6 +52,10 @@ struct SybilChatTranscriptView: View {
|
||||
.padding(.vertical, 18)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.refreshable {
|
||||
await onRefresh?()
|
||||
}
|
||||
.tint(SybilTheme.primary)
|
||||
.scrollDismissesKeyboard(.interactively)
|
||||
.onAppear {
|
||||
scrollToBottom(with: proxy, animated: false)
|
||||
|
||||
@@ -132,6 +132,10 @@ private struct SybilPhoneSidebarRoot: View {
|
||||
}
|
||||
.padding(10)
|
||||
}
|
||||
.refreshable {
|
||||
await viewModel.refreshCollectionsFromUser()
|
||||
}
|
||||
.tint(SybilTheme.primary)
|
||||
}
|
||||
}
|
||||
.background(SybilTheme.panelGradient)
|
||||
|
||||
@@ -6,6 +6,7 @@ struct SybilSearchResultsView: View {
|
||||
var isLoading: Bool
|
||||
var isRunning: Bool
|
||||
var isStartingChat: Bool = false
|
||||
var onRefresh: (() async -> Void)? = nil
|
||||
var onStartChat: (() -> Void)? = nil
|
||||
|
||||
var body: some View {
|
||||
@@ -100,6 +101,10 @@ struct SybilSearchResultsView: View {
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.vertical, 20)
|
||||
}
|
||||
.refreshable {
|
||||
await onRefresh?()
|
||||
}
|
||||
.tint(SybilTheme.primary)
|
||||
.scrollDismissesKeyboard(.interactively)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
@@ -149,6 +149,10 @@ struct SybilSidebarView: View {
|
||||
}
|
||||
.padding(10)
|
||||
}
|
||||
.refreshable {
|
||||
await viewModel.refreshCollectionsFromUser()
|
||||
}
|
||||
.tint(SybilTheme.primary)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -471,6 +471,34 @@ final class SybilViewModel {
|
||||
select(nextSelection)
|
||||
}
|
||||
|
||||
func refreshCollectionsFromUser() async {
|
||||
guard isAuthenticated else {
|
||||
return
|
||||
}
|
||||
|
||||
errorMessage = nil
|
||||
|
||||
guard draftKind == nil else {
|
||||
await refreshCollectionsPreservingDraft()
|
||||
return
|
||||
}
|
||||
|
||||
await refreshCollections(preferredSelection: selectedItem)
|
||||
}
|
||||
|
||||
func refreshSelectionFromUser() async {
|
||||
guard isAuthenticated, !isSending, !isCreatingSearchChat else {
|
||||
return
|
||||
}
|
||||
|
||||
guard selectedItem != nil, draftKind == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
errorMessage = nil
|
||||
await refreshSelectionIfNeeded()
|
||||
}
|
||||
|
||||
func deleteItem(_ selection: SidebarSelection) async {
|
||||
guard isAuthenticated else {
|
||||
return
|
||||
@@ -710,6 +738,30 @@ final class SybilViewModel {
|
||||
settings.persist()
|
||||
}
|
||||
|
||||
private func refreshCollectionsPreservingDraft() async {
|
||||
isLoadingCollections = true
|
||||
|
||||
do {
|
||||
let client = try client()
|
||||
async let chatsValue = client.listChats()
|
||||
async let searchesValue = client.listSearches()
|
||||
let (nextChats, nextSearches) = try await (chatsValue, searchesValue)
|
||||
|
||||
chats = nextChats
|
||||
searches = nextSearches
|
||||
|
||||
SybilLog.info(
|
||||
SybilLog.app,
|
||||
"Refreshed collections for draft: \(nextChats.count) chats, \(nextSearches.count) searches"
|
||||
)
|
||||
} catch {
|
||||
errorMessage = normalizeAPIError(error)
|
||||
SybilLog.error(SybilLog.app, "Refresh draft collections failed", error: error)
|
||||
}
|
||||
|
||||
isLoadingCollections = false
|
||||
}
|
||||
|
||||
private func refreshCollections(
|
||||
preferredSelection: SidebarSelection?,
|
||||
refreshSelection: Bool = true
|
||||
|
||||
@@ -127,7 +127,10 @@ struct SybilWorkspaceView: View {
|
||||
search: viewModel.selectedSearch,
|
||||
isLoading: viewModel.isLoadingSelection,
|
||||
isRunning: viewModel.isSending,
|
||||
isStartingChat: viewModel.isCreatingSearchChat
|
||||
isStartingChat: viewModel.isCreatingSearchChat,
|
||||
onRefresh: {
|
||||
await viewModel.refreshSelectionFromUser()
|
||||
}
|
||||
) {
|
||||
Task {
|
||||
await viewModel.startChatFromSelectedSearch()
|
||||
@@ -137,7 +140,10 @@ struct SybilWorkspaceView: View {
|
||||
SybilChatTranscriptView(
|
||||
messages: viewModel.displayedMessages,
|
||||
isLoading: viewModel.isLoadingSelection,
|
||||
isSending: viewModel.isSending
|
||||
isSending: viewModel.isSending,
|
||||
onRefresh: {
|
||||
await viewModel.refreshSelectionFromUser()
|
||||
}
|
||||
)
|
||||
.id(transcriptScrollContextID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user