diff --git a/apps/mobile/src/features/threads/thread-list-v2-items.tsx b/apps/mobile/src/features/threads/thread-list-v2-items.tsx index a1b16ee21ffd8a9b930b78de07dcf45b5534bdfc..bd7b481c337f36925fe112742fe7e58db1751f1e 100644 --- a/apps/mobile/src/features/threads/thread-list-v2-items.tsx +++ b/apps/mobile/src/features/threads/thread-list-v2-items.tsx @@ -1,3 +1,11 @@ +import { + THREAD_LIST_V2_MONO_FONT as MONO_FONT, + THREAD_LIST_V2_ROW_CONTENT_CLASS_NAME, + THREAD_LIST_V2_ROW_DIVIDERS, + selectedThreadRowColors, + getThreadListV2NewBranchMenuTitle, + getThreadListV2RowAppearance, +} from "./thread-list-v2-row-appearance"; import { RowPressable } from "../../components/RowPressable"; import { CustomSnoozeSheet } from "./CustomSnoozeSheet"; import { appAtomRegistry } from "../../state/atom-registry"; @@ -13,7 +21,7 @@ import { canSnooze, resolveSnoozePresets } from "@t3tools/client-runtime/state/t import { resolveSettledThreadTimestamp } from "@t3tools/client-runtime/state/thread-sort"; import type { MenuAction } from "@react-native-menu/menu"; import { memo, useCallback, useEffect, useMemo, useState, type ComponentProps } from "react"; -import { Alert, Platform, Pressable, useWindowDimensions, View } from "react-native"; +import { Alert, Pressable, useWindowDimensions, View } from "react-native"; import type { SwipeableMethods } from "react-native-gesture-handler/ReanimatedSwipeable"; import { SymbolView } from "../../components/AppSymbol"; @@ -49,12 +57,6 @@ import { ThreadSearchMatchExcerpt } from "./thread-search-match"; * hierarchy rather than card fills. */ -const MONO_FONT = Platform.select({ - ios: "Menlo", - android: "monospace", - default: "monospace", -}); - // Status hues follow the system-wide convention set by sidebar v1 and the // Live Activity/widgets (amber approval, indigo input, sky working) so a // thread reads the same color everywhere it surfaces. @@ -477,23 +479,9 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { const pr = useThreadPr(thread); const theme = useUniwindTheme(); - const screenColor = theme["--color-screen"]; - const drawerColor = theme["--color-drawer"]; - const selectedBackgroundColor = - theme[Platform.OS === "android" ? "--color-thread-selected" : "--color-user-bubble"]; const sidebarPane = props.pane === "sidebar"; const selected = props.selected === true; - // The provider badge's border blends into the row's own surface, which - // differs by pane and (for the sidebar pane) selection: the sidebar row - // background becomes the selected fill or the drawer surface, while the - // flat "screen" pane rows always sit on the screen background. - const providerIconSurfaceColor = sidebarPane - ? selected - ? selectedBackgroundColor - : Platform.OS === "android" - ? screenColor - : drawerColor - : screenColor; + const rowAppearance = getThreadListV2RowAppearance(theme, sidebarPane, selected); const status = resolveThreadListV2Status(thread); const statusLabel = STATUS_LABEL_BY_STATUS[status]; @@ -788,11 +776,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { @@ -811,9 +795,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { className={cn( "text-xs tabular-nums", selected - ? Platform.OS === "android" - ? "text-thread-selected-foreground" - : "text-user-bubble-foreground" + ? selectedThreadRowColors.foregroundClassName : (statusLabel?.className ?? "text-foreground-tertiary"), )} > @@ -823,11 +805,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { @@ -848,9 +826,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { className={cn( "flex-1 text-xs", selected - ? Platform.OS === "android" - ? "text-thread-selected-foreground-muted" - : "text-user-bubble-foreground-muted" + ? selectedThreadRowColors.mutedForegroundClassName : "text-danger-foreground", )} numberOfLines={1} @@ -869,9 +845,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { className={cn( "shrink text-xs", selected - ? Platform.OS === "android" - ? "text-thread-selected-foreground-muted" - : "text-user-bubble-foreground-muted" + ? selectedThreadRowColors.mutedForegroundClassName : "text-foreground-muted", )} numberOfLines={1} @@ -881,9 +855,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { className={cn( "text-xs", selected - ? Platform.OS === "android" - ? "text-thread-selected-foreground-muted" - : "text-user-bubble-foreground-muted" + ? selectedThreadRowColors.mutedForegroundClassName : "text-foreground-muted", )} style={{ fontFamily: MONO_FONT }} @@ -897,9 +869,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { className={cn( "text-xs", selected - ? Platform.OS === "android" - ? "text-thread-selected-foreground-muted" - : "text-user-bubble-foreground-muted" + ? selectedThreadRowColors.mutedForegroundClassName : "text-foreground-tertiary", )} > @@ -913,9 +883,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { size={11} tintColorClassName={ selected - ? Platform.OS === "android" - ? "accent-thread-selected-foreground-muted" - : "accent-user-bubble-foreground-muted" + ? selectedThreadRowColors.mutedIconTintClassName : "accent-foreground-tertiary" } /> @@ -932,9 +900,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { size={12} tintColorClassName={ selected - ? Platform.OS === "android" - ? "accent-thread-selected-foreground" - : "accent-user-bubble-foreground" + ? selectedThreadRowColors.iconTintClassName : pr.state === null || pr.isDraft ? "accent-foreground-muted" : pr.state === "open" @@ -949,11 +915,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { accessibilityLabel={pr.accessibilityLabel} className={cn( "text-xs", - selected - ? Platform.OS === "android" - ? "text-thread-selected-foreground" - : "text-user-bubble-foreground" - : pr.textClassName, + selected ? selectedThreadRowColors.foregroundClassName : pr.textClassName, )} style={{ fontFamily: MONO_FONT }} > @@ -968,7 +930,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { displayName={props.providerInstance.displayName} accentColor={props.providerInstance.accentColor} showBadge={props.providerInstance.showBadge} - surfaceColor={providerIconSurfaceColor} + surfaceColor={rowAppearance.providerIconSurfaceColor} /> ) : null} @@ -979,14 +941,8 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { variant === "card" ? ( {sidebarPane ? ( cardContent @@ -1019,10 +963,8 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { separates rows. The opaque screen background stays so swipe actions reveal behind the row. */ - - {cardContent} - - {Platform.OS !== "android" && props.showTrailingDivider !== false ? ( + {cardContent} + {THREAD_LIST_V2_ROW_DIVIDERS && props.showTrailingDivider !== false ? ( ) : null} @@ -1031,36 +973,19 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { ) : ( { close(); onSelectThread(thread); }} - style={ - sidebarPane || Platform.OS === "android" - ? { - backgroundColor: selected - ? selectedBackgroundColor - : sidebarPane && Platform.OS !== "android" - ? drawerColor - : screenColor, - borderRadius: Platform.OS === "android" ? 20 : SIDEBAR_V2_ROW_RADIUS, - } - : undefined - } + style={rowAppearance.style} > {/* Settled history recedes: dimmed favicon + muted title. */} @@ -1107,9 +1028,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { className={cn( "text-sm tabular-nums", selected - ? Platform.OS === "android" - ? "text-thread-selected-foreground-muted" - : "text-user-bubble-foreground-muted" + ? selectedThreadRowColors.mutedForegroundClassName : snoozedRow ? "text-foreground-secondary" : "text-foreground-tertiary", @@ -1131,15 +1050,9 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { )}