Update setting hooks

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2023-07-11 14:38:05 +03:00
parent 7ed62507c7
commit ca67493302
5 changed files with 69 additions and 72 deletions

View File

@@ -1 +1 @@
export { SettingsProvider, useSettings } from './settings';
export { SettingsProvider, useStorageUri, useNoMedia } from './settings';

View File

@@ -14,14 +14,15 @@ import {
createFile,
deleteFile,
} from 'react-native-scoped-storage';
import { Settings } from '../types';
import { LoadingView } from '../components';
import { Welcome } from '../screens';
import { clearPermissions, isPermissionForPath } from '../utilities';
interface SettingsContextType {
settings: Settings;
setSettings: (newSettings: Partial<Settings>) => void;
storageUri: string;
noMedia: boolean;
setStorageUri: (newStorageUri: string) => Promise<void>;
setNoMedia: (newNoMedia: boolean) => Promise<void>;
}
const SettingsContext = createContext<SettingsContextType | undefined>(
@@ -29,80 +30,70 @@ const SettingsContext = createContext<SettingsContextType | undefined>(
);
function SettingsProvider({ children }: { children: ReactNode }) {
const [settings, setSettings] = useState<Settings>({
storageUri: '',
noMedia: false,
});
const [storageUri, setStorageUri] = useState('');
const [noMedia, setNoMedia] = useState(false);
const [hasLoaded, setHasLoaded] = useState(false);
const updateSettings = (newSettings: Partial<Settings>) => {
const updatedSettings = { ...settings, ...newSettings };
const updateStorageUri = async (newStorageUri: string): Promise<void> => {
setStorageUri(newStorageUri);
void clearPermissions([updatedSettings.storageUri]);
void clearPermissions([newStorageUri]);
void AsyncStorage.setItem('storageUri', newStorageUri);
};
void AsyncStorage.setItem('storageUri', updatedSettings.storageUri);
const updateNoMedia = async (newNoMedia: boolean): Promise<void> => {
setNoMedia(newNoMedia);
void FileSystem.exists(
AndroidScoped.appendPath(updatedSettings.storageUri, '.nomedia'),
).then(noMediaExists => {
if (updatedSettings.noMedia && !noMediaExists) {
void createFile(
updatedSettings.storageUri,
'.nomedia',
'text/x-unknown',
);
} else if (!updatedSettings.noMedia && noMediaExists) {
void deleteFile(
AndroidScoped.appendPath(updatedSettings.storageUri, '.nomedia'),
);
}
});
const noMediaExists = await FileSystem.exists(
AndroidScoped.appendPath(storageUri, '.nomedia'),
);
setSettings(updatedSettings);
if (newNoMedia && !noMediaExists) {
await createFile(storageUri, '.nomedia', 'text/x-unknown');
} else if (!newNoMedia && noMediaExists) {
await deleteFile(AndroidScoped.appendPath(storageUri, '.nomedia'));
}
void AsyncStorage.setItem('noMedia', newNoMedia.toString());
};
useEffect(() => {
const loadSettings = async () => {
const storageUriValue = await AsyncStorage.getItem('storageUri');
const noMediaValue = await AsyncStorage.getItem('noMedia');
let storageUriValue = (await AsyncStorage.getItem('storageUri')) ?? '';
let noMediaValue = (await AsyncStorage.getItem('noMedia')) === 'true';
let storageUri = storageUriValue ?? '';
let noMedia = noMediaValue === 'true';
if (storageUri !== '') {
if (storageUriValue !== '') {
const permissions = await getPersistedUriPermissions();
if (
!permissions.some(permission =>
isPermissionForPath(permission, storageUri),
isPermissionForPath(permission, storageUriValue),
)
) {
storageUri = '';
storageUriValue = '';
}
try {
const exists = await FileSystem.exists(storageUri);
const exists = await FileSystem.exists(storageUriValue);
if (!exists) {
throw new Error('Storage URI does not exist');
}
const isDirectory = await FileSystem.isDir(storageUri);
const isDirectory = await FileSystem.isDir(storageUriValue);
if (!isDirectory) {
throw new Error('Storage URI is not a directory');
}
} catch {
storageUri = '';
storageUriValue = '';
}
noMedia = await FileSystem.exists(
AndroidScoped.appendPath(storageUri, '.nomedia'),
noMediaValue = await FileSystem.exists(
AndroidScoped.appendPath(storageUriValue, '.nomedia'),
);
}
setSettings({
storageUri,
noMedia,
});
setStorageUri(storageUriValue);
setNoMedia(noMediaValue);
setHasLoaded(true);
};
@@ -114,14 +105,19 @@ function SettingsProvider({ children }: { children: ReactNode }) {
}, []);
return (
<SettingsContext.Provider value={{ settings, setSettings: updateSettings }}>
<SettingsContext.Provider
value={{
storageUri,
noMedia,
setStorageUri: updateStorageUri,
setNoMedia: updateNoMedia,
}}>
{hasLoaded ? (
settings.storageUri === '' ? (
storageUri === '' ? (
<Welcome
selectStorageLocation={() => {
void openDocumentTree(true).then(uri => {
updateSettings({ storageUri: uri.uri });
});
selectStorageLocation={async () => {
const { uri } = await openDocumentTree(true);
await updateStorageUri(uri);
}}
/>
) : (
@@ -134,12 +130,20 @@ function SettingsProvider({ children }: { children: ReactNode }) {
);
}
const useSettings = (): SettingsContextType => {
function useStorageUri(): [string, (newStorageUri: string) => Promise<void>] {
const context = useContext(SettingsContext);
if (!context) {
throw new Error('useSettings must be used within a SettingsProvider');
throw new Error('useStorageUri must be used within a SettingsProvider');
}
return context;
};
return [context.storageUri, context.setStorageUri];
}
export { SettingsProvider, useSettings };
function useNoMedia(): [boolean, (newNoMedia: boolean) => Promise<void>] {
const context = useContext(SettingsContext);
if (!context) {
throw new Error('useNoMedia must be used within a SettingsProvider');
}
return [context.noMedia, context.setNoMedia];
}
export { SettingsProvider, useStorageUri, useNoMedia };

View File

@@ -6,7 +6,7 @@ import { openDocumentTree } from 'react-native-scoped-storage';
import { PaddedView } from '../components';
import styles from '../styles';
import { Meme } from '../database';
import { useSettings } from '../contexts';
import { useStorageUri, useNoMedia } from '../contexts';
const SettingsScreen = () => {
const [optimizingDatabase, setOptimizingDatabase] = useState(false);
@@ -14,7 +14,8 @@ const SettingsScreen = () => {
const [snackbarVisible, setSnackbarVisible] = useState(false);
const [snackbarMessage, setSnackbarMessage] = useState('');
const { settings, setSettings } = useSettings();
const [, setStorageUri] = useStorageUri();
const [noMedia, setNoMedia] = useNoMedia();
const realm = useRealm();
@@ -59,10 +60,9 @@ const SettingsScreen = () => {
<Button
mode="elevated"
style={styles.marginBottom}
onPress={() => {
void openDocumentTree(true).then(uri => {
setSettings({ storageUri: uri.uri });
});
onPress={async () => {
const { uri } = await openDocumentTree(true);
void setStorageUri(uri);
}}>
Change External Storage Path
</Button>
@@ -74,9 +74,9 @@ const SettingsScreen = () => {
]}>
<Text>Hide media from gallery</Text>
<Switch
value={settings.noMedia}
value={noMedia}
onValueChange={value => {
setSettings({ noMedia: value });
void setNoMedia(value);
}}
/>
</View>

View File

@@ -1 +0,0 @@
export type { default as Settings } from './settings';

View File

@@ -1,6 +0,0 @@
interface Settings {
storageUri: string;
noMedia: boolean;
}
export default Settings;