History

Optimize provider update pill renders

Cursor Agent committed 4 months ago

Commit f34cfbb1 parent 0c665651 file · +78 −55Browse files

Unified · Split

apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx+78−55
@@ -28,62 +28,19 @@ const PROVIDER_UPDATE_PILL_PROGRESS_STYLES = { · 27 unmodified lines
2828 error: "bg-destructive/14",
2929 } as const;
3030
31−function latestProviderCheckedAt(
32− providers: ReadonlyArray<Pick<ServerProvider, "checkedAt">>,
33−): string | undefined {
34− return providers.reduce<string | undefined>(
35− (latest, provider) =>
36− latest === undefined || provider.checkedAt > latest ? provider.checkedAt : latest,
37− undefined,
38− );
31+function useMountedIsoTimestamp(): string {
32+ const [mountedIsoTimestamp] = useState(() => new Date().toISOString());
33+ return mountedIsoTimestamp;
3934 }
4035
41−export function SidebarProviderUpdatePill() {
42− const navigate = useNavigate();
43− const providers = useAtomValue(primaryServerProvidersAtom);
44− const [dismissedKeys, setDismissedKeys] = useState<ReadonlySet<string>>(() => new Set());
45− const [renderedView, setRenderedView] = useState<ProviderUpdateSidebarPillView | null>(null);
46− const [pendingView, setPendingView] = useState<ProviderUpdateSidebarPillView | null>(null);
47− const [exitingKey, setExitingKey] = useState<string | null>(null);
48− const [dismissAfterExitKey, setDismissAfterExitKey] = useState<string | null>(null);
49− const [visibleAfterIso, setVisibleAfterIso] = useState<string | undefined>();
50− const effectiveVisibleAfterIso = visibleAfterIso ?? latestProviderCheckedAt(providers);
51− const view = getProviderUpdateSidebarPillView(providers, {
52− ...(effectiveVisibleAfterIso !== undefined
53− ? { visibleAfterIso: effectiveVisibleAfterIso }
54− : {}),
55− dismissedKeys,
56− });
57−
58− useEffect(() => {
59− if (visibleAfterIso === undefined && effectiveVisibleAfterIso !== undefined) {
60− setVisibleAfterIso(effectiveVisibleAfterIso);
61− }
62− }, [effectiveVisibleAfterIso, visibleAfterIso]);
63−
64− const openProviderSettings = useCallback(() => {
65− void navigate({ to: "/settings/providers" });
66− }, [navigate]);
67− const displayedView = renderedView ?? view;
68− const dismissAfterVisibleMs = displayedView?.dismissAfterVisibleMs;
69− const viewKey = displayedView?.key ?? null;
70− const showDismissProgress =
71− dismissAfterVisibleMs !== undefined &&
72− displayedView?.tone !== "loading" &&
73− exitingKey !== viewKey;
74−
75− const startExit = useCallback(
76− (key: string, nextView: ProviderUpdateSidebarPillView | null, dismissKey?: string) => {
77− if (exitingKey === key) {
78− return;
79− }
80− setPendingView(nextView);
81− setExitingKey(key);
82− setDismissAfterExitKey(dismissKey ?? null);
83− },
84− [exitingKey],
85− );
86−
36+function useProviderUpdateRenderedViewSynchronization(input: {
37+ readonly exitingKey: string | null;
38+ readonly renderedView: ProviderUpdateSidebarPillView | null;
39+ readonly setRenderedView: (view: ProviderUpdateSidebarPillView | null) => void;
40+ readonly startExit: (key: string, nextView: ProviderUpdateSidebarPillView | null) => void;
41+ readonly view: ProviderUpdateSidebarPillView | null;
42+}) {
43+ const { exitingKey, renderedView, setRenderedView, startExit, view } = input;
8744 useEffect(() => {
8845 if (exitingKey !== null) {
8946 return;
@@ -102,8 +59,20 @@ export function SidebarProviderUpdatePill() { · 12 unmodified lines
10259 startExit(renderedView.key, view);
10360 return;
10461 }
105− }, [exitingKey, renderedView, startExit, view]);
62+ }, [exitingKey, renderedView, setRenderedView, startExit, view]);
63+}
10664
65+function useProviderUpdateAutoDismiss(input: {
66+ readonly dismissAfterVisibleMs: number | undefined;
67+ readonly exitingKey: string | null;
68+ readonly startExit: (
69+ key: string,
70+ nextView: ProviderUpdateSidebarPillView | null,
71+ dismissKey?: string,
72+ ) => void;
73+ readonly viewKey: string | null;
74+}) {
75+ const { dismissAfterVisibleMs, exitingKey, startExit, viewKey } = input;
10776 useEffect(() => {
10877 if (!dismissAfterVisibleMs || !viewKey) {
10978 return;
@@ -117,6 +86,60 @@ export function SidebarProviderUpdatePill() { · 7 unmodified lines
11786
11887 return () => window.clearTimeout(timeoutId);
11988 }, [dismissAfterVisibleMs, exitingKey, startExit, viewKey]);
89+}
90+
91+export function SidebarProviderUpdatePill() {
92+ const navigate = useNavigate();
93+ const providers = useAtomValue(primaryServerProvidersAtom);
94+ const [dismissedKeys, setDismissedKeys] = useState<ReadonlySet<string>>(() => new Set());
95+ const visibleAfterIso = useMountedIsoTimestamp();
96+ const view = getProviderUpdateSidebarPillView(providers, {
97+ visibleAfterIso,
98+ dismissedKeys,
99+ });
100+ const [renderedView, setRenderedView] = useState<ProviderUpdateSidebarPillView | null>(
101+ () => view,
102+ );
103+ const [pendingView, setPendingView] = useState<ProviderUpdateSidebarPillView | null>(null);
104+ const [exitingKey, setExitingKey] = useState<string | null>(null);
105+ const [dismissAfterExitKey, setDismissAfterExitKey] = useState<string | null>(null);
106+
107+ const openProviderSettings = useCallback(() => {
108+ void navigate({ to: "/settings/providers" });
109+ }, [navigate]);
110+ const displayedView = renderedView ?? view;
111+ const dismissAfterVisibleMs = displayedView?.dismissAfterVisibleMs;
112+ const viewKey = displayedView?.key ?? null;
113+ const showDismissProgress =
114+ dismissAfterVisibleMs !== undefined &&
115+ displayedView?.tone !== "loading" &&
116+ exitingKey !== viewKey;
117+
118+ const startExit = useCallback(
119+ (key: string, nextView: ProviderUpdateSidebarPillView | null, dismissKey?: string) => {
120+ if (exitingKey === key) {
121+ return;
122+ }
123+ setPendingView(nextView);
124+ setExitingKey(key);
125+ setDismissAfterExitKey(dismissKey ?? null);
126+ },
127+ [exitingKey],
128+ );
129+
130+ useProviderUpdateRenderedViewSynchronization({
131+ exitingKey,
132+ renderedView,
133+ setRenderedView,
134+ startExit,
135+ view,
136+ });
137+ useProviderUpdateAutoDismiss({
138+ dismissAfterVisibleMs,
139+ exitingKey,
140+ startExit,
141+ viewKey,
142+ });
120143
121144 if (!displayedView) {
122145 return null;