/** * Settings screen for Scry app. */ import React, { useState } from "react"; import { StyleSheet, View, Text, ScrollView, Pressable, Switch, ActivityIndicator, Alert, } from "react-native"; import { FontAwesome } from "@expo/vector-icons"; import { useQuery } from "convex/react"; import { api } from "../../convex/_generated/api"; import { useSync } from "@/lib/hooks/useSync"; import { useHashCache } from "@/lib/context"; interface SettingRowProps { icon: React.ComponentProps["name"]; title: string; subtitle?: string; onPress?: () => void; rightElement?: React.ReactNode; destructive?: boolean; } function SettingRow({ icon, title, subtitle, onPress, rightElement, destructive, }: SettingRowProps) { return ( [ styles.settingRow, pressed && onPress && styles.settingRowPressed, ]} onPress={onPress} disabled={!onPress} > {title} {subtitle && {subtitle}} {rightElement || (onPress && )} ); } function SettingSection({ title, children }: { title: string; children: React.ReactNode }) { return ( {title} {children} ); } export default function SettingsScreen() { const [cardDetectionEnabled, setCardDetectionEnabled] = useState(true); const [rotationMatchingEnabled, setRotationMatchingEnabled] = useState(true); // Get hash count from context const { cardHashes, hashesLoaded } = useHashCache(); // Sync hook for cache management const { isInitialized, isSyncing, lastSync, localCardCount, error: syncError, sync, clearCache } = useSync(); // Get total card count from Convex const cardCount = useQuery(api.cards.count); const formatLastSync = (timestamp: number) => { if (!timestamp) return "Never"; const date = new Date(timestamp); return date.toLocaleDateString() + " " + date.toLocaleTimeString(); }; const handleClearCache = () => { Alert.alert( "Clear Local Cache", "This will remove all downloaded card data. You'll need to sync again to scan cards.", [ { text: "Cancel", style: "cancel" }, { text: "Clear", style: "destructive", onPress: async () => { await clearCache(); Alert.alert("Cache Cleared", "Local card data has been removed."); }, }, ] ); }; const handleManualSync = async () => { await sync(); Alert.alert("Sync Complete", `${localCardCount} cards now available for scanning.`); }; return ( {/* Database section */} : undefined} /> : undefined} /> {syncError && ( )} {/* Recognition section */} } /> } /> {/* Collection section */} { // TODO: Implement export }} /> {/* About section */} { // TODO: Open source URL }} /> {/* Danger zone */} { Alert.alert( "Clear Collection", "This will remove all cards from your collection. This cannot be undone.", [ { text: "Cancel", style: "cancel" }, { text: "Clear", style: "destructive", onPress: () => {} }, ] ); }} destructive /> {/* Footer */} Scry • Card scanner for Magic: The Gathering Card data © Wizards of the Coast ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#1a1a1a", }, content: { paddingBottom: 40, }, section: { marginTop: 24, }, sectionTitle: { color: "#888", fontSize: 13, fontWeight: "600", textTransform: "uppercase", letterSpacing: 0.5, marginLeft: 16, marginBottom: 8, }, sectionContent: { backgroundColor: "#2a2a2a", borderRadius: 12, marginHorizontal: 16, overflow: "hidden", }, settingRow: { flexDirection: "row", alignItems: "center", padding: 14, borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: "#3a3a3a", }, settingRowPressed: { backgroundColor: "#333", }, settingIcon: { width: 32, height: 32, borderRadius: 8, backgroundColor: "rgba(0,122,255,0.1)", justifyContent: "center", alignItems: "center", marginRight: 12, }, settingIconDestructive: { backgroundColor: "rgba(255,107,107,0.1)", }, settingContent: { flex: 1, }, settingTitle: { color: "#fff", fontSize: 16, }, settingTitleDestructive: { color: "#FF6B6B", }, settingSubtitle: { color: "#888", fontSize: 13, marginTop: 2, }, footer: { marginTop: 40, alignItems: "center", paddingHorizontal: 16, }, footerText: { color: "#666", fontSize: 14, }, footerSubtext: { color: "#444", fontSize: 12, marginTop: 4, }, });