Preserve Assistant navigation state

This commit is contained in:
Kaede Akino committed 2026-08-27 22:35:15 +08:00
1 parent 5641a28841
commit e36f470917
8 files changed
+61 -17

No files matched your search

+2 -2
View File
@@ -418,7 +418,7 @@
"@executable_path/../Frameworks",
);
LM_SKIP_METADATA_EXTRACTION = YES;
MARKETING_VERSION = 0.1.1;
MARKETING_VERSION = 0.1.2;
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -449,7 +449,7 @@
"@executable_path/../Frameworks",
);
LM_SKIP_METADATA_EXTRACTION = YES;
MARKETING_VERSION = 0.1.1;
MARKETING_VERSION = 0.1.2;
PRODUCT_BUNDLE_IDENTIFIER = com.akinokaede.termind;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
+1 -1
View File
@@ -39,7 +39,7 @@ struct TermindCommands: Commands {
app.connect(in: window)
}
.keyboardShortcut("t")
Button("New Chat") { window?.openAssistant() }
Button("New Chat") { window?.openNewAssistantChat() }
.keyboardShortcut("t", modifiers: [.command, .option])
Divider()
@@ -59,7 +59,7 @@ final class AppCommandRegistry {
guard let host = app.hostLibrary.host(id) else { return }
app.open(host, as: target, in: window)
case .newChat:
window.openAssistant()
window.openNewAssistantChat()
case .newHost:
window.openHostEditor(host: nil)
case .showAssistant:
@@ -11,7 +11,7 @@ struct AssistantSidebarView: View {
Divider()
HStack(spacing: Metrics.Space.s) {
Button {
window.openAssistant()
window.openNewAssistantChat()
} label: {
Label("New Chat", systemImage: "plus.bubble")
.frame(
@@ -532,7 +532,7 @@ struct AssistantView: View {
} else if let conversation = window.assistantLibrary.selectedConversation {
ConversationView(
conversation: conversation,
onNewChat: { window.selectAssistant() }
onNewChat: { window.openNewAssistantChat() }
)
.background(.background)
} else {
+1 -1
View File
@@ -368,7 +368,7 @@ struct TabBarView: View {
// Same order as the File menu, so the two lists of the same four
// verbs cannot be read as two different lists.
Button("Connect") { app.connect(in: window) }
Button("New Chat") { window.openAssistant() }
Button("New Chat") { window.openNewAssistantChat() }
Button("New Host") { window.openHostEditor(host: nil) }
let recents = app.hostLibrary.recents(limit: 5)
+1 -1
View File
@@ -765,7 +765,7 @@ struct WelcomeView: View {
HStack(spacing: Metrics.Space.l) {
Button("Connect") { app.connect(in: window) }
Button("Batch Startup") { app.batchStartup(in: window) }
Button("New Chat") { window.openAssistant() }
Button("New Chat") { window.openNewAssistantChat() }
}
}
+9 -7
View File
@@ -393,13 +393,15 @@ final class WindowModel {
selectedTopLevelTab = .vault
}
func selectAssistant(_ id: ConversationModel.ID? = nil) {
/// Enters the Assistant without changing its in-memory navigation state:
/// the current conversation, New Chat, and Archive are all left untouched.
func selectAssistant() {
selectedTopLevelTab = .assistant
}
func selectAssistant(_ id: ConversationModel.ID) {
isAssistantArchivePresented = false
if let id {
assistantLibrary.select(id)
} else {
assistantLibrary.selectNewConversation()
}
assistantLibrary.select(id)
selectedTopLevelTab = .assistant
}
@@ -652,7 +654,7 @@ final class WindowModel {
}
@discardableResult
func openAssistant() -> ConversationModel {
func openNewAssistantChat() -> ConversationModel {
isAssistantArchivePresented = false
let conversation = assistantLibrary.selectNewConversation()
selectedTopLevelTab = .assistant
+44 -2
View File
@@ -202,7 +202,49 @@ struct WindowStateTests {
}
@Test
func assistantDefaultsToNewChatEvenWhenHistoryExists() {
func enteringAssistantKeepsTheVolatileConversationSelection() {
let conversation = ConversationModel()
let library = AssistantLibraryModel(store: AssistantConversationStore(
conversations: [conversation]
))
let window = WindowModel(assistantLibrary: library)
window.selectAssistant(conversation.id)
window.selectVault()
window.selectAssistant()
#expect(window.selectedTopLevelTab == .assistant)
#expect(window.assistantLibrary.selectedConversation === conversation)
let draft = window.openNewAssistantChat()
#expect(window.assistantLibrary.selectedConversation == nil)
#expect(draft === window.assistantLibrary.draftConversation)
window.selectVault()
window.selectAssistant()
#expect(window.assistantLibrary.selectedConversation == nil)
#expect(draft === window.assistantLibrary.draftConversation)
}
@Test
func enteringAssistantKeepsTheVolatileArchiveDestination() {
let conversation = ConversationModel()
let library = AssistantLibraryModel(store: AssistantConversationStore(
conversations: [conversation]
))
let window = WindowModel(assistantLibrary: library)
window.selectAssistant(conversation.id)
window.showAssistantArchive()
window.selectVault()
window.selectAssistant()
#expect(window.isAssistantArchivePresented)
#expect(window.assistantLibrary.selectedConversation === conversation)
}
@Test
func assistantStartsOnNewChatWhenNoVolatileSelectionExists() {
let previousID = UUID()
let library = AssistantLibraryModel()
library.restore([
@@ -225,7 +267,7 @@ struct WindowStateTests {
@Test
func newChatJoinsHistoryOnlyAfterItsFirstSend() {
let window = WindowModel()
let draft = window.openAssistant()
let draft = window.openNewAssistantChat()
#expect(window.assistantLibrary.selectedConversation == nil)
#expect(window.assistantLibrary.conversations.isEmpty)