import { useAtomSet, useAtomValue } from "@effect/atom-react";
import { AsyncResult } from "effect/unstable/reactivity";
import { SymbolView } from "expo-symbols";
import { useMemo } from "react";
import { ActivityIndicator, Alert, Pressable, ScrollView, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { AppText as Text } from "../../components/AppText";
import { useThemeColor } from "../../lib/useThemeColor";
import {
clearClientCacheAtom,
clientCacheSummaryAtom,
type EnvironmentClientCacheSummary,
} from "../../state/client-cache-state";
import { useSavedRemoteConnections } from "../../state/use-remote-environment-registry";
import { SettingsSection } from "./components/SettingsSection";
export function SettingsClientStorageRouteScreen() {
const insets = useSafeAreaInsets();
const iconColor = useThemeColor("--color-icon");
const dangerForegroundColor = useThemeColor("--color-danger-foreground");
const summaryResult = useAtomValue(clientCacheSummaryAtom);
const clearResult = useAtomValue(clearClientCacheAtom);
const clearCache = useAtomSet(clearClientCacheAtom);
const { savedConnectionsById } = useSavedRemoteConnections();
const isClearing = clearResult.waiting;
const summary = AsyncResult.isSuccess(summaryResult) ? summaryResult.value : null;
const environmentSummaries = useMemo(
() =>
[...(summary?.environments ?? [])].sort((left, right) => {
const leftLabel = savedConnectionsById[left.environmentId]?.environmentLabel ?? "";
const rightLabel = savedConnectionsById[right.environmentId]?.environmentLabel ?? "";
return leftLabel.localeCompare(rightLabel);
}),
[savedConnectionsById, summary?.environments],
);
const confirmClearEnvironment = (environment: EnvironmentClientCacheSummary) => {
const label =
savedConnectionsById[environment.environmentId]?.environmentLabel ??
environment.environmentId;
Alert.alert(
`Clear cache for ${label}?`,
"This removes offline threads, server metadata, and cached branches for this environment. The saved connection and credentials stay intact.",
[
{ text: "Cancel", style: "cancel" },
{
text: "Clear Cache",
style: "destructive",
onPress: () =>
clearCache({ type: "environment", environmentId: environment.environmentId }),
},
],
);
};
const confirmClearAll = () => {
Alert.alert(
"Clear all client caches?",
"This removes offline data for every environment. Connections, credentials, account data, and app preferences stay intact.",
[
{ text: "Cancel", style: "cancel" },
{
text: "Clear All Caches",
style: "destructive",
onPress: () => clearCache({ type: "all" }),
},
],
);
};
return (
{AsyncResult.isFailure(summaryResult) ? (
Storage unavailable
Restart the app and try again.
) : !summary ? (
Inspecting cached data…
) : environmentSummaries.length > 0 ? (
environmentSummaries.map((environment, index) => (
confirmClearEnvironment(environment)}
/>
))
) : (
No cached data
Offline cache records will appear here after environments are used.
)}
{summary ? `Clear ${formatBytes(summary.payloadBytes)}` : "Clear caches"}
{isClearing ? : null}
Clearing caches never removes environment connections, credentials, account data, or
appearance preferences.
{AsyncResult.isFailure(summaryResult) || AsyncResult.isFailure(clearResult) ? (
Client storage is temporarily unavailable. Try again after restarting the app.
) : null}
);
}
function CacheEnvironmentRow(props: {
readonly environment: EnvironmentClientCacheSummary;
readonly environmentLabel: string;
readonly disabled: boolean;
readonly first: boolean;
readonly onClear: () => void;
}) {
const iconColor = useThemeColor("--color-icon");
return (
{props.environmentLabel}
Clear {formatBytes(props.environment.payloadBytes)}
);
}
function formatBytes(bytes: number): string {
if (bytes < 1024) return `${bytes} B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(bytes < 10 * 1024 ? 1 : 0)} KB`;
return `${(bytes / (1024 * 1024)).toFixed(bytes < 10 * 1024 * 1024 ? 1 : 0)} MB`;
}