Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions apps/mobile/src/features/home/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
import {
ThreadListV2PendingRow,
ThreadListV2Row,
ThreadListV2SettledShelfHeader,
ThreadListV2SnoozedShelfHeader,
} from "../threads/thread-list-v2-items";
import {
Expand Down Expand Up @@ -534,6 +535,8 @@ export function HomeScreen(props: HomeScreenProps) {
);
const [snoozedShelfExpanded, setSnoozedShelfExpanded] = useState(false);
const toggleSnoozedShelf = useCallback(() => setSnoozedShelfExpanded((value) => !value), []);
const [settledShelfExpanded, setSettledShelfExpanded] = useState(true);
const toggleSettledShelf = useCallback(() => setSettledShelfExpanded((value) => !value), []);
// now is quantized to the minute and ticks so the inactivity auto-settle
// boundary is actually crossed while the app stays open (mirrors web);
// without a clock dependency the partition memoizes a frozen "now".
Expand Down Expand Up @@ -579,6 +582,8 @@ export function HomeScreen(props: HomeScreenProps) {
hiddenSettledCount: 0,
snoozedCount: 0,
snoozedShelfHeaderIndex: null,
settledCount: 0,
settledShelfHeaderIndex: null,
nextSnoozeWakeAt: null,
};
// Settled threads are live shells; archived threads keep their original
Expand All @@ -596,13 +601,15 @@ export function HomeScreen(props: HomeScreenProps) {
now: `${nowMinute}:00.000Z`,
snoozeNow: new Date().toISOString(),
snoozedShelfExpanded,
settledShelfExpanded,
selectedThreadKey: null,
});
}, [
changeRequestStateByKey,
nowMinute,
snoozeWakeTick,
snoozedShelfExpanded,
settledShelfExpanded,
settledVisibleCount,
settlementEnvironmentIds,
snoozeEnvironmentIds,
Expand Down Expand Up @@ -655,9 +662,12 @@ export function HomeScreen(props: HomeScreenProps) {
snoozedCount: threadListV2Layout.snoozedCount,
snoozedShelfExpanded,
snoozedShelfHeaderIndex: threadListV2Layout.snoozedShelfHeaderIndex,
settledCount: threadListV2Layout.settledCount,
settledShelfExpanded,
settledShelfHeaderIndex: threadListV2Layout.settledShelfHeaderIndex,
snoozeLabelNow: `${nowMinute}:00.000Z`,
}),
[snoozedShelfExpanded, threadListV2Layout, v2PendingTasks],
[settledShelfExpanded, snoozedShelfExpanded, threadListV2Layout, v2PendingTasks],
);

