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 fa406271198f..58214fd0d36f 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"; @@ -48,12 +56,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. @@ -476,23 +478,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]; @@ -784,11 +772,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { @@ -807,9 +791,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"), )} > @@ -819,11 +801,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { @@ -844,9 +822,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} @@ -865,9 +841,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} @@ -877,9 +851,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 }} @@ -893,9 +865,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", )} > @@ -909,9 +879,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" } /> @@ -928,9 +896,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" @@ -945,11 +911,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 }} > @@ -964,7 +926,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} @@ -975,14 +937,8 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { variant === "card" ? ( {sidebarPane ? ( cardContent @@ -1015,10 +959,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} @@ -1027,36 +969,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. */} @@ -1103,9 +1024,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", @@ -1127,15 +1046,9 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { )}