mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-09 07:42:39 +02:00
merge: upstream/dev with migration renumbering
This commit is contained in:
commit
a7145b2c63
176 changed files with 8791 additions and 3608 deletions
28
surfsense_web/hooks/use-composio-drive-folders.ts
Normal file
28
surfsense_web/hooks/use-composio-drive-folders.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { useQuery } from "@tanstack/react-query";
|
||||
import { connectorsApiService } from "@/lib/apis/connectors-api.service";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
|
||||
interface UseComposioDriveFoldersOptions {
|
||||
connectorId: number;
|
||||
parentId?: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export function useComposioDriveFolders({
|
||||
connectorId,
|
||||
parentId,
|
||||
enabled = true,
|
||||
}: UseComposioDriveFoldersOptions) {
|
||||
return useQuery({
|
||||
queryKey: cacheKeys.connectors.composioDrive.folders(connectorId, parentId),
|
||||
queryFn: async () => {
|
||||
return connectorsApiService.listComposioDriveFolders({
|
||||
connector_id: connectorId,
|
||||
parent_id: parentId,
|
||||
});
|
||||
},
|
||||
enabled: enabled && !!connectorId,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
retry: 2,
|
||||
});
|
||||
}
|
||||
104
surfsense_web/hooks/use-global-loading.ts
Normal file
104
surfsense_web/hooks/use-global-loading.ts
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
"use client";
|
||||
|
||||
import { useAtom } from "jotai";
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
import { globalLoadingAtom } from "@/atoms/ui/loading.atoms";
|
||||
|
||||
// Global counter to generate unique IDs for each loading request
|
||||
let loadingIdCounter = 0;
|
||||
|
||||
// Track the current active loading ID globally
|
||||
let currentLoadingId: number | null = null;
|
||||
|
||||
// Pending hide timeout - allows new loading requests to take over before hiding
|
||||
let pendingHideTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
/**
|
||||
* Hook to control the global loading screen.
|
||||
* The spinner is always mounted in the DOM to prevent animation reset.
|
||||
*/
|
||||
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 id = ++loadingIdCounter;
|
||||
currentLoadingId = id;
|
||||
setLoading({ isLoading: true, message, variant });
|
||||
return id;
|
||||
},
|
||||
[setLoading]
|
||||
);
|
||||
|
||||
const hide = useCallback(
|
||||
(id?: number) => {
|
||||
// Only hide if this is the current loading, or if no ID provided (force hide)
|
||||
if (id === undefined || id === currentLoadingId) {
|
||||
// Use a small delay to allow React to flush pending mounts
|
||||
// This prevents flash when transitioning between loading states
|
||||
if (pendingHideTimeout) {
|
||||
clearTimeout(pendingHideTimeout);
|
||||
}
|
||||
|
||||
pendingHideTimeout = setTimeout(() => {
|
||||
// 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" });
|
||||
}
|
||||
pendingHideTimeout = null;
|
||||
}, 50); // Small delay to allow next component to mount and show loading
|
||||
}
|
||||
},
|
||||
[setLoading]
|
||||
);
|
||||
|
||||
return { show, hide, isLoading: loading.isLoading };
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook that automatically shows/hides the global loading screen based on a condition.
|
||||
* Useful for components that show loading on mount and hide on unmount.
|
||||
*
|
||||
* Uses ownership tracking to prevent flashes when multiple components
|
||||
* 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"
|
||||
) {
|
||||
const { show, hide } = useGlobalLoading();
|
||||
const loadingIdRef = useRef<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldShow) {
|
||||
// Show loading and store the ID
|
||||
loadingIdRef.current = show(message, variant);
|
||||
} 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]);
|
||||
|
||||
// Cleanup on unmount - only hide if we're still the active loading
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (loadingIdRef.current !== null) {
|
||||
hide(loadingIdRef.current);
|
||||
loadingIdRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [hide]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue