import React, { useEffect } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import { Folder, FileText, FileCode, FileAudio, File, Image as ImageIcon, } from 'lucide-react-native'; import { SettingsSection, SettingItem, RadioGroup, ToggleSwitch } from './settings-section'; import { spacing, radius, typography, type ThemePalette } from '../../theme/tokens'; import { useColors } from '../../theme/colors'; import { useSettingsStore, type FilesViewMode, type FilesSortKey, type FilesSortDir, } from '../../stores/settings-store'; import { useLocaleStore } from '../../stores/locale-store'; interface FilesPrefs { defaultViewMode: FilesViewMode; defaultSortKey: FilesSortKey; defaultSortDir: FilesSortDir; showIcons: boolean; coloredIcons: boolean; showThumbnails: boolean; showHiddenFiles: boolean; } interface SampleFile { name: string; isFolder: boolean; size: number; modified: string; hidden?: boolean; } const SAMPLE: SampleFile[] = [ { name: 'Documents', isFolder: true, size: 0, modified: '03-10' }, { name: 'Photos', isFolder: true, size: 0, modified: '03-14' }, { name: 'report.pdf', isFolder: false, size: 245000, modified: '03-15' }, { name: 'notes.md', isFolder: false, size: 1200, modified: '03-12' }, { name: 'song.mp3', isFolder: false, size: 5200000, modified: '03-01' }, { name: '.config', isFolder: false, size: 340, modified: '02-20', hidden: true }, ]; function formatSize(b: number) { if (b === 0) return '-'; if (b < 1024) return `${b} B`; if (b < 1024 * 1024) return `${(b / 1024).toFixed(1)} KB`; return `${(b / (1024 * 1024)).toFixed(1)} MB`; } function getIcon(c: ThemePalette, file: SampleFile, colored: boolean, sz: number) { if (file.isFolder) return ; const ext = file.name.split('.').pop()?.toLowerCase(); switch (ext) { case 'jpg': case 'png': case 'gif': return ; case 'mp3': case 'wav': return ; case 'pdf': return ; case 'md': case 'json': case 'js': case 'ts': return ; default: return ; } } function FilesPreview({ prefs }: { prefs: FilesPrefs }) { const c = useColors(); const styles = React.useMemo(() => makeStyles(c), [c]); const t = useLocaleStore((s) => s.t); const files = SAMPLE.filter((f) => { if (!prefs.showHiddenFiles && f.hidden) return false; return true; }).sort((a, b) => { if (a.isFolder !== b.isFolder) return a.isFolder ? -1 : 1; let cmp = 0; if (prefs.defaultSortKey === 'name') cmp = a.name.localeCompare(b.name); if (prefs.defaultSortKey === 'size') cmp = a.size - b.size; if (prefs.defaultSortKey === 'modified') cmp = a.modified.localeCompare(b.modified); return prefs.defaultSortDir === 'desc' ? -cmp : cmp; }); if (prefs.defaultViewMode === 'grid') { return ( {files.map((f) => ( {prefs.showIcons ? getIcon(c, f, prefs.coloredIcons, 24) : } {f.name} ))} ); } return ( {t('files.name', 'Name')} {t('files.size', 'Size')} {t('files.modified', 'Modified')} {files.map((f) => ( {prefs.showIcons && getIcon(c, f, prefs.coloredIcons, 14)} {f.name} {formatSize(f.size)} {f.modified} ))} ); } export function FilesSettings() { const c = useColors(); const styles = React.useMemo(() => makeStyles(c), [c]); const hydrated = useSettingsStore((s) => s.hydrated); const hydrate = useSettingsStore((s) => s.hydrate); const set = useSettingsStore((s) => s.updateSetting); const t = useLocaleStore((s) => s.t); const defaultViewMode = useSettingsStore((s) => s.filesDefaultViewMode); const defaultSortKey = useSettingsStore((s) => s.filesDefaultSortKey); const defaultSortDir = useSettingsStore((s) => s.filesDefaultSortDir); const showIcons = useSettingsStore((s) => s.filesShowIcons); const coloredIcons = useSettingsStore((s) => s.filesColoredIcons); const showThumbnails = useSettingsStore((s) => s.filesShowThumbnails); const showHiddenFiles = useSettingsStore((s) => s.filesShowHiddenFiles); useEffect(() => { if (!hydrated) void hydrate(); }, [hydrated, hydrate]); const prefs: FilesPrefs = { defaultViewMode, defaultSortKey, defaultSortDir, showIcons, coloredIcons, showThumbnails, showHiddenFiles, }; return ( {t('files.preview', 'Preview')} set('filesDefaultViewMode', v as FilesViewMode)} options={[ { value: 'list', label: t('files.list_view', 'List') }, { value: 'grid', label: t('files.grid_view', 'Grid') }, ]} /> set('filesDefaultSortKey', v as FilesSortKey)} options={[ { value: 'name', label: t('files.name', 'Name') }, { value: 'size', label: t('files.size', 'Size') }, { value: 'modified', label: t('files.modified', 'Modified') }, ]} /> set('filesDefaultSortDir', v as FilesSortDir)} options={[ { value: 'asc', label: t('files.settings_ascending', 'Ascending') }, { value: 'desc', label: t('files.settings_descending', 'Descending') }, ]} /> set('filesShowIcons', v)} /> set('filesColoredIcons', v)} disabled={!showIcons} /> set('filesShowThumbnails', v)} /> ); } function makeStyles(c: ThemePalette) { return StyleSheet.create({ container: { gap: spacing.xxxl }, previewLabel: { ...typography.bodyMedium, color: c.text, marginBottom: spacing.sm }, previewBox: { borderRadius: radius.md, borderWidth: 1, borderColor: c.border, backgroundColor: c.background, overflow: 'hidden', minHeight: 160, }, listHeader: { flexDirection: 'row', alignItems: 'center', gap: spacing.sm, paddingVertical: 4, paddingHorizontal: spacing.sm, borderBottomWidth: 1, borderBottomColor: c.border, backgroundColor: c.muted, }, listHeaderText: { fontSize: 10, fontWeight: '500', color: c.mutedForeground }, listRow: { flexDirection: 'row', alignItems: 'center', gap: spacing.sm, paddingVertical: 6, paddingHorizontal: spacing.sm, borderBottomWidth: 1, borderBottomColor: c.border, }, listName: { fontSize: 11, color: c.text, flex: 1 }, listMeta: { fontSize: 10, color: c.mutedForeground, width: 60, textAlign: 'right' }, gridWrap: { flexDirection: 'row', flexWrap: 'wrap', gap: 6, padding: spacing.sm, }, gridItem: { alignItems: 'center', gap: 4, padding: spacing.sm, width: 72, borderRadius: radius.sm, }, gridName: { fontSize: 9, color: c.text, textAlign: 'center' }, }); }