-
Notifications
You must be signed in to change notification settings - Fork 59.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Enhance cloud synchronization functionality, support syncing delete operations for messages and conversations, and add support for automatic sync settings #5236
base: main
Are you sure you want to change the base?
Changes from 56 commits
1d0a40b
78c4084
1cce87a
cd354cf
d957397
284d33b
c440637
22f6129
5065091
22c7959
faac0d9
4f876f3
648e600
93bfb55
4b22aaf
621b148
eae593d
2ee2d50
5e1064a
0a6ddda
b2336f5
31f2829
e515f0f
fdb89af
fc97c4b
0745b64
d0b7ddc
5c51fd2
2fdb35b
31baa10
f1d69cb
2d68f17
0638db1
e8c7ac0
2bf72d0
c204031
ccacfec
6dc8681
6f3d753
5ae4921
370ce3e
9551f5d
35f5288
144fdc9
659a389
60bd3c5
89edebd
41242ca
cf7c6f2
c6657d3
31900cb
c4ae73d
9a025ae
98ab561
f80da8a
3e02a71
f45a693
7f3ec6d
dfd3d24
af23929
9a95d32
b2381b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -70,6 +70,7 @@ import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
getMessageImages, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
isVisionModel, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
isDalle3, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
removeOutdatedEntries, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
showPlugins, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
safeLocalStorage, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} from "../utils"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -987,6 +988,7 @@ function _Chat() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
const chatCommands = useChatCommand({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
new: () => chatStore.newSession(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
newm: () => navigate(Path.NewChat), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
copy: () => chatStore.copySession(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
prev: () => chatStore.nextSession(-1), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
next: () => chatStore.nextSession(1), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
clear: () => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1118,10 +1120,20 @@ function _Chat() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
const deleteMessage = (msgId?: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
chatStore.updateCurrentSession( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(session) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(session.messages = session.messages.filter((m) => m.id !== msgId)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
chatStore.updateCurrentSession((session) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
session.deletedMessageIds && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
removeOutdatedEntries(session.deletedMessageIds); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
session.messages = session.messages.filter((m) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1125
to
+1126
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Initialize In the Please apply the following diff to initialize const deleteMessage = (msgId?: string) => {
chatStore.updateCurrentSession((session) => {
+ if (!session.deletedMessageIds) {
+ session.deletedMessageIds = {} as Record<string, number>;
+ }
removeOutdatedEntries(session.deletedMessageIds);
session.messages = session.messages.filter((m) => {
if (m.id !== msgId) {
return true;
}
session.deletedMessageIds[m.id] = Date.now();
return false;
});
});
}; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (m.id !== msgId) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!session.deletedMessageIds) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
session.deletedMessageIds = {} as Record<string, number>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
session.deletedMessageIds[m.id] = Date.now(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1123
to
+1136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor to avoid side effects within the Modifying Consider refactoring the code to separate the side effects from the filtering logic: chatStore.updateCurrentSession((session) => {
+ if (!session.deletedMessageIds) {
+ session.deletedMessageIds = {} as Record<string, number>;
+ }
+ session.deletedMessageIds && removeOutdatedEntries(session.deletedMessageIds);
- session.messages = session.messages.filter((m) => {
- if (m.id !== msgId) {
- return true;
- }
- session.deletedMessageIds[m.id] = Date.now();
- return false;
- });
+ session.messages = session.messages.filter((m) => m.id !== msgId);
+
+ if (msgId) {
+ session.deletedMessageIds[msgId] = Date.now();
+ }
}); This refactoring improves readability by:
📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
const onDelete = (msgId: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -361,6 +361,21 @@ function SyncConfigModal(props: { onClose?: () => void }) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</select> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</ListItem> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ListItem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
title={Locale.Settings.Sync.Config.EnableAutoSync.Title} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
subTitle={Locale.Settings.Sync.Config.EnableAutoSync.SubTitle} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type="checkbox" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
checked={syncStore.enableAutoSync} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onChange={(e) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
syncStore.update( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(config) => (config.enableAutoSync = e.currentTarget.checked), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+373
to
+375
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid assignments within expressions. The assignment within the expression can lead to confusion and potential side effects. Consider refactoring to separate the assignment from the update function call. - syncStore.update(
- (config) => (config.enableAutoSync = e.currentTarget.checked),
- );
+ const enableAutoSync = e.currentTarget.checked;
+ syncStore.update((config) => {
+ config.enableAutoSync = enableAutoSync;
+ }); Committable suggestion
Suggested change
ToolsBiome
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
></input> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</ListItem> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+365
to
+378
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor the assignment within the expression. The implementation of the automatic synchronization toggle looks good overall. However, there's a minor issue with the assignment within the expression in the To improve readability and avoid potential side effects, consider refactoring the onChange={(e) => {
- syncStore.update(
- (config) => (config.enableAutoSync = e.currentTarget.checked),
- );
+ const enableAutoSync = e.currentTarget.checked;
+ syncStore.update((config) => {
+ config.enableAutoSync = enableAutoSync;
+ });
}} This change separates the assignment from the update function call, making the code clearer and less prone to unexpected behavior. The overall implementation of the automatic synchronization feature is well-integrated into the existing UI and follows the established patterns in the codebase. 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Biome
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ListItem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
title={Locale.Settings.Sync.Config.Proxy.Title} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
subTitle={Locale.Settings.Sync.Config.Proxy.SubTitle} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,4 +1,8 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { getMessageTextContent, trimTopic } from "../utils"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
getMessageTextContent, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
trimTopic, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
removeOutdatedEntries, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} from "../utils"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { indexedDBStorage } from "@/app/utils/indexedDB-storage"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { nanoid } from "nanoid"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -29,6 +33,7 @@ import { ModelConfig, ModelType, useAppConfig } from "./config"; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { useAccessStore } from "./access"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { collectModelsWithDefaultModel } from "../utils/model"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { createEmptyMask, Mask } from "./mask"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { useSyncStore } from "./sync"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const localStorage = safeLocalStorage(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -80,6 +85,7 @@ export interface ChatSession { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lastUpdate: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lastSummarizeIndex: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
clearContextIndex?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
deletedMessageIds?: Record<string, number>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mask: Mask; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -103,6 +109,7 @@ function createEmptySession(): ChatSession { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lastUpdate: Date.now(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lastSummarizeIndex: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
deletedMessageIds: {}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mask: createEmptyMask(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -188,9 +195,19 @@ function fillTemplateWith(input: string, modelConfig: ModelConfig) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return output; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let cloudSyncTimer: any = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Specify a more precise type for Using the Apply this diff to specify a more precise type: -let cloudSyncTimer: any = null;
+let cloudSyncTimer: ReturnType<typeof setTimeout> | null = null; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function noticeCloudSync(): void { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const syncStore = useSyncStore.getState(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cloudSyncTimer && clearTimeout(cloudSyncTimer); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cloudSyncTimer = setTimeout(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
syncStore.autoSync(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, 500); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const DEFAULT_CHAT_STATE = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sessions: [createEmptySession()], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
currentSessionIndex: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
deletedSessionIds: {} as Record<string, number>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lastInput: "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -240,6 +257,28 @@ export const useChatStore = createPersistStore( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
copySession() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
set((state) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { sessions, currentSessionIndex } = state; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const emptySession = createEmptySession(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// copy the session | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const curSession = JSON.parse( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
JSON.stringify(sessions[currentSessionIndex]), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
curSession.id = emptySession.id; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
curSession.lastUpdate = emptySession.lastUpdate; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const newSessions = [...sessions]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
newSessions.splice(0, 0, curSession); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
currentSessionIndex: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sessions: newSessions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+260
to
+280
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Avoid using Using Apply this diff to use -const curSession = JSON.parse(
- JSON.stringify(sessions[currentSessionIndex]),
-);
+const curSession = structuredClone(sessions[currentSessionIndex]); If +import cloneDeep from 'lodash.clonedeep';
+
const curSession = cloneDeep(sessions[currentSessionIndex]); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
moveSession(from: number, to: number) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
set((state) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { sessions, currentSessionIndex: oldIndex } = state; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -302,7 +341,18 @@ export const useChatStore = createPersistStore( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!deletedSession) return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const sessions = get().sessions.slice(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sessions.splice(index, 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const deletedSessionIds = { ...get().deletedSessionIds }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
removeOutdatedEntries(deletedSessionIds); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const hasDelSessions = sessions.splice(index, 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (hasDelSessions?.length) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
hasDelSessions.forEach((session) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (session.messages.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
deletedSessionIds[session.id] = Date.now(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const currentIndex = get().currentSessionIndex; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let nextIndex = Math.min( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -319,19 +369,24 @@ export const useChatStore = createPersistStore( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const restoreState = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
currentSessionIndex: get().currentSessionIndex, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sessions: get().sessions.slice(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
deletedSessionIds: get().deletedSessionIds, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
set(() => ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
currentSessionIndex: nextIndex, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sessions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
deletedSessionIds, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
})); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
noticeCloudSync(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
showToast( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Locale.Home.DeleteToast, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
text: Locale.Home.Revert, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onClick() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
set(() => restoreState); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
noticeCloudSync(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
5000, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -352,13 +407,33 @@ export const useChatStore = createPersistStore( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return session; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sortSessions() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const currentSession = get().currentSession(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const sessions = get().sessions.slice(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sessions.sort( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(a, b) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new Date(b.lastUpdate).getTime() - new Date(a.lastUpdate).getTime(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+414
to
+417
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Simplify session sorting by using numeric comparison Since Apply this diff to refine the sorting function: sessions.sort(
- (a, b) =>
- new Date(b.lastUpdate).getTime() - new Date(a.lastUpdate).getTime(),
+ (a, b) => b.lastUpdate - a.lastUpdate,
);
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const currentSessionIndex = sessions.findIndex((session) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return session && currentSession && session.id === currentSession.id; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
set((state) => ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
currentSessionIndex, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sessions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
})); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+410
to
+426
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix session comparison and optimize sorting implementation. There are two issues in the sorting implementation:
Apply these fixes: sessions.sort(
- (a, b) =>
- new Date(b.lastUpdate).getTime() - new Date(a.lastUpdate).getTime(),
+ (a, b) => b.lastUpdate - a.lastUpdate,
);
const currentSessionIndex = sessions.findIndex((session) => {
- return session && currentSession && session.id === currentSession.id;
+ return session && currentSession && session.id === currentSession?.id;
}); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onNewMessage(message: ChatMessage) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get().updateCurrentSession((session) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
session.messages = session.messages.concat(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
session.lastUpdate = Date.now(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get().updateStat(message); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get().summarizeSession(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get().sortSessions(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
noticeCloudSync(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async onUserInput(content: string, attachImages?: string[]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -24,6 +24,7 @@ export type SyncStore = GetStoreState<typeof useSyncStore>; | |||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
const DEFAULT_SYNC_STATE = { | ||||||||||||||||||||||||||||||||||||||||
provider: ProviderType.WebDAV, | ||||||||||||||||||||||||||||||||||||||||
enableAutoSync: true, | ||||||||||||||||||||||||||||||||||||||||
useProxy: true, | ||||||||||||||||||||||||||||||||||||||||
proxyUrl: ApiPath.Cors as string, | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
|
@@ -43,6 +44,8 @@ const DEFAULT_SYNC_STATE = { | |||||||||||||||||||||||||||||||||||||||
lastProvider: "", | ||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
let lastSyncTime = 0; | ||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistent handling of 'lastSyncTime' The declaration of Suggestion: Use the state variable 'lastSyncTime' consistently Consider removing the module-level declaration of Apply this diff to address the issue: - let lastSyncTime = 0;
... Inside the 'sync' method:
- if (lastSyncTime && lastSyncTime >= Date.now() - 800) {
+ if (get().lastSyncTime && get().lastSyncTime >= Date.now() - 800) {
...
- lastSyncTime = Date.now();
+ set({ lastSyncTime: Date.now() });
|
||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
export const useSyncStore = createPersistStore( | ||||||||||||||||||||||||||||||||||||||||
DEFAULT_SYNC_STATE, | ||||||||||||||||||||||||||||||||||||||||
(set, get) => ({ | ||||||||||||||||||||||||||||||||||||||||
|
@@ -89,6 +92,16 @@ export const useSyncStore = createPersistStore( | |||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
async sync() { | ||||||||||||||||||||||||||||||||||||||||
if (lastSyncTime && lastSyncTime >= Date.now() - 800) { | ||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
lastSyncTime = Date.now(); | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
const enableAutoSync = get().enableAutoSync; | ||||||||||||||||||||||||||||||||||||||||
if (!enableAutoSync) { | ||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
Comment on lines
+95
to
+104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure consistent use of state for 'lastSyncTime' and 'enableAutoSync' Within the Suggestion: Retrieve both 'lastSyncTime' and 'enableAutoSync' from the state Consistently using the state ensures that all parts of the code are referencing the same source of truth. Apply this diff to make the necessary changes: - if (lastSyncTime && lastSyncTime >= Date.now() - 800) {
+ const { lastSyncTime, enableAutoSync } = get();
+ if (lastSyncTime && lastSyncTime >= Date.now() - 800) {
...
- lastSyncTime = Date.now();
+ set({ lastSyncTime: Date.now() });
...
- const enableAutoSync = get().enableAutoSync; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
const localState = getLocalAppState(); | ||||||||||||||||||||||||||||||||||||||||
const provider = get().provider; | ||||||||||||||||||||||||||||||||||||||||
const config = get()[provider]; | ||||||||||||||||||||||||||||||||||||||||
|
@@ -103,9 +116,7 @@ export const useSyncStore = createPersistStore( | |||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||
const parsedRemoteState = JSON.parse( | ||||||||||||||||||||||||||||||||||||||||
await client.get(config.username), | ||||||||||||||||||||||||||||||||||||||||
) as AppState; | ||||||||||||||||||||||||||||||||||||||||
const parsedRemoteState = JSON.parse(remoteState) as AppState; | ||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add error handling when parsing 'remoteState' Parsing Suggestion: Implement try-catch block for JSON parsing Wrap the parsing logic in a try-catch block to handle potential errors gracefully. Apply this diff: - const parsedRemoteState = JSON.parse(remoteState) as AppState;
- mergeAppState(localState, parsedRemoteState);
+ try {
+ const parsedRemoteState = JSON.parse(remoteState) as AppState;
+ mergeAppState(localState, parsedRemoteState);
+ } catch (e) {
+ console.error("[Sync] Failed to parse remote state", e);
+ showToast(Locale.Settings.Sync.ParseRemoteFailed);
+ // Optionally handle the error, e.g., by using the local state or prompting the user
+ return;
+ } 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
mergeAppState(localState, parsedRemoteState); | ||||||||||||||||||||||||||||||||||||||||
setLocalAppState(localState); | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
@@ -123,6 +134,14 @@ export const useSyncStore = createPersistStore( | |||||||||||||||||||||||||||||||||||||||
const client = this.getClient(); | ||||||||||||||||||||||||||||||||||||||||
return await client.check(); | ||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
async autoSync() { | ||||||||||||||||||||||||||||||||||||||||
const { lastSyncTime, provider } = get(); | ||||||||||||||||||||||||||||||||||||||||
const syncStore = useSyncStore.getState(); | ||||||||||||||||||||||||||||||||||||||||
if (lastSyncTime && syncStore.cloudSync()) { | ||||||||||||||||||||||||||||||||||||||||
syncStore.sync(); | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||
Comment on lines
+138
to
+144
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Simplify 'autoSync' method by using 'this' context and 'get()' Currently, the Consider refactoring async autoSync() {
- const { lastSyncTime, provider } = get();
- const syncStore = useSyncStore.getState();
- if (lastSyncTime && syncStore.cloudSync()) {
- syncStore.sync();
+ const { lastSyncTime } = get();
+ if (lastSyncTime && this.cloudSync()) {
+ await this.sync();
}
} This refactor makes the code more consistent and leverages the 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||
}), | ||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||
name: StoreKey.Sync, | ||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Incomplete
copy
Command Implementation inexporter.tsx
copy
command is defined as a no-operation function inapp/components/exporter.tsx
:copy
functionality not performing as expected within the exporter component.🔗 Analysis chain
LGTM! New
copy
command added successfully.The addition of the
copy
command to theChatCommands
interface is implemented correctly and consistently with other commands. This aligns with the PR objective of enhancing functionality.To ensure proper implementation of the new
copy
command, please run the following script:This script will help verify that the
copy
command is properly implemented and used in other parts of the codebase.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 561
Script:
Length of output: 7136