Update setting hooks
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
export { SettingsProvider, useSettings } from './settings';
|
||||
export { SettingsProvider, useStorageUri, useNoMedia } from './settings';
|
||||
|
@@ -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 };
|
||||
|
@@ -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>
|
||||
|
@@ -1 +0,0 @@
|
||||
export type { default as Settings } from './settings';
|
@@ -1,6 +0,0 @@
|
||||
interface Settings {
|
||||
storageUri: string;
|
||||
noMedia: boolean;
|
||||
}
|
||||
|
||||
export default Settings;
|
Reference in New Issue
Block a user