Skip to content

Commit 079eb70

Browse files
authored
Merge pull request #2402 from ThinkInAIXYZ/fix/beta5-release-checks
fix: resolve sync loading loop and composer focus
2 parents 642e015 + 1d8ad91 commit 079eb70

4 files changed

Lines changed: 46 additions & 5 deletions

File tree

‎src/main/sync/host/index.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export class SyncHostService {
135135
state.hostId = state.hostId ?? created
136136
})
137137
this.pendingHostId = null
138-
})
138+
}, false)
139139
}
140140

141141
getEnabled(): boolean {
@@ -436,8 +436,11 @@ export class SyncHostService {
436436
}
437437
}
438438

439-
private serialize<T>(step: () => Promise<T>): Promise<T> {
440-
const next = this.lifecycle.then(step, step).finally(() => this.deps.changed?.())
439+
private serialize<T>(step: () => Promise<T>, notify = true): Promise<T> {
440+
const next = this.lifecycle.then(step, step).finally(() => {
441+
// Status reads initialize state too; notifying here would trigger another status read.
442+
if (notify) this.deps.changed?.()
443+
})
441444
this.lifecycle = next.catch(() => undefined)
442445
return next
443446
}

‎src/renderer/src/components/chat/ChatInputBox.vue‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
:files="files.selectedFiles.value"
4949
:editable="editable"
5050
@file-click="windowClient.previewFile"
51-
@remove="files.deleteFile"
51+
@remove="removeShelfFile"
5252
@update:representation="updateShelfFileRepresentation"
5353
@switch-vision-model="emit('switch-vision-model')"
5454
/>
@@ -260,6 +260,12 @@ const files = useChatInputFiles(
260260
let isSyncingNodes = false
261261
let isSubmittingCommandForm = false
262262
263+
function removeShelfFile(index: number) {
264+
if (!props.editable) return
265+
files.deleteFile(index)
266+
focusInput()
267+
}
268+
263269
function updateShelfFileRepresentation(
264270
index: number,
265271
requestedRepresentation: MessageFile['requestedRepresentation']

‎test/e2e/specs/36-chat-streaming.smoke.spec.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ test('local streaming preserves an editable composer and completes the response
6969
const address = server.address() as { port: number }
7070
try {
7171
await waitForAppReady(app.page)
72+
await app.page.evaluate(async () => {
73+
await window.deepchat.invoke('config.setLanguage', { language: 'en-US' })
74+
})
7275
const providerId = await app.page.evaluate(async (baseUrl) => {
7376
const id = `custom-${crypto.randomUUID()}`
7477
await window.deepchat.invoke('providers.add', {
@@ -130,7 +133,9 @@ test('local streaming preserves an editable composer and completes the response
130133
await app.page.getByRole('button', { name: /^(Attach|添加附件)$/ }).focus()
131134
await app.page.keyboard.press('Enter')
132135
await (await chooser).setFiles(attachmentPath)
133-
const remove = editor.getByRole('button', { name: /keyboard-removal.txt/ })
136+
const remove = shell
137+
.getByTestId('attachment-shelf')
138+
.getByRole('button', { name: 'Delete keyboard-removal.txt', exact: true })
134139
await remove.focus()
135140
await app.page.keyboard.press(key)
136141
await expect(remove).toHaveCount(0)

‎test/main/sync/host/hostEndpoint.test.ts‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ describe('SyncHostService endpoint', () => {
3333
let baseUrl: string
3434
let backupBytes: Buffer
3535
let publicationDir: string
36+
let changed: ReturnType<typeof vi.fn>
3637

3738
beforeEach(async () => {
3839
tempDir = await mkdtemp(path.join(os.tmpdir(), 'deepchat-sync-host-'))
@@ -52,7 +53,9 @@ describe('SyncHostService endpoint', () => {
5253
await writeFile(path.join(syncDir, BACKUP_FILE_NAME), backupBytes)
5354

5455
publicationDir = path.join(tempDir, 'sync-host', 'snapshots')
56+
changed = vi.fn()
5557
service = new SyncHostService({
58+
changed,
5659
createBackup: async () => ({
5760
fileName: BACKUP_FILE_NAME,
5861
createdAt: 1_700_000_000_000,
@@ -690,6 +693,30 @@ describe('SyncHostService endpoint', () => {
690693
await expect(fetch(`${baseUrl}${SYNC_HOST_PATH_PREFIX}/handshake`)).rejects.toThrow()
691694
})
692695

696+
it('keeps status refreshes silent while notifying host lifecycle changes', async () => {
697+
changed.mockClear()
698+
await service.initialize()
699+
const statuses = await Promise.all([service.getStatus(), service.getStatus()])
700+
expect(statuses.map(({ running }) => running)).toEqual([true, true])
701+
expect(changed).not.toHaveBeenCalled()
702+
703+
const disabled = await service.setEnabled(false)
704+
expect(disabled.running).toBe(false)
705+
expect(changed).toHaveBeenCalled()
706+
707+
changed.mockClear()
708+
const enabled = await service.setEnabled(true, {
709+
port: Number(new URL(baseUrl).port),
710+
consent: true
711+
})
712+
expect(enabled.running).toBe(true)
713+
expect(changed).toHaveBeenCalled()
714+
715+
changed.mockClear()
716+
expect((await service.getStatus()).running).toBe(true)
717+
expect(changed).not.toHaveBeenCalled()
718+
})
719+
693720
it('keeps the listener and the enabled flag consistent under interleaved enable/disable', async () => {
694721
await Promise.all([
695722
service.setEnabled(false),

0 commit comments

Comments
 (0)