| ... | ... | @@ -1,3 +1,11 @@ |
| 1 | import { |
| 2 | THREAD_LIST_V2_MONO_FONT as MONO_FONT, |
| 3 | THREAD_LIST_V2_ROW_CONTENT_CLASS_NAME, |
| 4 | THREAD_LIST_V2_ROW_DIVIDERS, |
| 5 | selectedThreadRowColors, |
| 6 | getThreadListV2NewBranchMenuTitle, |
| 7 | getThreadListV2RowAppearance, |
| 8 | } from "./thread-list-v2-row-appearance"; |
| 1 | 9 | import { RowPressable } from "../../components/RowPressable"; |
| 2 | 10 | import { CustomSnoozeSheet } from "./CustomSnoozeSheet"; |
| 3 | 11 | import { appAtomRegistry } from "../../state/atom-registry"; |
| ... | ... | @@ -13,7 +21,7 @@ import { canSnooze, resolveSnoozePresets } from "@t3tools/client-runtime/state/t |
| 13 | 21 | import { resolveSettledThreadTimestamp } from "@t3tools/client-runtime/state/thread-sort"; |
| 14 | 22 | import type { MenuAction } from "@react-native-menu/menu"; |
| 15 | 23 | import { memo, useCallback, useEffect, useMemo, useState, type ComponentProps } from "react"; |
| 16 | | import { Alert, Platform, Pressable, useWindowDimensions, View } from "react-native"; |
| 24 | import { Alert, Pressable, useWindowDimensions, View } from "react-native"; |
| 17 | 25 | import type { SwipeableMethods } from "react-native-gesture-handler/ReanimatedSwipeable"; |
| 18 | 26 | |
| 19 | 27 | import { SymbolView } from "../../components/AppSymbol"; |
| ... | ... | @@ -49,12 +57,6 @@ import { ThreadSearchMatchExcerpt } from "./thread-search-match"; |
| 49 | 57 | * hierarchy rather than card fills. |
| 50 | 58 | */ |
| 51 | 59 | |
| 52 | | const MONO_FONT = Platform.select({ |
| 53 | | ios: "Menlo", |
| 54 | | android: "monospace", |
| 55 | | default: "monospace", |
| 56 | | }); |
| 57 | | |
| 58 | 60 | // Status hues follow the system-wide convention set by sidebar v1 and the |
| 59 | 61 | // Live Activity/widgets (amber approval, indigo input, sky working) so a |
| 60 | 62 | // thread reads the same color everywhere it surfaces. |
| ... | ... | @@ -477,23 +479,9 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 477 | 479 | const pr = useThreadPr(thread); |
| 478 | 480 | |
| 479 | 481 | const theme = useUniwindTheme(); |
| 480 | | const screenColor = theme["--color-screen"]; |
| 481 | | const drawerColor = theme["--color-drawer"]; |
| 482 | | const selectedBackgroundColor = |
| 483 | | theme[Platform.OS === "android" ? "--color-thread-selected" : "--color-user-bubble"]; |
| 484 | 482 | const sidebarPane = props.pane === "sidebar"; |
| 485 | 483 | const selected = props.selected === true; |
| 486 | | // The provider badge's border blends into the row's own surface, which |
| 487 | | // differs by pane and (for the sidebar pane) selection: the sidebar row |
| 488 | | // background becomes the selected fill or the drawer surface, while the |
| 489 | | // flat "screen" pane rows always sit on the screen background. |
| 490 | | const providerIconSurfaceColor = sidebarPane |
| 491 | | ? selected |
| 492 | | ? selectedBackgroundColor |
| 493 | | : Platform.OS === "android" |
| 494 | | ? screenColor |
| 495 | | : drawerColor |
| 496 | | : screenColor; |
| 484 | const rowAppearance = getThreadListV2RowAppearance(theme, sidebarPane, selected); |
| 497 | 485 | |
| 498 | 486 | const status = resolveThreadListV2Status(thread); |
| 499 | 487 | const statusLabel = STATUS_LABEL_BY_STATUS[status]; |
| ... | ... | @@ -788,11 +776,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 788 | 776 | <Text |
| 789 | 777 | className={cn( |
| 790 | 778 | "flex-1 text-sm font-t3-medium", |
| 791 | | selected |
| 792 | | ? Platform.OS === "android" |
| 793 | | ? "text-thread-selected-foreground-muted" |
| 794 | | : "text-user-bubble-foreground-muted" |
| 795 | | : "text-foreground-muted", |
| 779 | selected ? selectedThreadRowColors.mutedForegroundClassName : "text-foreground-muted", |
| 796 | 780 | )} |
| 797 | 781 | numberOfLines={1} |
| 798 | 782 | > |
| ... | ... | @@ -811,9 +795,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 811 | 795 | className={cn( |
| 812 | 796 | "text-xs tabular-nums", |
| 813 | 797 | selected |
| 814 | | ? Platform.OS === "android" |
| 815 | | ? "text-thread-selected-foreground" |
| 816 | | : "text-user-bubble-foreground" |
| 798 | ? selectedThreadRowColors.foregroundClassName |
| 817 | 799 | : (statusLabel?.className ?? "text-foreground-tertiary"), |
| 818 | 800 | )} |
| 819 | 801 | > |
| ... | ... | @@ -823,11 +805,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 823 | 805 | <Text |
| 824 | 806 | className={cn( |
| 825 | 807 | "mt-1 text-base font-t3-medium", |
| 826 | | selected |
| 827 | | ? Platform.OS === "android" |
| 828 | | ? "text-thread-selected-foreground" |
| 829 | | : "text-user-bubble-foreground" |
| 830 | | : "text-foreground", |
| 808 | selected ? selectedThreadRowColors.foregroundClassName : "text-foreground", |
| 831 | 809 | )} |
| 832 | 810 | numberOfLines={2} |
| 833 | 811 | > |
| ... | ... | @@ -848,9 +826,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 848 | 826 | className={cn( |
| 849 | 827 | "flex-1 text-xs", |
| 850 | 828 | selected |
| 851 | | ? Platform.OS === "android" |
| 852 | | ? "text-thread-selected-foreground-muted" |
| 853 | | : "text-user-bubble-foreground-muted" |
| 829 | ? selectedThreadRowColors.mutedForegroundClassName |
| 854 | 830 | : "text-danger-foreground", |
| 855 | 831 | )} |
| 856 | 832 | numberOfLines={1} |
| ... | ... | @@ -869,9 +845,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 869 | 845 | className={cn( |
| 870 | 846 | "shrink text-xs", |
| 871 | 847 | selected |
| 872 | | ? Platform.OS === "android" |
| 873 | | ? "text-thread-selected-foreground-muted" |
| 874 | | : "text-user-bubble-foreground-muted" |
| 848 | ? selectedThreadRowColors.mutedForegroundClassName |
| 875 | 849 | : "text-foreground-muted", |
| 876 | 850 | )} |
| 877 | 851 | numberOfLines={1} |
| ... | ... | @@ -881,9 +855,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 881 | 855 | className={cn( |
| 882 | 856 | "text-xs", |
| 883 | 857 | selected |
| 884 | | ? Platform.OS === "android" |
| 885 | | ? "text-thread-selected-foreground-muted" |
| 886 | | : "text-user-bubble-foreground-muted" |
| 858 | ? selectedThreadRowColors.mutedForegroundClassName |
| 887 | 859 | : "text-foreground-muted", |
| 888 | 860 | )} |
| 889 | 861 | style={{ fontFamily: MONO_FONT }} |
| ... | ... | @@ -897,9 +869,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 897 | 869 | className={cn( |
| 898 | 870 | "text-xs", |
| 899 | 871 | selected |
| 900 | | ? Platform.OS === "android" |
| 901 | | ? "text-thread-selected-foreground-muted" |
| 902 | | : "text-user-bubble-foreground-muted" |
| 872 | ? selectedThreadRowColors.mutedForegroundClassName |
| 903 | 873 | : "text-foreground-tertiary", |
| 904 | 874 | )} |
| 905 | 875 | > |
| ... | ... | @@ -913,9 +883,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 913 | 883 | size={11} |
| 914 | 884 | tintColorClassName={ |
| 915 | 885 | selected |
| 916 | | ? Platform.OS === "android" |
| 917 | | ? "accent-thread-selected-foreground-muted" |
| 918 | | : "accent-user-bubble-foreground-muted" |
| 886 | ? selectedThreadRowColors.mutedIconTintClassName |
| 919 | 887 | : "accent-foreground-tertiary" |
| 920 | 888 | } |
| 921 | 889 | /> |
| ... | ... | @@ -932,9 +900,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 932 | 900 | size={12} |
| 933 | 901 | tintColorClassName={ |
| 934 | 902 | selected |
| 935 | | ? Platform.OS === "android" |
| 936 | | ? "accent-thread-selected-foreground" |
| 937 | | : "accent-user-bubble-foreground" |
| 903 | ? selectedThreadRowColors.iconTintClassName |
| 938 | 904 | : pr.state === null || pr.isDraft |
| 939 | 905 | ? "accent-foreground-muted" |
| 940 | 906 | : pr.state === "open" |
| ... | ... | @@ -949,11 +915,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 949 | 915 | accessibilityLabel={pr.accessibilityLabel} |
| 950 | 916 | className={cn( |
| 951 | 917 | "text-xs", |
| 952 | | selected |
| 953 | | ? Platform.OS === "android" |
| 954 | | ? "text-thread-selected-foreground" |
| 955 | | : "text-user-bubble-foreground" |
| 956 | | : pr.textClassName, |
| 918 | selected ? selectedThreadRowColors.foregroundClassName : pr.textClassName, |
| 957 | 919 | )} |
| 958 | 920 | style={{ fontFamily: MONO_FONT }} |
| 959 | 921 | > |
| ... | ... | @@ -968,7 +930,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 968 | 930 | displayName={props.providerInstance.displayName} |
| 969 | 931 | accentColor={props.providerInstance.accentColor} |
| 970 | 932 | showBadge={props.providerInstance.showBadge} |
| 971 | | surfaceColor={providerIconSurfaceColor} |
| 933 | surfaceColor={rowAppearance.providerIconSurfaceColor} |
| 972 | 934 | /> |
| 973 | 935 | ) : null} |
| 974 | 936 | </View> |
| ... | ... | @@ -979,14 +941,8 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 979 | 941 | variant === "card" ? ( |
| 980 | 942 | <RowPressable |
| 981 | 943 | key={`${thread.environmentId}:${thread.id}`} |
| 982 | | interactionClassName={ |
| 983 | | selected && (sidebarPane || Platform.OS === "android") |
| 984 | | ? Platform.OS === "android" |
| 985 | | ? "bg-thread-selected-foreground" |
| 986 | | : "bg-user-bubble-foreground" |
| 987 | | : "bg-primary" |
| 988 | | } |
| 989 | | className={sidebarPane || Platform.OS === "android" ? undefined : "bg-screen"} |
| 944 | interactionClassName={rowAppearance.interactionClassName} |
| 945 | className={rowAppearance.className} |
| 990 | 946 | accessibilityHint={swipeAccessibilityHint} |
| 991 | 947 | accessibilityLabel={ |
| 992 | 948 | props.hasQueuedMessages ? `${thread.title}, messages queued to send` : thread.title |
| ... | ... | @@ -997,19 +953,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 997 | 953 | close(); |
| 998 | 954 | onSelectThread(thread); |
| 999 | 955 | }} |
| 1000 | | style={ |
| 1001 | | sidebarPane || Platform.OS === "android" |
| 1002 | | ? { |
| 1003 | | backgroundColor: selected |
| 1004 | | ? selectedBackgroundColor |
| 1005 | | : sidebarPane && Platform.OS !== "android" |
| 1006 | | ? drawerColor |
| 1007 | | : screenColor, |
| 1008 | | borderRadius: Platform.OS === "android" ? 20 : SIDEBAR_V2_ROW_RADIUS, |
| 1009 | | ...(sidebarPane ? { paddingHorizontal: 12, paddingVertical: 10 } : null), |
| 1010 | | } |
| 1011 | | : undefined |
| 1012 | | } |
| 956 | style={rowAppearance.cardStyle} |
| 1013 | 957 | > |
| 1014 | 958 | {sidebarPane ? ( |
| 1015 | 959 | cardContent |
| ... | ... | @@ -1019,10 +963,8 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 1019 | 963 | separates rows. The opaque screen background stays so swipe |
| 1020 | 964 | actions reveal behind the row. */ |
| 1021 | 965 | <View> |
| 1022 | | <View className={Platform.OS === "android" ? "px-3 py-2.5" : "px-5 py-2.5"}> |
| 1023 | | {cardContent} |
| 1024 | | </View> |
| 1025 | | {Platform.OS !== "android" && props.showTrailingDivider !== false ? ( |
| 966 | <View className={THREAD_LIST_V2_ROW_CONTENT_CLASS_NAME}>{cardContent}</View> |
| 967 | {THREAD_LIST_V2_ROW_DIVIDERS && props.showTrailingDivider !== false ? ( |
| 1026 | 968 | <View className="ml-5 h-px bg-border-subtle" /> |
| 1027 | 969 | ) : null} |
| 1028 | 970 | </View> |
| ... | ... | @@ -1031,36 +973,19 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 1031 | 973 | ) : ( |
| 1032 | 974 | <RowPressable |
| 1033 | 975 | key={`${thread.environmentId}:${thread.id}`} |
| 1034 | | interactionClassName={ |
| 1035 | | selected && (sidebarPane || Platform.OS === "android") |
| 1036 | | ? Platform.OS === "android" |
| 1037 | | ? "bg-thread-selected-foreground" |
| 1038 | | : "bg-user-bubble-foreground" |
| 1039 | | : "bg-primary" |
| 1040 | | } |
| 976 | interactionClassName={rowAppearance.interactionClassName} |
| 1041 | 977 | accessibilityHint={swipeAccessibilityHint} |
| 1042 | 978 | accessibilityLabel={ |
| 1043 | 979 | props.hasQueuedMessages ? `${thread.title}, messages queued to send` : thread.title |
| 1044 | 980 | } |
| 1045 | 981 | accessibilityRole="button" |
| 1046 | 982 | accessibilityState={{ selected }} |
| 1047 | | className={sidebarPane || Platform.OS === "android" ? undefined : "bg-screen"} |
| 983 | className={rowAppearance.className} |
| 1048 | 984 | onPress={() => { |
| 1049 | 985 | close(); |
| 1050 | 986 | onSelectThread(thread); |
| 1051 | 987 | }} |
| 1052 | | style={ |
| 1053 | | sidebarPane || Platform.OS === "android" |
| 1054 | | ? { |
| 1055 | | backgroundColor: selected |
| 1056 | | ? selectedBackgroundColor |
| 1057 | | : sidebarPane && Platform.OS !== "android" |
| 1058 | | ? drawerColor |
| 1059 | | : screenColor, |
| 1060 | | borderRadius: Platform.OS === "android" ? 20 : SIDEBAR_V2_ROW_RADIUS, |
| 1061 | | } |
| 1062 | | : undefined |
| 1063 | | } |
| 988 | style={rowAppearance.style} |
| 1064 | 989 | > |
| 1065 | 990 | {/* Settled history recedes: dimmed favicon + muted title. */} |
| 1066 | 991 | <View |
| ... | ... | @@ -1084,11 +1009,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 1084 | 1009 | <Text |
| 1085 | 1010 | className={cn( |
| 1086 | 1011 | "text-base", |
| 1087 | | selected |
| 1088 | | ? Platform.OS === "android" |
| 1089 | | ? "text-thread-selected-foreground" |
| 1090 | | : "text-user-bubble-foreground" |
| 1091 | | : "text-foreground-muted", |
| 1012 | selected ? selectedThreadRowColors.foregroundClassName : "text-foreground-muted", |
| 1092 | 1013 | )} |
| 1093 | 1014 | numberOfLines={1} |
| 1094 | 1015 | > |
| ... | ... | @@ -1107,9 +1028,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 1107 | 1028 | className={cn( |
| 1108 | 1029 | "text-sm tabular-nums", |
| 1109 | 1030 | selected |
| 1110 | | ? Platform.OS === "android" |
| 1111 | | ? "text-thread-selected-foreground-muted" |
| 1112 | | : "text-user-bubble-foreground-muted" |
| 1031 | ? selectedThreadRowColors.mutedForegroundClassName |
| 1113 | 1032 | : snoozedRow |
| 1114 | 1033 | ? "text-foreground-secondary" |
| 1115 | 1034 | : "text-foreground-tertiary", |
| ... | ... | @@ -1131,15 +1050,9 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 1131 | 1050 | )} |
| 1132 | 1051 | <ThreadSwipeable |
| 1133 | 1052 | threadKey={`${thread.environmentId}:${thread.id}`} |
| 1134 | | backgroundColor={sidebarPane && Platform.OS !== "android" ? drawerColor : screenColor} |
| 1053 | backgroundColor={rowAppearance.swipeBackgroundColor} |
| 1135 | 1054 | compactActions={variant === "slim"} |
| 1136 | | containerStyle={ |
| 1137 | | Platform.OS === "android" |
| 1138 | | ? { borderRadius: 20, overflow: "hidden", marginHorizontal: 8, marginVertical: 2 } |
| 1139 | | : sidebarPane |
| 1140 | | ? { borderRadius: SIDEBAR_V2_ROW_RADIUS, overflow: "hidden" } |
| 1141 | | : undefined |
| 1142 | | } |
| 1055 | containerStyle={rowAppearance.swipeContainerStyle} |
| 1143 | 1056 | enableTrackpadSwipe |
| 1144 | 1057 | // Full swipe commits the advertised lifecycle action (Settle / |
| 1145 | 1058 | // Un-settle), never the secondary snooze action. |
| ... | ... | @@ -1161,10 +1074,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { |
| 1161 | 1074 | ? [ |
| 1162 | 1075 | { |
| 1163 | 1076 | id: "new-thread-on-branch", |
| 1164 | | title: |
| 1165 | | Platform.OS === "ios" |
| 1166 | | ? "New thread on branch" |
| 1167 | | : `New thread on ${thread.branch}`, |
| 1077 | title: getThreadListV2NewBranchMenuTitle(thread.branch), |
| 1168 | 1078 | image: "square.and.pencil", |
| 1169 | 1079 | }, |
| 1170 | 1080 | ] |