feat(core): restore pinned chat for independent chat (#13154)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Improved chat session management by automatically restoring a pinned
chat session when opening the workspace chat.

* **Enhancements**
* Added support for cancelling certain requests, improving
responsiveness and user experience.

* **Style**
* Updated the label "AFFiNE Intelligence" to "Intelligence" in relevant
UI components for a more concise display.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Cats Juice
2025-07-11 12:45:59 +08:00
committed by GitHub
parent af9c455ee0
commit 2dacba9011
4 changed files with 42 additions and 3 deletions
+5
View File
@@ -82,6 +82,10 @@ export type RequestOptions<Q extends GraphQLQuery> = QueryVariablesOption<Q> & {
* @default 15000 * @default 15000
*/ */
timeout?: number; timeout?: number;
/**
* Abort signal
*/
signal?: AbortSignal;
}; };
export type QueryOptions<Q extends GraphQLQuery> = RequestOptions<Q> & { export type QueryOptions<Q extends GraphQLQuery> = RequestOptions<Q> & {
@@ -207,6 +211,7 @@ export const gqlFetcherFactory = (
headers, headers,
body: isFormData ? body : JSON.stringify(body), body: isFormData ? body : JSON.stringify(body),
timeout: options.timeout, timeout: options.timeout,
signal: options.signal,
}) })
).then(async res => { ).then(async res => {
if (res.headers.get('content-type')?.startsWith('application/json')) { if (res.headers.get('content-type')?.startsWith('application/json')) {
@@ -165,7 +165,8 @@ export class CopilotClient {
docId?: string, docId?: string,
options?: RequestOptions< options?: RequestOptions<
typeof getCopilotSessionsQuery typeof getCopilotSessionsQuery
>['variables']['options'] >['variables']['options'],
signal?: AbortSignal
) { ) {
try { try {
const res = await this.gql({ const res = await this.gql({
@@ -176,6 +177,7 @@ export class CopilotClient {
docId, docId,
options, options,
}, },
signal,
}); });
return res.currentUser?.copilot?.chats.edges.map(e => e.node); return res.currentUser?.copilot?.chats.edges.map(e => e.node);
} catch (err) { } catch (err) {
@@ -98,7 +98,7 @@ const AIChatButton = () => {
return ( return (
<MenuLinkItem icon={<AiOutlineIcon />} active={aiChatActive} to={'/chat'}> <MenuLinkItem icon={<AiOutlineIcon />} active={aiChatActive} to={'/chat'}>
<span data-testid="ai-chat">AFFiNE Intelligence</span> <span data-testid="ai-chat">Intelligence</span>
</MenuLinkItem> </MenuLinkItem>
); );
}; };
@@ -260,6 +260,38 @@ export const Component = () => {
status, status,
]); ]);
// restore pinned session
useEffect(() => {
if (!chatContent) return;
const controller = new AbortController();
const signal = controller.signal;
client
.getSessions(
workspaceId,
{},
undefined,
{ pinned: true, limit: 1 },
signal
)
.then(sessions => {
if (!Array.isArray(sessions)) return;
const session = sessions[0];
if (!session) return;
setCurrentSession(session);
if (chatContent) {
chatContent.session = session;
chatContent.reloadSession();
}
})
.catch(console.error);
// abort the request
return () => {
controller.abort();
};
}, [chatContent, client, workspaceId]);
const onChatContainerRef = useCallback((node: HTMLDivElement) => { const onChatContainerRef = useCallback((node: HTMLDivElement) => {
if (node) { if (node) {
setIsBodyProvided(true); setIsBodyProvided(true);
@@ -285,7 +317,7 @@ export const Component = () => {
return ( return (
<> <>
<ViewTitle title="AFFiNE Intelligence" /> <ViewTitle title="Intelligence" />
<ViewIcon icon="ai" /> <ViewIcon icon="ai" />
<ViewHeader> <ViewHeader>
<div className={styles.chatHeader}> <div className={styles.chatHeader}>