chore: vendor client into main repo

This commit is contained in:
吕新雨
2026-01-28 22:54:21 +08:00
parent 7d743e78ea
commit 6a598f0a98
79 changed files with 12952 additions and 1 deletions

View File

@@ -0,0 +1,61 @@
import { useEffect, useMemo, useState } from 'react';
import { FlatList, StyleSheet, Text, View } from 'react-native';
import { useTranslation } from 'react-i18next';
import { MOCK_CONTENT } from '@/src/constants/mockContent';
import { getFavorites } from '@/src/storage/appStorage';
export default function FavoritesScreen() {
const { t } = useTranslation();
const [ids, setIds] = useState<string[]>([]);
useEffect(() => {
let cancelled = false;
(async () => {
const list = await getFavorites();
if (!cancelled) setIds(list);
})();
return () => {
cancelled = true;
};
}, []);
const items = useMemo(() => {
const map = new Map(MOCK_CONTENT.map((c) => [c.id, c]));
return ids.map((id) => map.get(id)).filter(Boolean) as { id: string; text: string }[];
}, [ids]);
return (
<View style={styles.container}>
{items.length === 0 ? (
<Text style={styles.empty}>{t('favorites.empty')}</Text>
) : (
<FlatList
data={items}
keyExtractor={(it) => it.id}
contentContainerStyle={styles.list}
renderItem={({ item }) => (
<View style={styles.row}>
<Text style={styles.text}>{item.text}</Text>
</View>
)}
/>
)}
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 16 },
empty: { color: '#6B7280', fontSize: 16, textAlign: 'center', marginTop: 40 },
list: { gap: 12, paddingBottom: 24 },
row: {
borderRadius: 14,
padding: 16,
backgroundColor: '#F9FAFB',
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#E5E7EB',
},
text: { color: '#111827', fontSize: 16, lineHeight: 22 },
});