2024-07-09 15:53:34 +08:00
|
|
|
import { findAssetId } from "@lib/api/assets";
|
2024-05-23 19:29:56 +08:00
|
|
|
import { lazyDestructure } from "@lib/utils/lazy";
|
2025-10-11 02:26:41 +02:00
|
|
|
import {
|
|
|
|
|
Card,
|
|
|
|
|
FormRadio,
|
|
|
|
|
FormSwitch,
|
|
|
|
|
IconButton,
|
|
|
|
|
LegacyFormRow,
|
|
|
|
|
Stack,
|
|
|
|
|
Text,
|
|
|
|
|
} from "@metro/common/components";
|
2024-07-30 00:18:01 +08:00
|
|
|
import { findByProps } from "@metro/wrappers";
|
2024-05-23 19:29:56 +08:00
|
|
|
import { semanticColors } from "@ui/color";
|
|
|
|
|
import { createStyles, TextStyleSheet } from "@ui/styles";
|
|
|
|
|
import { TouchableOpacity, View } from "react-native";
|
|
|
|
|
|
2025-10-11 02:26:41 +02:00
|
|
|
const { hideActionSheet } = lazyDestructure(() =>
|
|
|
|
|
findByProps("openLazy", "hideActionSheet"),
|
|
|
|
|
);
|
|
|
|
|
const { showSimpleActionSheet } = lazyDestructure(() =>
|
|
|
|
|
findByProps("showSimpleActionSheet"),
|
|
|
|
|
);
|
2024-05-23 19:29:56 +08:00
|
|
|
|
2025-05-03 20:32:55 +01:00
|
|
|
// TODO: These styles work weirdly. Low DPI Has cramped text. Fix?
|
2024-05-23 19:29:56 +08:00
|
|
|
const useStyles = createStyles({
|
2025-10-11 02:26:41 +02:00
|
|
|
card: {
|
|
|
|
|
backgroundColor: semanticColors?.CARD_SECONDARY_BG,
|
|
|
|
|
borderRadius: 12,
|
|
|
|
|
overflow: "hidden",
|
|
|
|
|
},
|
|
|
|
|
header: {
|
|
|
|
|
padding: 0,
|
|
|
|
|
},
|
|
|
|
|
headerLeading: {
|
|
|
|
|
flexDirection: "column",
|
|
|
|
|
justifyContent: "center",
|
2026-05-15 21:41:32 +02:00
|
|
|
flexShrink: 1,
|
2025-10-11 02:26:41 +02:00
|
|
|
scale: 1.2,
|
|
|
|
|
},
|
|
|
|
|
headerTrailing: {
|
|
|
|
|
display: "flex",
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
gap: 15,
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
},
|
|
|
|
|
headerLabel: {
|
|
|
|
|
...TextStyleSheet["heading-md/semibold"],
|
2025-12-12 18:31:13 +01:00
|
|
|
color: semanticColors.MOBILE_TEXT_HEADING_PRIMARY,
|
2025-10-11 02:26:41 +02:00
|
|
|
},
|
|
|
|
|
headerSubtitle: {
|
|
|
|
|
...TextStyleSheet["text-md/semibold"],
|
|
|
|
|
color: semanticColors.TEXT_MUTED,
|
|
|
|
|
},
|
|
|
|
|
descriptionLabel: {
|
|
|
|
|
...TextStyleSheet["text-md/semibold"],
|
|
|
|
|
color: semanticColors.TEXT_NORMAL,
|
|
|
|
|
},
|
|
|
|
|
actions: {
|
|
|
|
|
flexDirection: "row-reverse",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
gap: 5,
|
|
|
|
|
},
|
|
|
|
|
iconStyle: {
|
2025-12-19 23:22:28 +01:00
|
|
|
tintColor: semanticColors.INTERACTIVE_ICON_DEFAULT,
|
2025-10-11 02:26:41 +02:00
|
|
|
opacity: 0.2,
|
|
|
|
|
height: 64,
|
|
|
|
|
width: 64,
|
|
|
|
|
left: void 0,
|
|
|
|
|
right: "30%",
|
|
|
|
|
top: "-10%",
|
|
|
|
|
},
|
2024-05-23 19:29:56 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
interface Action {
|
2025-10-11 02:26:41 +02:00
|
|
|
icon: string;
|
|
|
|
|
disabled?: boolean;
|
|
|
|
|
onPress: () => void;
|
2024-05-23 19:29:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface OverflowAction extends Action {
|
2025-10-11 02:26:41 +02:00
|
|
|
label: string;
|
|
|
|
|
isDestructive?: boolean;
|
2024-05-23 19:29:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface CardWrapper<T> {
|
2025-10-11 02:26:41 +02:00
|
|
|
item: T;
|
|
|
|
|
result: Fuzzysort.KeysResult<T>;
|
2024-05-23 19:29:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface CardProps {
|
2025-10-11 02:26:41 +02:00
|
|
|
index?: number;
|
|
|
|
|
headerLabel: string;
|
|
|
|
|
headerSublabel?: string;
|
|
|
|
|
headerIcon?: string;
|
|
|
|
|
toggleType?: "switch" | "radio";
|
|
|
|
|
toggleValue: () => boolean;
|
|
|
|
|
onToggleChange?: (v: boolean) => void;
|
|
|
|
|
descriptionLabel?: string;
|
|
|
|
|
actions?: Action[];
|
|
|
|
|
overflowTitle?: string;
|
|
|
|
|
overflowActions?: OverflowAction[];
|
2024-05-23 19:29:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function AddonCard(props: CardProps) {
|
2025-10-11 02:26:41 +02:00
|
|
|
const styles = useStyles();
|
2024-05-23 19:29:56 +08:00
|
|
|
|
2025-10-11 02:26:41 +02:00
|
|
|
return (
|
|
|
|
|
<Card>
|
|
|
|
|
<Stack spacing={16}>
|
|
|
|
|
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
|
|
|
|
<View style={styles.headerLeading}>
|
2026-05-15 21:41:32 +02:00
|
|
|
<Text numberOfLines={1} ellipsizeMode="tail" style={styles.headerLabel}>{props.headerLabel}</Text>
|
2025-10-11 02:26:41 +02:00
|
|
|
{props.headerSublabel && (
|
2026-05-15 21:41:32 +02:00
|
|
|
<Text numberOfLines={1} ellipsizeMode="tail" style={styles.headerSubtitle}>{props.headerSublabel}</Text>
|
2025-10-11 02:26:41 +02:00
|
|
|
)}
|
|
|
|
|
</View>
|
|
|
|
|
<View style={[styles.headerTrailing, { marginLeft: "auto" }]}>
|
|
|
|
|
<View style={styles.actions}>
|
|
|
|
|
{props.overflowActions && (
|
|
|
|
|
<IconButton
|
|
|
|
|
onPress={() =>
|
|
|
|
|
showSimpleActionSheet({
|
|
|
|
|
key: "CardOverflow",
|
|
|
|
|
header: {
|
|
|
|
|
title: props.overflowTitle,
|
|
|
|
|
icon: props.headerIcon && (
|
|
|
|
|
<LegacyFormRow.Icon
|
|
|
|
|
style={{ marginRight: 8 }}
|
|
|
|
|
source={findAssetId(props.headerIcon)}
|
|
|
|
|
/>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
options: props.overflowActions?.map((i) => ({
|
|
|
|
|
...i,
|
|
|
|
|
icon: findAssetId(i.icon),
|
|
|
|
|
})),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
size="sm"
|
|
|
|
|
variant="secondary"
|
|
|
|
|
icon={findAssetId("CircleInformationIcon-primary")}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
{props.actions?.map(({ icon, onPress, disabled }) => (
|
|
|
|
|
<IconButton
|
|
|
|
|
onPress={onPress}
|
|
|
|
|
disabled={disabled}
|
|
|
|
|
size="sm"
|
|
|
|
|
variant="secondary"
|
|
|
|
|
icon={findAssetId(icon)}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</View>
|
|
|
|
|
{props.toggleType &&
|
|
|
|
|
(props.toggleType === "switch" ? (
|
|
|
|
|
<FormSwitch
|
|
|
|
|
value={props.toggleValue()}
|
|
|
|
|
onValueChange={props.onToggleChange}
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<TouchableOpacity
|
|
|
|
|
onPress={() => {
|
|
|
|
|
props.onToggleChange?.(!props.toggleValue());
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<FormRadio selected={props.toggleValue()} />
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
))}
|
|
|
|
|
</View>
|
|
|
|
|
</View>
|
|
|
|
|
{props.descriptionLabel && (
|
|
|
|
|
<Text variant="text-md/medium">{props.descriptionLabel}</Text>
|
|
|
|
|
)}
|
|
|
|
|
</Stack>
|
|
|
|
|
</Card>
|
|
|
|
|
);
|
2024-05-23 19:29:56 +08:00
|
|
|
}
|