authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-08-31 11:44:56-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-31 11:44:56-07:00
log5ce92c2f192040bf77c0211fa33bf03c74c031ef
treeb87db9b1648398d2c60adb4bac5584dc8c511f61
parent35da5813315dc4e0c20602ed1918ceccc916b7eb
signature Signed by PGP key B5690EEEBB952194

fix(mobile): shimmer active tool rows (#8932)

Co-authored-by: Julius Marminge <julius@mac.lan>

3 files changed, 25 insertions(+), 7 deletions(-)

apps/mobile/src/features/threads/thread-work-log.tsx+3-2
......@@ -9,6 +9,7 @@ import {
99 type ColorValue,
1010 Pressable,
1111 ScrollView,
12 StyleSheet,
1213 View,
1314} from "react-native";
1415import Svg, { Defs, LinearGradient, Rect, Stop } from "react-native-svg";
......@@ -143,7 +144,7 @@ function ShimmeringWorkContent(props: {
143144
144145 return (
145146 <View
146 className="min-w-0 flex-1"
147 className="min-w-0 flex-1 overflow-hidden"
147148 onLayout={(event) => setAvailableWidth(event.nativeEvent.layout.width)}
148149 >
149150 <ShimmerWorkContent
......@@ -164,7 +165,7 @@ function ShimmeringWorkContent(props: {
164165 style={[{ width: SHIMMER_WIDTH }, sweepStyle]}
165166 >
166167 <MaskedView
167 className="absolute inset-0"
168 style={StyleSheet.absoluteFill}
168169 maskElement={
169170 <Svg width="100%" height="100%">
170171 <Defs>
apps/mobile/src/lib/threadActivity.test.ts+20-1
......@@ -942,8 +942,27 @@ describe("buildThreadFeed", () => {
942942 summary: "Running pnpm",
943943 summaryKind: "command",
944944 live: true,
945 shimmer: false,
945 shimmer: true,
946946 });
947 expect(rows[0]).toMatchObject({ live: false, shimmer: false });
948
949 const stoppedRows = deriveThreadFeedPresentation(feed, latestTurn, new Set());
950 expect(stoppedRows.filter((entry) => entry.type === "work-toggle")).toMatchObject([
951 { live: false, shimmer: false },
952 { live: false, shimmer: false },
953 ]);
954
955 const completedRows = deriveThreadFeedPresentation(
956 feed,
957 { ...latestTurn, state: "completed", completedAt: "2026-04-01T00:00:04.000Z" },
958 new Set([turnId]),
959 new Set(),
960 latestTurn.startedAt,
961 );
962 expect(completedRows.filter((entry) => entry.type === "work-toggle")).toMatchObject([
963 { live: false, shimmer: false },
964 { live: false, shimmer: false },
965 ]);
947966 });
948967
949968 it("does not revive cached in-progress tools after work stops", () => {
apps/mobile/src/lib/threadActivity.ts+2-4
......@@ -1512,10 +1512,8 @@ function appendToolGroupRows(
15121512 ),
15131513 hasFailure: activities.findLast((activity) => activity.toolLike)?.status === "failure",
15141514 live,
1515 shimmer:
1516 isWorking &&
1517 latestActivity.lifecycleStatus === "inProgress" &&
1518 latestActivity.turnId === unsettledTurnId,
1515 // Match the live label until the turn or contiguous tool run settles.
1516 shimmer: live,
15191517 });
15201518 if (!expanded) {
15211519 return;