Skip to content

Commit 625ffbf

Browse files
refactor(mobile): thread list actions and inspector registration drop finally chains and ref syncs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 28113c2 commit 625ffbf

2 files changed

Lines changed: 33 additions & 39 deletions

File tree

‎apps/mobile/src/features/home/useThreadListActions.ts‎

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ function useThreadActionExecutor(
134134

135135
inFlightThreadKeys.current.add(key);
136136
selectionHaptic();
137-
return await (async () => {
137+
const succeeded = await (async () => {
138138
if (
139139
(action === "settle" || action === "unsettle") &&
140140
!environmentSupportsSettlement(thread.environmentId)
@@ -185,9 +185,9 @@ function useThreadActionExecutor(
185185
}
186186
onCompleted?.(action, thread);
187187
return true;
188-
})().finally(() => {
189-
inFlightThreadKeys.current.delete(key);
190-
});
188+
})();
189+
inFlightThreadKeys.current.delete(key);
190+
return succeeded;
191191
};
192192

193193
return executeAction;
@@ -258,7 +258,7 @@ export function useThreadListActions(): {
258258
return false;
259259
}
260260
snoozeInFlightThreadKeys.current.add(key);
261-
return await (async () => {
261+
const succeeded = await (async () => {
262262
if (!environmentSupportsSnooze(thread.environmentId)) {
263263
Dialog.alert(
264264
"Could not snooze thread",
@@ -302,9 +302,9 @@ export function useThreadListActions(): {
302302
return false;
303303
}
304304
return true;
305-
})().finally(() => {
306-
snoozeInFlightThreadKeys.current.delete(key);
307-
});
305+
})();
306+
snoozeInFlightThreadKeys.current.delete(key);
307+
return succeeded;
308308
};
309309
const unsnoozeThread = async (thread: EnvironmentThreadShell) => {
310310
if (!checkThreadOperationPermission(thread, "Could not wake thread")) return false;
@@ -313,7 +313,7 @@ export function useThreadListActions(): {
313313
return false;
314314
}
315315
snoozeInFlightThreadKeys.current.add(key);
316-
return await (async () => {
316+
const succeeded = await (async () => {
317317
if (!environmentSupportsSnooze(thread.environmentId)) {
318318
Dialog.alert(
319319
"Could not wake thread",
@@ -343,9 +343,9 @@ export function useThreadListActions(): {
343343
return false;
344344
}
345345
return true;
346-
})().finally(() => {
347-
snoozeInFlightThreadKeys.current.delete(key);
348-
});
346+
})();
347+
snoozeInFlightThreadKeys.current.delete(key);
348+
return succeeded;
349349
};
350350
const unsettleThread = async (thread: EnvironmentThreadShell) =>
351351
(await executeAction("unsettle", thread)) === true;
@@ -454,7 +454,7 @@ export function useThreadListActions(): {
454454

455455
titleRegenerationInFlightThreadKeys.current.add(key);
456456
selectionHaptic();
457-
return await (async () => {
457+
const succeeded = await (async () => {
458458
const result = await updateThreadMetadata({
459459
environmentId: thread.environmentId,
460460
input: { threadId: thread.id, regenerateTitle: true },
@@ -470,9 +470,9 @@ export function useThreadListActions(): {
470470
return false;
471471
}
472472
return true;
473-
})().finally(() => {
474-
titleRegenerationInFlightThreadKeys.current.delete(key);
475-
});
473+
})();
474+
titleRegenerationInFlightThreadKeys.current.delete(key);
475+
return succeeded;
476476
};
477477
const renameThread = (thread: EnvironmentThreadShell) => {
478478
const commit = (title: string) => {
@@ -531,11 +531,9 @@ export function useThreadListActions(): {
531531
if (section === "settled") {
532532
if (!environmentSupportsSettlement(thread.environmentId)) return false;
533533
appAtomRegistry.set(threadDropBusyAtom, true);
534-
return await (async () => {
535-
return await settleThread(thread);
536-
})().finally(() => {
537-
appAtomRegistry.set(threadDropBusyAtom, false);
538-
});
534+
const settled = await settleThread(thread);
535+
appAtomRegistry.set(threadDropBusyAtom, false);
536+
return settled;
539537
}
540538
const configs = appAtomRegistry.get(environmentServerConfigsAtom);
541539
const supportsReorder = (environmentId: EnvironmentThreadShell["environmentId"]) => {
@@ -608,9 +606,8 @@ export function useThreadListActions(): {
608606
assignments,
609607
}),
610608
);
611-
let succeeded = false;
612609
const reorder = section === "pinned" ? reorderPinnedMutation : reorderActiveMutation;
613-
return await (async () => {
610+
const moved = await (async () => {
614611
if (crossSection) {
615612
if (section === "pinned") {
616613
const orderKey = assignments.find(
@@ -657,13 +654,12 @@ export function useThreadListActions(): {
657654
return false;
658655
}
659656
}
660-
succeeded = true;
661657
pending?.complete();
662658
return true;
663-
})().finally(() => {
664-
if (!succeeded) pending?.cancel();
665-
appAtomRegistry.set(threadDropBusyAtom, false);
666-
});
659+
})();
660+
if (!moved) pending?.cancel();
661+
appAtomRegistry.set(threadDropBusyAtom, false);
662+
return moved;
667663
};
668664

669665
const confirmDeleteThread = useConfirmDeleteThread(executeAction);

‎apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx‎

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
createContext,
1717
use,
1818
useEffect,
19-
useLayoutEffect,
19+
useEffectEvent,
2020
useRef,
2121
useState,
2222
type ReactNode,
@@ -154,17 +154,18 @@ export function useRegisterWorkspaceInspector(render: (() => ReactNode) | undefi
154154
);
155155
})();
156156

157-
const wrappedRenderRef = useRef(wrappedRender);
158157
const focusedRef = useRef(false);
159158
const deactivateRef = useRef<(() => void) | null>(null);
160159

161-
const syncRegistration = () => {
162-
if (!focusedRef.current || wrappedRenderRef.current === undefined) {
160+
// An effect event reads this render's pane without making the focus
161+
// subscription re-run (and deactivate) every time the pane closure changes.
162+
const syncRegistration = useEffectEvent(() => {
163+
if (!focusedRef.current || wrappedRender === undefined) {
163164
deactivateRef.current?.();
164165
return;
165166
}
166-
deactivateRef.current = registerWorkspaceInspector(wrappedRenderRef.current);
167-
};
167+
deactivateRef.current = registerWorkspaceInspector(wrappedRender);
168+
});
168169

169170
useFocusEffect(() => {
170171
focusedRef.current = true;
@@ -175,14 +176,11 @@ export function useRegisterWorkspaceInspector(render: (() => ReactNode) | undefi
175176
};
176177
});
177178

178-
// A layout effect runs before the focus effect, so the ref already holds this
179-
// render's pane when focus registers it.
180-
useLayoutEffect(() => {
181-
wrappedRenderRef.current = wrappedRender;
179+
useEffect(() => {
182180
if (focusedRef.current) {
183181
syncRegistration();
184182
}
185-
}, [syncRegistration, wrappedRender]);
183+
}, [wrappedRender]);
186184

187185
useEffect(
188186
() => () => {

0 commit comments

Comments
 (0)