const renderV2Item = useCallback(
Expand Down Expand Up @@ -693,12 +703,20 @@ export function HomeScreen(props: HomeScreenProps) {
/>
);
}
if (item.type === "v2-settled-shelf") {
return (
<ThreadListV2SettledShelfHeader
count={item.count}
expanded={item.expanded}
onToggle={toggleSettledShelf}
/>
);
}
const thread = item.item.thread;
return (
<ThreadListV2Row
thread={thread}
variant={item.item.variant}
showSettledDivider={item.item.showSettledDivider}
snoozed={item.item.snoozed}
snoozePresetMinute={nowMinute}
snoozeWakeLabelText={item.snoozeWakeLabelText}
Expand Down Expand Up @@ -767,6 +785,7 @@ export function HomeScreen(props: HomeScreenProps) {
settlementEnvironmentIds,
snoozeEnvironmentIds,
threadSearchMatchByKey,
toggleSettledShelf,
toggleSnoozedShelf,
v2ProjectTitleByProjectKey,
props.searchQuery,
Expand Down Expand Up @@ -1036,7 +1055,7 @@ export function HomeScreen(props: HomeScreenProps) {
extraData={v2ExtraData}
ListHeaderComponent={v2ListHeader}
ListFooterComponent={
threadListV2Layout.hiddenSettledCount > 0 ? (
settledShelfExpanded && threadListV2Layout.hiddenSettledCount > 0 ? (
<Pressable
accessibilityRole="button"
accessibilityLabel={`Show ${Math.min(threadListV2Layout.hiddenSettledCount, THREAD_LIST_V2_SETTLED_PAGE_COUNT)} more settled threads`}
Expand Down
32 changes: 28 additions & 4 deletions apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import {
import {
ThreadListV2PendingRow,
ThreadListV2Row,
ThreadListV2SettledShelfHeader,
ThreadListV2SnoozedShelfHeader,
} from "./thread-list-v2-items";
import {
Expand Down Expand Up @@ -440,6 +441,8 @@ function ThreadNavigationSidebarPane(
);
const [snoozedShelfExpanded, setSnoozedShelfExpanded] = useState(false);
const toggleSnoozedShelf = useCallback(() => setSnoozedShelfExpanded((value) => !value), []);
const [settledShelfExpanded, setSettledShelfExpanded] = useState(true);
const toggleSettledShelf = useCallback(() => setSettledShelfExpanded((value) => !value), []);
// now ticks per minute so the inactivity auto-settle boundary is actually
// crossed while the pane stays open; without a clock dependency the
// partition memoizes a frozen "now".
Expand Down Expand Up @@ -485,6 +488,8 @@ function ThreadNavigationSidebarPane(
hiddenSettledCount: 0,
snoozedCount: 0,
snoozedShelfHeaderIndex: null,
settledCount: 0,
settledShelfHeaderIndex: null,
nextSnoozeWakeAt: null,
};
return buildThreadListV2Items({
Expand All @@ -500,13 +505,15 @@ function ThreadNavigationSidebarPane(
now: `${nowMinute}:00.000Z`,
snoozeNow: new Date().toISOString(),
snoozedShelfExpanded,
settledShelfExpanded,
selectedThreadKey: props.selectedThreadKey ?? null,
});
}, [
changeRequestStateByKey,
nowMinute,
snoozeWakeTick,
snoozedShelfExpanded,
settledShelfExpanded,
props.selectedThreadKey,
options.selectedEnvironmentId,
props.searchQuery,
Expand Down Expand Up @@ -557,9 +564,12 @@ function ThreadNavigationSidebarPane(
snoozedCount: threadListV2Layout.snoozedCount,
snoozedShelfExpanded,
snoozedShelfHeaderIndex: threadListV2Layout.snoozedShelfHeaderIndex,
settledCount: threadListV2Layout.settledCount,
settledShelfExpanded,
settledShelfHeaderIndex: threadListV2Layout.settledShelfHeaderIndex,
snoozeLabelNow: `${nowMinute}:00.000Z`,
});
if (threadListV2Layout.hiddenSettledCount > 0) {
if (settledShelfExpanded && threadListV2Layout.hiddenSettledCount > 0) {
items.push({
type: "v2-show-more",
key: "v2-show-more",
Expand All @@ -574,6 +584,7 @@ function ThreadNavigationSidebarPane(
pendingTasks,
props.searchQuery,
selectedProjectRefs,
settledShelfExpanded,
snoozedShelfExpanded,
threadListV2Enabled,
threadListV2Layout,
Expand Down Expand Up @@ -780,7 +791,6 @@ function ThreadNavigationSidebarPane(
previous.key === item.key &&
previous.item.thread === item.item.thread &&
previous.item.variant === item.item.variant &&
previous.item.showSettledDivider === item.item.showSettledDivider &&
previous.item.snoozed === item.item.snoozed &&
previous.snoozeWakeLabelText === item.snoozeWakeLabelText
);
Expand All @@ -797,15 +807,20 @@ function ThreadNavigationSidebarPane(
if (previous.type === "v2-snoozed-shelf" && item.type === "v2-snoozed-shelf") {
return previous.count === item.count && previous.expanded === item.expanded;
}
if (previous.type === "v2-settled-shelf" && item.type === "v2-settled-shelf") {
return previous.count === item.count && previous.expanded === item.expanded;
}
if (
previous.type === "v2-thread" ||
previous.type === "v2-show-more" ||
previous.type === "v2-pending" ||
previous.type === "v2-snoozed-shelf" ||
previous.type === "v2-settled-shelf" ||
item.type === "v2-thread" ||
item.type === "v2-show-more" ||
item.type === "v2-pending" ||
item.type === "v2-snoozed-shelf"
item.type === "v2-snoozed-shelf" ||
item.type === "v2-settled-shelf"
) {
return false;
}
Expand Down Expand Up @@ -863,7 +878,6 @@ function ThreadNavigationSidebarPane(
<ThreadListV2Row
thread={thread}
variant={item.item.variant}
showSettledDivider={item.item.showSettledDivider}
snoozed={item.item.snoozed}
snoozePresetMinute={nowMinute}
snoozeWakeLabelText={item.snoozeWakeLabelText}
Expand Down Expand Up @@ -921,6 +935,15 @@ function ThreadNavigationSidebarPane(
pane="sidebar"
/>
);
case "v2-settled-shelf":
return (
<ThreadListV2SettledShelfHeader
count={item.count}
expanded={item.expanded}
onToggle={toggleSettledShelf}
pane="sidebar"
/>
);
case "v2-show-more":
return (
<Pressable
Expand Down Expand Up @@ -1039,6 +1062,7 @@ function ThreadNavigationSidebarPane(
snoozeEnvironmentIds,
snoozeThread,
nowMinute,
toggleSettledShelf,
toggleSnoozedShelf,
unsettleThread,
unsnoozeThread,
Expand Down
40 changes: 36 additions & 4 deletions apps/mobile/src/features/threads/thread-list-v2-items.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,42 @@ export const ThreadListV2SnoozedShelfHeader = memo(function ThreadListV2SnoozedS
);
});

export const ThreadListV2SettledShelfHeader = memo(function ThreadListV2SettledShelfHeader(props: {
readonly count: number;
readonly expanded: boolean;
readonly onToggle: () => void;
readonly pane?: "screen" | "sidebar";
}) {
const mutedColor = useThemeColor("--color-foreground-muted");
return (
<Pressable
accessibilityHint={
props.expanded ? "Collapses the settled threads." : "Expands the settled threads."
}
accessibilityLabel={props.count === 1 ? "1 settled thread" : `${props.count} settled threads`}
accessibilityRole="button"
accessibilityState={{ expanded: props.expanded }}
className={cn(
"mb-1.5 mt-4 flex-row items-center gap-2.5",
props.pane === "sidebar" ? "px-3" : "px-5",
)}
onPress={props.onToggle}
style={({ pressed }) => ({ opacity: pressed ? 0.6 : 1 })}
>
<Text className="text-xs font-t3-medium text-foreground-tertiary">
{props.expanded ? "Settled" : `Settled (${props.count})`}
</Text>
<View className="h-px flex-1 bg-border" />
<SymbolView
name={props.expanded ? "chevron.up" : "chevron.down"}
size={10}
tintColor={mutedColor}
type="monochrome"
/>
</Pressable>
);
});

const PENDING_TASK_MENU_ACTIONS: MenuAction[] = [
{ id: "delete", title: "Delete", image: "trash", attributes: { destructive: true } },
];
Expand Down Expand Up @@ -267,7 +303,6 @@ export const ThreadListV2PendingRow = memo(function ThreadListV2PendingRow(props
export const ThreadListV2Row = memo(function ThreadListV2Row(props: {
readonly thread: EnvironmentThreadShell;
readonly variant: "card" | "slim";
readonly showSettledDivider: boolean;
/** Snoozed-shelf row: shows its wake time and offers Wake. */
readonly snoozed?: boolean;
/** Preformatted against the parent minute tick so this memoized row's
Expand Down Expand Up @@ -739,9 +774,6 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {

return (
<>
{props.showSettledDivider ? (
<ThreadListV2SectionDivider label="Settled" pane={props.pane} />
) : null}
<ThreadSwipeable
backgroundColor={sidebarPane ? drawerColor : screenColor}
compactActions={variant === "slim"}
Expand Down
Loading
Loading