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

View File

@@ -82,6 +82,10 @@ export type RequestOptions<Q extends GraphQLQuery> = QueryVariablesOption<Q> & {
* @default 15000
*/
timeout?: number;
/**
* Abort signal
*/
signal?: AbortSignal;
};
export type QueryOptions<Q extends GraphQLQuery> = RequestOptions<Q> & {
@@ -207,6 +211,7 @@ export const gqlFetcherFactory = (
headers,
body: isFormData ? body : JSON.stringify(body),
timeout: options.timeout,
signal: options.signal,
})
).then(async res => {
if (res.headers.get('content-type')?.startsWith('application/json')) {

View File

@@ -165,7 +165,8 @@ export class CopilotClient {
docId?: string,
options?: RequestOptions<
typeof getCopilotSessionsQuery
>['variables']['options']
>['variables']['options'],
signal?: AbortSignal
) {
try {
const res = await this.gql({
@@ -176,6 +177,7 @@ export class CopilotClient {
docId,
options,
},
signal,
});
return res.currentUser?.copilot?.chats.edges.map(e => e.node);
} catch (err) {

View File

@@ -98,7 +98,7 @@ const AIChatButton = () => {
return (
<MenuLinkItem icon={<AiOutlineIcon />} active={aiChatActive} to={'/chat'}>
<span data-testid="ai-chat">AFFiNE Intelligence</span>
<span data-testid="ai-chat">Intelligence</span>
</MenuLinkItem>
);
};

View File

@@ -260,6 +260,38 @@ export const Component = () => {
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) => {
if (node) {
setIsBodyProvided(true);
@@ -285,7 +317,7 @@ export const Component = () => {
return (
<>
<ViewTitle title="AFFiNE Intelligence" />
<ViewTitle title="Intelligence" />
<ViewIcon icon="ai" />
<ViewHeader>
<div className={styles.chatHeader}>