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
28 error: "bg-destructive/14",28 error: "bg-destructive/14",
29} as const;29} as const;
30 30
31function latestProviderCheckedAt(31function useMountedIsoTimestamp(): string {
32 providers: ReadonlyArray<Pick<ServerProvider, "checkedAt">>,32 const [mountedIsoTimestamp] = useState(() => new Date().toISOString());
33): string | undefined {33 return mountedIsoTimestamp;
34 return providers.reduce<string | undefined>(
35 (latest, provider) =>
36 latest === undefined || provider.checkedAt > latest ? provider.checkedAt : latest,
37 undefined,
38 );
39}34}
40 35
41export function SidebarProviderUpdatePill() {36function useProviderUpdateRenderedViewSynchronization(input: {
42 const navigate = useNavigate();37 readonly exitingKey: string | null;
43 const providers = useAtomValue(primaryServerProvidersAtom);38 readonly renderedView: ProviderUpdateSidebarPillView | null;
44 const [dismissedKeys, setDismissedKeys] = useState<ReadonlySet<string>>(() => new Set());39 readonly setRenderedView: (view: ProviderUpdateSidebarPillView | null) => void;
45 const [renderedView, setRenderedView] = useState<ProviderUpdateSidebarPillView | null>(null);40 readonly startExit: (key: string, nextView: ProviderUpdateSidebarPillView | null) => void;
46 const [pendingView, setPendingView] = useState<ProviderUpdateSidebarPillView | null>(null);41 readonly view: ProviderUpdateSidebarPillView | null;
47 const [exitingKey, setExitingKey] = useState<string | null>(null);42}) {
48 const [dismissAfterExitKey, setDismissAfterExitKey] = useState<string | null>(null);43 const { exitingKey, renderedView, setRenderedView, startExit, view } = input;
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
87 useEffect(() => {44 useEffect(() => {
88 if (exitingKey !== null) {45 if (exitingKey !== null) {
89 return;46 return;
@@ -102,8 +59,20 @@ export function SidebarProviderUpdatePill() { · 12 unmodified lines
102 startExit(renderedView.key, view);59 startExit(renderedView.key, view);
103 return;60 return;
104 }61 }
105 }, [exitingKey, renderedView, startExit, view]);62 }, [exitingKey, renderedView, setRenderedView, startExit, view]);
63}
106 64
65function 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;
107 useEffect(() => {76 useEffect(() => {
108 if (!dismissAfterVisibleMs || !viewKey) {77 if (!dismissAfterVisibleMs || !viewKey) {
109 return;78 return;
@@ -117,6 +86,60 @@ export function SidebarProviderUpdatePill() { · 7 unmodified lines
117 86
118 return () => window.clearTimeout(timeoutId);87 return () => window.clearTimeout(timeoutId);
119 }, [dismissAfterVisibleMs, exitingKey, startExit, viewKey]);88 }, [dismissAfterVisibleMs, exitingKey, startExit, viewKey]);
89}
90
91export 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 });
120 143
121 if (!displayedView) {144 if (!displayedView) {
122 return null;145 return null;