Skip to content

Commit 9ed82fd

Browse files
fix(mobile): keep PR stack loading layout stable
1 parent b295f23 commit 9ed82fd

4 files changed

Lines changed: 38 additions & 6 deletions

File tree

‎apps/mobile/src/features/pull-requests/PullRequestMergeControls.tsx‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export function PullRequestMergeControls(props: {
5454
hasStack: stack.stack !== null,
5555
isFresh: stack.isFresh,
5656
});
57+
const checkingStack = stack.supportsStackActions && !stack.isFresh && !stack.error;
5758
const reason =
5859
mergeUnavailableReason(pr, permissions.canWrite) ??
5960
(stack.stack
@@ -167,12 +168,12 @@ export function PullRequestMergeControls(props: {
167168
accessibilityLabel={
168169
scope ? `${label}, ${scope.layers.length} stack layers through #${pr.number}` : label
169170
}
170-
accessibilityState={{ disabled: !canMerge }}
171+
accessibilityState={{ disabled: !canMerge, busy: busy || checkingStack }}
171172
disabled={!canMerge}
172173
onPress={() => confirm("merge")}
173174
className="min-h-11 min-w-0 flex-1 flex-row items-center justify-center gap-2 px-3 py-2 active:opacity-70"
174175
>
175-
{busy ? (
176+
{busy || checkingStack ? (
176177
<ActivityIndicator size="small" colorClassName="accent-icon-muted" />
177178
) : (
178179
<SymbolView
@@ -229,7 +230,10 @@ export function PullRequestMergeControls(props: {
229230
</ControlPillMenu>
230231
) : null}
231232
</View>
232-
{reason && reason !== MERGE_CONFLICT_REASON ? (
233+
{reason &&
234+
reason !== MERGE_CONFLICT_REASON &&
235+
reason !== "Checking stack membership…" &&
236+
!(checkingStack && reason === "Refresh the stack before merging.") ? (
233237
<Text className="px-1 text-xs text-foreground-muted">{reason}</Text>
234238
) : null}
235239
{pr.autoMergeEnabled ? (

‎apps/mobile/src/features/pull-requests/PullRequestOverviewLoading.tsx‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@ import type { PullRequestListEntry } from "@t3tools/contracts";
22
import { View } from "react-native";
33
import { AppText as Text } from "../../components/AppText";
44
import { PullRequestCardGroup, PullRequestCardRow } from "./PullRequestControls";
5+
import { PullRequestStackCard } from "./PullRequestStackCard";
6+
import type { PullRequestParams } from "./usePullRequestDiff";
7+
import type { PullRequestStackState } from "./usePullRequestStack";
58
import { pullRequestListReviewStatus } from "./pullRequestList";
69

710
export function PullRequestOverviewLoading({
811
summary,
12+
params,
13+
stack,
914
}: {
1015
readonly summary: PullRequestListEntry;
16+
readonly params: PullRequestParams;
17+
readonly stack: PullRequestStackState;
1118
}) {
1219
const review = pullRequestListReviewStatus(summary);
1320
const conflicting = summary.mergeability === "conflicting";
@@ -18,6 +25,7 @@ export function PullRequestOverviewLoading({
1825
accessibilityLabel="Loading pull request details"
1926
accessibilityState={{ busy: true }}
2027
>
28+
<PullRequestStackCard params={params} state={stack} />
2129
<PullRequestCardGroup>
2230
<PullRequestCardRow
2331
compact

‎apps/mobile/src/features/pull-requests/PullRequestRouteScreen.tsx‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,11 @@ export function PullRequestRouteScreen({ route }: StaticScreenProps<PullRequestP
504504
}}
505505
/>
506506
) : summary ? (
507-
<PullRequestOverviewLoading summary={summary} />
507+
<PullRequestOverviewLoading
508+
summary={summary}
509+
params={params}
510+
stack={stack}
511+
/>
508512
) : null}
509513
<View
510514
className="mt-8 border-t border-border-subtle pt-3"

‎apps/mobile/src/features/pull-requests/PullRequestStackCard.tsx‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,31 @@ export function PullRequestStackCard(props: {
1414
const navigation = useNavigation();
1515
const [expanded, setExpanded] = useState(false);
1616
const stack = props.state.stack;
17-
if (!stack) return null;
17+
if (!stack) {
18+
const summary =
19+
props.params.initialSummary?.number === props.params.number
20+
? props.params.initialSummary.stack
21+
: undefined;
22+
if (!summary) return null;
23+
return (
24+
<PullRequestCardGroup>
25+
<PullRequestCardRow
26+
title="Stack"
27+
icon="square.3.layers.3d"
28+
value={`${summary.position} of ${summary.size}`}
29+
last
30+
/>
31+
</PullRequestCardGroup>
32+
);
33+
}
1834
const position = stack.layers.findIndex((layer) => layer.number === props.params.number) + 1;
1935
return (
2036
<PullRequestCardGroup>
2137
<PullRequestCardRow
2238
title="Stack"
2339
icon="square.3.layers.3d"
2440
value={`${position} of ${stack.layers.length}`}
25-
detail={!props.state.isFresh ? "Showing saved stack · refresh to merge" : undefined}
41+
accessibilityLabel={`Stack, ${position} of ${stack.layers.length}${props.state.isFresh ? "" : ", showing saved stack"}`}
2642
expanded={expanded}
2743
onPress={() => setExpanded(!expanded)}
2844
last={!expanded}

0 commit comments

Comments
 (0)