Files
2026-08-11 11:52:34 +01:00

155 lines
5.1 KiB
TypeScript

"use client";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import type { PresetOption } from "./search-bar";
import type { SidebarSelection, SidebarSelectionRequest } from "./presets-sidebar";
import {
findDefaultSavedPreset,
resolveDefaultSidebarTarget,
type SavedPreset,
} from "./saved-preset-model";
type InitialSidebarSelectionOptions = {
workspaceId: string | null;
resolvedPrPresets: PresetOption[];
shouldAutoResetSearch: () => boolean;
resetSearchOnWorkspaceChange: () => void;
setQueryImmediate: (query: string) => void;
setRepoFilter: (repo: string) => void;
savedPresets?: SavedPreset[];
};
type AppliedSidebarTarget = ReturnType<typeof resolveDefaultSidebarTarget> & {
workspaceId: string | null;
};
function sameAppliedSidebarTarget(
current: AppliedSidebarTarget | null,
next: AppliedSidebarTarget,
) {
return (
current !== null &&
current.workspaceId === next.workspaceId &&
current.selection.kind === next.selection.kind &&
current.selection.source === next.selection.source &&
current.selection.id === next.selection.id &&
current.query === next.query &&
current.repoFilter === next.repoFilter
);
}
export function useInitialSidebarSelection({
workspaceId,
resolvedPrPresets,
shouldAutoResetSearch,
resetSearchOnWorkspaceChange,
setQueryImmediate,
setRepoFilter,
savedPresets = [],
}: InitialSidebarSelectionOptions) {
const userSelectedRef = useRef(false);
const resetWorkspaceIdRef = useRef<string | null | undefined>(undefined);
const lastAppliedTargetRef = useRef<AppliedSidebarTarget | null>(null);
const savedPrDefault = useMemo(() => findDefaultSavedPreset(savedPresets, "pr"), [savedPresets]);
const resolvedPrTarget = useMemo(
() =>
resolveDefaultSidebarTarget("pr", savedPrDefault ? [savedPrDefault] : [], resolvedPrPresets),
[savedPrDefault, resolvedPrPresets],
);
const [selection, setSelection] = useState<SidebarSelection>(() => resolvedPrTarget.selection);
useEffect(() => {
if (resetWorkspaceIdRef.current !== workspaceId) {
resetWorkspaceIdRef.current = workspaceId;
userSelectedRef.current = false;
resetSearchOnWorkspaceChange();
}
if (userSelectedRef.current || !shouldAutoResetSearch()) return;
const target = resolvedPrTarget;
const appliedTarget = { workspaceId, ...target };
if (sameAppliedSidebarTarget(lastAppliedTargetRef.current, appliedTarget)) return;
lastAppliedTargetRef.current = appliedTarget;
setSelection((current) =>
current.kind === target.selection.kind &&
current.source === target.selection.source &&
current.id === target.selection.id
? current
: target.selection,
);
setQueryImmediate(target.query);
setRepoFilter(target.repoFilter);
}, [
workspaceId,
resolvedPrTarget,
setQueryImmediate,
setRepoFilter,
resetSearchOnWorkspaceChange,
shouldAutoResetSearch,
]);
const setUserSelection = useCallback((next: SidebarSelection) => {
userSelectedRef.current = true;
setSelection(next);
}, []);
return { selection, setProgrammaticSelection: setSelection, setUserSelection };
}
export function useSidebarSelectionHandler({
savedPresets,
resolvedPrPresets,
resolvedIssuePresets,
setQueryImmediate,
setRepoFilter,
setUserSelection,
markSearchInteracted,
currentKind,
}: {
savedPresets: SavedPreset[];
resolvedPrPresets: PresetOption[];
resolvedIssuePresets: PresetOption[];
setQueryImmediate: (query: string) => void;
setRepoFilter: (repo: string) => void;
setUserSelection: (next: SidebarSelection) => void;
markSearchInteracted: () => void;
currentKind: SidebarSelection["kind"];
}) {
const savedPresetsRef = useRef(savedPresets);
savedPresetsRef.current = savedPresets;
const resolvedPresetsRef = useRef({ pr: resolvedPrPresets, issue: resolvedIssuePresets });
resolvedPresetsRef.current = { pr: resolvedPrPresets, issue: resolvedIssuePresets };
const currentKindRef = useRef(currentKind);
currentKindRef.current = currentKind;
return useCallback(
(selection: SidebarSelectionRequest) => {
if (selection.source === "kind-switch") {
if (selection.kind === currentKindRef.current) return;
markSearchInteracted();
const target = resolveDefaultSidebarTarget(
selection.kind,
savedPresetsRef.current,
resolvedPresetsRef.current[selection.kind],
);
setUserSelection(target.selection);
setQueryImmediate(target.query);
setRepoFilter(target.repoFilter);
return;
}
markSearchInteracted();
setUserSelection(selection);
if (selection.source === "saved") {
const found = savedPresetsRef.current.find((preset) => preset.id === selection.id);
setQueryImmediate(found?.customQuery ?? "");
setRepoFilter(found?.repoFilter ?? "");
return;
}
const preset = resolvedPresetsRef.current[selection.kind].find(
(candidate) => candidate.value === selection.id,
);
setQueryImmediate(preset?.filter ?? "");
setRepoFilter("");
},
[setQueryImmediate, setUserSelection, markSearchInteracted, setRepoFilter],
);
}