Set and persist a data directory
This commit is contained in:
+4
-35
@@ -5,6 +5,7 @@ import { HelloWave } from '@/components/HelloWave';
|
||||
import ParallaxScrollView from '@/components/ParallaxScrollView';
|
||||
import { ThemedText } from '@/components/ThemedText';
|
||||
import { ThemedView } from '@/components/ThemedView';
|
||||
import { Text } from 'react-native-paper';
|
||||
|
||||
export default function HomeScreen() {
|
||||
return (
|
||||
@@ -16,41 +17,9 @@ export default function HomeScreen() {
|
||||
style={styles.headerImage}
|
||||
/>
|
||||
}>
|
||||
<ThemedView style={styles.titleContainer}>
|
||||
<ThemedText type="title">Welcome bruh.</ThemedText>
|
||||
<HelloWave />
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
||||
<ThemedText>
|
||||
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
||||
Press{' '}
|
||||
<ThemedText type="defaultSemiBold">
|
||||
{Platform.select({
|
||||
ios: 'cmd + d',
|
||||
android: 'cmd + m',
|
||||
web: 'F12',
|
||||
})}
|
||||
</ThemedText>{' '}
|
||||
to open developer tools.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
|
||||
<ThemedText>
|
||||
{`Tap the Explore tab to learn more about what's included in this starter app.`}
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
||||
<ThemedText>
|
||||
{`When you're ready, run `}
|
||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<Text variant="headlineLarge" style={styles.titleContainer}>
|
||||
My Journey
|
||||
</Text>
|
||||
</ParallaxScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
+84
-19
@@ -1,27 +1,92 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, Text, View } from 'react-native';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Button, View } from 'react-native';
|
||||
import { pickDirectory } from '@react-native-documents/picker'
|
||||
import { List, Text } from 'react-native-paper';
|
||||
import { Directory, Paths } from 'expo-file-system/next';
|
||||
import { StorageAccessFramework } from 'expo-file-system';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
const DATA_DIRECTORY_URI_KEY = 'dataDirectoryUri';
|
||||
|
||||
const prettyName = (uri: string | null) => {
|
||||
if (!uri) return null;
|
||||
const decodedUri = decodeURIComponent(uri);
|
||||
const match = decodedUri.match(/.*\/primary:(.+)/);
|
||||
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
|
||||
// Fallback to your original logic
|
||||
return uri.split('%3A').pop() || "Unknown";
|
||||
|
||||
}
|
||||
|
||||
export default function SettingsScreen() {
|
||||
const [directoryUri, setDirectoryUri] = useState<string | null>(null);
|
||||
// Load saved directory URI on component mount
|
||||
useEffect(() => {
|
||||
const loadDirectoryUri = async () => {
|
||||
try {
|
||||
const savedUri = await AsyncStorage.getItem(DATA_DIRECTORY_URI_KEY);
|
||||
if (savedUri) {
|
||||
setDirectoryUri(savedUri);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading directory URI:', error);
|
||||
}
|
||||
};
|
||||
|
||||
loadDirectoryUri();
|
||||
}, []);
|
||||
|
||||
// Save directory URI whenever it changes
|
||||
const saveDirectoryUri = async (uri: string | null) => {
|
||||
try {
|
||||
if (uri) {
|
||||
await AsyncStorage.setItem(DATA_DIRECTORY_URI_KEY, uri);
|
||||
} else {
|
||||
await AsyncStorage.removeItem(DATA_DIRECTORY_URI_KEY);
|
||||
}
|
||||
setDirectoryUri(uri);
|
||||
} catch (error) {
|
||||
console.error('Error saving directory URI:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', gap: 20 }}>
|
||||
<Text>{directoryUri ?? "No directory set."}</Text>
|
||||
<Button
|
||||
title="open directory"
|
||||
onPress={async () => {
|
||||
try {
|
||||
const { uri } = await pickDirectory({
|
||||
requestLongTermAccess: false,
|
||||
})
|
||||
console.log(uri)
|
||||
setDirectoryUri(uri)
|
||||
} catch (err) {
|
||||
// see error handling section
|
||||
console.error(err)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View style={{ flex: 1, padding: 16, backgroundColor: 'white' }}>
|
||||
<List.Section title="Data" style={{ backgroundColor: 'white', }} titleStyle={{ fontSize: 24, fontWeight: 'bold' }}>
|
||||
<List.Item
|
||||
left={props => <List.Icon {...props} icon="folder" />}
|
||||
title={prettyName(directoryUri) ?? "No directory selected. Tap to select."}
|
||||
right={props => <List.Icon {...props} icon="chevron-right" />}
|
||||
|
||||
onPress={async () => {
|
||||
try {
|
||||
const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync();
|
||||
if (permissions.granted) {
|
||||
await saveDirectoryUri(permissions.directoryUri);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</List.Section>
|
||||
<Button title="Debug: List Files" onPress={async () => {
|
||||
if (!directoryUri) {
|
||||
console.warn("No directory set.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const dir = await StorageAccessFramework.readDirectoryAsync(directoryUri);
|
||||
console.log("Directory contents:", dir.map((file, i) => prettyName(file)));
|
||||
} catch (error) {
|
||||
console.error("Error reading directory:", error);
|
||||
}
|
||||
}
|
||||
} />
|
||||
</View>
|
||||
)
|
||||
|
||||
|
||||
+16
-4
@@ -1,11 +1,11 @@
|
||||
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
|
||||
import { DarkTheme, ThemeProvider } from '@react-navigation/native';
|
||||
import { createDrawerNavigator } from '@react-navigation/drawer';
|
||||
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||
import { useFonts } from 'expo-font';
|
||||
import { Stack } from 'expo-router';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import 'react-native-reanimated';
|
||||
|
||||
import { MD3LightTheme as DefaultTheme, PaperProvider } from 'react-native-paper';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import SettingsScreen from './SettingsScreen';
|
||||
import { IconSymbol } from '@/components/ui/IconSymbol';
|
||||
@@ -70,6 +70,18 @@ function DrawerNavigator() {
|
||||
);
|
||||
}
|
||||
|
||||
const theme = {
|
||||
...DefaultTheme,
|
||||
colors: {
|
||||
...DefaultTheme.colors,
|
||||
primary: Colors.light.tint,
|
||||
background: Colors.light.background,
|
||||
text: Colors.light.text,
|
||||
placeholder: Colors.light.tabIconDefault,
|
||||
icon: Colors.light.icon,
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout() {
|
||||
const colorScheme = useColorScheme();
|
||||
const [loaded] = useFonts({
|
||||
@@ -81,7 +93,7 @@ export default function RootLayout() {
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||
<PaperProvider theme={theme}>
|
||||
<RootStack.Navigator>
|
||||
<RootStack.Screen
|
||||
name="Main"
|
||||
@@ -112,6 +124,6 @@ export default function RootLayout() {
|
||||
/>
|
||||
</RootStack.Navigator>
|
||||
<StatusBar style="auto" />
|
||||
</ThemeProvider>
|
||||
</PaperProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user