mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-10 16:22:38 +02:00
Merge remote-tracking branch 'upstream/dev' into feat/inbox
This commit is contained in:
commit
614761bb17
64 changed files with 2604 additions and 730 deletions
|
|
@ -25,6 +25,10 @@ export const useGithubStars = () => {
|
|||
|
||||
setStars(data?.stargazers_count);
|
||||
} catch (err) {
|
||||
// Ignore abort errors (expected on unmount)
|
||||
if (err instanceof Error && err.name === "AbortError") {
|
||||
return;
|
||||
}
|
||||
if (err instanceof Error) {
|
||||
console.error("Error fetching stars:", err);
|
||||
setError(err.message);
|
||||
|
|
@ -37,7 +41,7 @@ export const useGithubStars = () => {
|
|||
getStars();
|
||||
|
||||
return () => {
|
||||
abortController.abort();
|
||||
abortController.abort("Component unmounted");
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,21 +20,18 @@ let pendingHideTimeout: ReturnType<typeof setTimeout> | null = null;
|
|||
export function useGlobalLoading() {
|
||||
const [loading, setLoading] = useAtom(globalLoadingAtom);
|
||||
|
||||
const show = useCallback(
|
||||
(message?: string, variant: "login" | "default" = "default") => {
|
||||
// Cancel any pending hide - new loading request takes over
|
||||
if (pendingHideTimeout) {
|
||||
clearTimeout(pendingHideTimeout);
|
||||
pendingHideTimeout = null;
|
||||
}
|
||||
const show = useCallback(() => {
|
||||
// Cancel any pending hide - new loading request takes over
|
||||
if (pendingHideTimeout) {
|
||||
clearTimeout(pendingHideTimeout);
|
||||
pendingHideTimeout = null;
|
||||
}
|
||||
|
||||
const id = ++loadingIdCounter;
|
||||
currentLoadingId = id;
|
||||
setLoading({ isLoading: true, message, variant });
|
||||
return id;
|
||||
},
|
||||
[setLoading]
|
||||
);
|
||||
const id = ++loadingIdCounter;
|
||||
currentLoadingId = id;
|
||||
setLoading({ isLoading: true });
|
||||
return id;
|
||||
}, [setLoading]);
|
||||
|
||||
const hide = useCallback(
|
||||
(id?: number) => {
|
||||
|
|
@ -50,7 +47,7 @@ export function useGlobalLoading() {
|
|||
// Double-check we're still the current loading after the delay
|
||||
if (id === undefined || id === currentLoadingId) {
|
||||
currentLoadingId = null;
|
||||
setLoading({ isLoading: false, message: undefined, variant: "default" });
|
||||
setLoading({ isLoading: false });
|
||||
}
|
||||
pendingHideTimeout = null;
|
||||
}, 50); // Small delay to allow next component to mount and show loading
|
||||
|
|
@ -70,27 +67,21 @@ export function useGlobalLoading() {
|
|||
* transition loading states (e.g., layout → page).
|
||||
*
|
||||
* @param shouldShow - Whether the loading screen should be visible
|
||||
* @param message - Optional message to display
|
||||
* @param variant - Visual style variant ("login" or "default")
|
||||
*/
|
||||
export function useGlobalLoadingEffect(
|
||||
shouldShow: boolean,
|
||||
message?: string,
|
||||
variant: "login" | "default" = "default"
|
||||
) {
|
||||
export function useGlobalLoadingEffect(shouldShow: boolean) {
|
||||
const { show, hide } = useGlobalLoading();
|
||||
const loadingIdRef = useRef<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldShow) {
|
||||
// Show loading and store the ID
|
||||
loadingIdRef.current = show(message, variant);
|
||||
loadingIdRef.current = show();
|
||||
} else if (loadingIdRef.current !== null) {
|
||||
// Only hide if we were the ones showing loading
|
||||
hide(loadingIdRef.current);
|
||||
loadingIdRef.current = null;
|
||||
}
|
||||
}, [shouldShow, message, variant, show, hide]);
|
||||
}, [shouldShow, show, hide]);
|
||||
|
||||
// Cleanup on unmount - only hide if we're still the active loading
|
||||
useEffect(() => {
|
||||
|
|
|
|||
51
surfsense_web/hooks/use-public-chat-runtime.ts
Normal file
51
surfsense_web/hooks/use-public-chat-runtime.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
"use client";
|
||||
|
||||
import { type AppendMessage, useExternalStoreRuntime } from "@assistant-ui/react";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import type { GetPublicChatResponse, PublicChatMessage } from "@/contracts/types/public-chat.types";
|
||||
import { convertToThreadMessage } from "@/lib/chat/message-utils";
|
||||
import type { MessageRecord } from "@/lib/chat/thread-persistence";
|
||||
|
||||
interface UsePublicChatRuntimeOptions {
|
||||
data: GetPublicChatResponse | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map PublicChatMessage to MessageRecord shape for reuse of convertToThreadMessage
|
||||
*/
|
||||
function toMessageRecord(msg: PublicChatMessage, idx: number): MessageRecord {
|
||||
return {
|
||||
id: idx,
|
||||
thread_id: 0,
|
||||
role: msg.role as "user" | "assistant" | "system",
|
||||
content: msg.content,
|
||||
created_at: msg.created_at,
|
||||
author_id: msg.author ? "public" : null,
|
||||
author_display_name: msg.author?.display_name ?? null,
|
||||
author_avatar_url: msg.author?.avatar_url ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a read-only runtime for public chat viewing.
|
||||
*/
|
||||
export function usePublicChatRuntime({ data }: UsePublicChatRuntimeOptions) {
|
||||
const messages = useMemo(() => data?.messages ?? [], [data?.messages]);
|
||||
|
||||
// No-op - public chat is read-only
|
||||
const onNew = useCallback(async (_message: AppendMessage) => {}, []);
|
||||
|
||||
const convertMessage = useCallback(
|
||||
(msg: PublicChatMessage, idx: number) => convertToThreadMessage(toMessageRecord(msg, idx)),
|
||||
[]
|
||||
);
|
||||
|
||||
const runtime = useExternalStoreRuntime({
|
||||
isRunning: false,
|
||||
messages,
|
||||
onNew,
|
||||
convertMessage,
|
||||
});
|
||||
|
||||
return runtime;
|
||||
}
|
||||
14
surfsense_web/hooks/use-public-chat.ts
Normal file
14
surfsense_web/hooks/use-public-chat.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { useQuery } from "@tanstack/react-query";
|
||||
import type { GetPublicChatResponse } from "@/contracts/types/public-chat.types";
|
||||
import { publicChatApiService } from "@/lib/apis/public-chat-api.service";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
|
||||
export function usePublicChat(shareToken: string) {
|
||||
return useQuery<GetPublicChatResponse, Error>({
|
||||
queryKey: cacheKeys.publicChat.byToken(shareToken),
|
||||
queryFn: () => publicChatApiService.getPublicChat({ share_token: shareToken }),
|
||||
enabled: !!shareToken,
|
||||
staleTime: 30_000,
|
||||
retry: false,
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue