mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
✨ feat: 支持会话置顶 (#32)
This commit is contained in:
@@ -19,10 +19,9 @@ interface SessionItemProps {
|
||||
active?: boolean;
|
||||
id: string;
|
||||
loading?: boolean;
|
||||
pin?: boolean;
|
||||
}
|
||||
|
||||
const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading, pin }) => {
|
||||
const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading }) => {
|
||||
const ref = useRef(null);
|
||||
const isHovering = useHover(ref);
|
||||
|
||||
@@ -33,6 +32,7 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading, pi
|
||||
const [defaultModel] = useSettings((s) => [s.settings.model], shallow);
|
||||
|
||||
const [
|
||||
pin,
|
||||
title,
|
||||
description,
|
||||
systemRole,
|
||||
@@ -42,11 +42,13 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading, pi
|
||||
model,
|
||||
chatLength,
|
||||
removeSession,
|
||||
pinSession,
|
||||
] = useSessionStore((s) => {
|
||||
const session = sessionSelectors.getSessionById(id)(s);
|
||||
const meta = session.meta;
|
||||
const systemRole = session.config.systemRole;
|
||||
return [
|
||||
session.pinned,
|
||||
agentSelectors.getTitle(meta),
|
||||
meta.description,
|
||||
systemRole,
|
||||
@@ -56,6 +58,7 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading, pi
|
||||
session.config.model,
|
||||
chatSelectors.currentChats(s).length,
|
||||
s.removeSession,
|
||||
s.pinSession,
|
||||
];
|
||||
}, shallow);
|
||||
|
||||
@@ -66,8 +69,9 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading, pi
|
||||
icon: <Icon icon={pin ? PinOff : Pin} />,
|
||||
key: 'pin',
|
||||
label: t(pin ? 'pinOff' : 'pin'),
|
||||
// TODO: 动作绑定
|
||||
onClick: () => {},
|
||||
onClick: () => {
|
||||
pinSession(id, !pin);
|
||||
},
|
||||
},
|
||||
{
|
||||
children: [
|
||||
@@ -154,7 +158,16 @@ const SessionItem: FC<SessionItemProps> = memo(({ id, active = true, loading, pi
|
||||
style={{ color: theme.colorText }}
|
||||
title={title}
|
||||
/>
|
||||
<Dropdown arrow={false} menu={{ items }} trigger={['click']}>
|
||||
<Dropdown
|
||||
arrow={false}
|
||||
menu={{
|
||||
items,
|
||||
onClick: ({ domEvent }) => {
|
||||
domEvent.stopPropagation();
|
||||
},
|
||||
}}
|
||||
trigger={['click']}
|
||||
>
|
||||
<ActionIcon
|
||||
className="session-remove"
|
||||
icon={MoreVertical}
|
||||
|
||||
@@ -31,6 +31,11 @@ export interface SessionAction {
|
||||
*/
|
||||
importSessions: (sessions: LobeSessions) => void;
|
||||
|
||||
/**
|
||||
* 置顶会话
|
||||
* @param sessionId
|
||||
*/
|
||||
pinSession: (sessionId: string, pinned?: boolean) => void;
|
||||
/**
|
||||
* 生成压缩后的消息
|
||||
* @returns 压缩后的消息
|
||||
@@ -42,12 +47,13 @@ export interface SessionAction {
|
||||
* @returns void
|
||||
*/
|
||||
removeSession: (sessionId: string) => void;
|
||||
|
||||
/**
|
||||
* @title 切换会话
|
||||
* @param sessionId - 会话索引
|
||||
* @returns void
|
||||
*/
|
||||
switchSession: (sessionId?: string | 'new') => Promise<void>;
|
||||
switchSession: (sessionId?: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export const createSessionSlice: StateCreator<
|
||||
@@ -104,6 +110,19 @@ export const createSessionSlice: StateCreator<
|
||||
}),
|
||||
});
|
||||
},
|
||||
// genShareUrl: () => {
|
||||
// const session = sessionSelectors.currentSession(get());
|
||||
// if (!session) return '';
|
||||
//
|
||||
// const agent = session.config;
|
||||
// return genShareMessagesUrl(session.chats, agent.systemRole);
|
||||
// },
|
||||
pinSession: (sessionId, pinned) => {
|
||||
const nextValue = typeof pinned === 'boolean' ? pinned : !get().sessions[sessionId].pinned;
|
||||
|
||||
get().dispatchSession({ id: sessionId, pinned: nextValue, type: 'toggleSessionPinned' });
|
||||
},
|
||||
|
||||
removeSession: (sessionId) => {
|
||||
get().dispatchSession({ id: sessionId, type: 'removeSession' });
|
||||
|
||||
@@ -122,11 +141,4 @@ export const createSessionSlice: StateCreator<
|
||||
// 新会话
|
||||
await Router.push(`/chat/${sessionId}`);
|
||||
},
|
||||
// genShareUrl: () => {
|
||||
// const session = sessionSelectors.currentSession(get());
|
||||
// if (!session) return '';
|
||||
//
|
||||
// const agent = session.config;
|
||||
// return genShareMessagesUrl(session.chats, agent.systemRole);
|
||||
// },
|
||||
});
|
||||
|
||||
@@ -63,6 +63,11 @@ interface UpdateSessionAgentConfig {
|
||||
id: string;
|
||||
type: 'updateSessionConfig';
|
||||
}
|
||||
interface ToggleSessionPinned {
|
||||
id: string;
|
||||
pinned: boolean;
|
||||
type: 'toggleSessionPinned';
|
||||
}
|
||||
|
||||
export type SessionDispatch =
|
||||
| AddSession
|
||||
@@ -70,7 +75,8 @@ export type SessionDispatch =
|
||||
| RemoveSession
|
||||
| UpdateSessionMeta
|
||||
| UpdateSessionAgentConfig
|
||||
| UpdateSessionTopic;
|
||||
| UpdateSessionTopic
|
||||
| ToggleSessionPinned;
|
||||
|
||||
export const sessionsReducer = (state: LobeSessions, payload: SessionDispatch): LobeSessions => {
|
||||
switch (payload.type) {
|
||||
@@ -89,6 +95,16 @@ export const sessionsReducer = (state: LobeSessions, payload: SessionDispatch):
|
||||
});
|
||||
}
|
||||
|
||||
case 'toggleSessionPinned': {
|
||||
return produce(state, (draft) => {
|
||||
const { pinned, id } = payload;
|
||||
const session = draft[id];
|
||||
if (!session) return;
|
||||
|
||||
session.pinned = pinned;
|
||||
});
|
||||
}
|
||||
|
||||
case 'updateSessionMeta': {
|
||||
return produce(state, (draft) => {
|
||||
const chat = draft[payload.id];
|
||||
|
||||
@@ -21,8 +21,19 @@ export const sessionList = (s: SessionStore) => {
|
||||
.map((c) => c.content)
|
||||
.join(''),
|
||||
]);
|
||||
|
||||
return Object.values(filterChats).sort((a, b) => (b.updateAt || 0) - (a.updateAt || 0));
|
||||
// 先按照 `pinned` 字段进行排序,置顶的会排在前面。然后,根据 `updateAt` 字段进行倒序排序。
|
||||
return Object.values(filterChats).sort((a, b) => {
|
||||
if (a.pinned && !b.pinned) {
|
||||
return -1;
|
||||
}
|
||||
if (!a.pinned && b.pinned) {
|
||||
return 1;
|
||||
}
|
||||
if (a.updateAt && b.updateAt) {
|
||||
return b.updateAt - a.updateAt;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
export const getSessionById =
|
||||
|
||||
@@ -19,6 +19,13 @@ interface LobeSessionBase extends BaseDataModel {
|
||||
* 聊天记录
|
||||
*/
|
||||
chats: ChatMessageMap;
|
||||
/**
|
||||
* 置顶
|
||||
*/
|
||||
pinned?: boolean;
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
topics?: ChatTopicMap;
|
||||
/**
|
||||
* 每个会话的类别
|
||||
|
||||
Reference in New Issue
Block a user