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,
|
createFile,
|
||||||
deleteFile,
|
deleteFile,
|
||||||
} from 'react-native-scoped-storage';
|
} from 'react-native-scoped-storage';
|
||||||
import { Settings } from '../types';
|
|
||||||
import { LoadingView } from '../components';
|
import { LoadingView } from '../components';
|
||||||
import { Welcome } from '../screens';
|
import { Welcome } from '../screens';
|
||||||
import { clearPermissions, isPermissionForPath } from '../utilities';
|
import { clearPermissions, isPermissionForPath } from '../utilities';
|
||||||
|
|
||||||
interface SettingsContextType {
|
interface SettingsContextType {
|
||||||
settings: Settings;
|
storageUri: string;
|
||||||
setSettings: (newSettings: Partial<Settings>) => void;
|
noMedia: boolean;
|
||||||
|
setStorageUri: (newStorageUri: string) => Promise<void>;
|
||||||
|
setNoMedia: (newNoMedia: boolean) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SettingsContext = createContext<SettingsContextType | undefined>(
|
const SettingsContext = createContext<SettingsContextType | undefined>(
|
||||||
@@ -29,80 +30,70 @@ const SettingsContext = createContext<SettingsContextType | undefined>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
function SettingsProvider({ children }: { children: ReactNode }) {
|
function SettingsProvider({ children }: { children: ReactNode }) {
|
||||||
const [settings, setSettings] = useState<Settings>({
|
const [storageUri, setStorageUri] = useState('');
|
||||||
storageUri: '',
|
const [noMedia, setNoMedia] = useState(false);
|
||||||
noMedia: false,
|
|
||||||
});
|
|
||||||
const [hasLoaded, setHasLoaded] = useState(false);
|
const [hasLoaded, setHasLoaded] = useState(false);
|
||||||
|
|
||||||
const updateSettings = (newSettings: Partial<Settings>) => {
|
const updateStorageUri = async (newStorageUri: string): Promise<void> => {
|
||||||
const updatedSettings = { ...settings, ...newSettings };
|
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(
|
const noMediaExists = await FileSystem.exists(
|
||||||
AndroidScoped.appendPath(updatedSettings.storageUri, '.nomedia'),
|
AndroidScoped.appendPath(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'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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(() => {
|
useEffect(() => {
|
||||||
const loadSettings = async () => {
|
const loadSettings = async () => {
|
||||||
const storageUriValue = await AsyncStorage.getItem('storageUri');
|
let storageUriValue = (await AsyncStorage.getItem('storageUri')) ?? '';
|
||||||
const noMediaValue = await AsyncStorage.getItem('noMedia');
|
let noMediaValue = (await AsyncStorage.getItem('noMedia')) === 'true';
|
||||||
|
|
||||||
let storageUri = storageUriValue ?? '';
|
if (storageUriValue !== '') {
|
||||||
let noMedia = noMediaValue === 'true';
|
|
||||||
|
|
||||||
if (storageUri !== '') {
|
|
||||||
const permissions = await getPersistedUriPermissions();
|
const permissions = await getPersistedUriPermissions();
|
||||||
if (
|
if (
|
||||||
!permissions.some(permission =>
|
!permissions.some(permission =>
|
||||||
isPermissionForPath(permission, storageUri),
|
isPermissionForPath(permission, storageUriValue),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
storageUri = '';
|
storageUriValue = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const exists = await FileSystem.exists(storageUri);
|
const exists = await FileSystem.exists(storageUriValue);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
throw new Error('Storage URI does not exist');
|
throw new Error('Storage URI does not exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
const isDirectory = await FileSystem.isDir(storageUri);
|
const isDirectory = await FileSystem.isDir(storageUriValue);
|
||||||
if (!isDirectory) {
|
if (!isDirectory) {
|
||||||
throw new Error('Storage URI is not a directory');
|
throw new Error('Storage URI is not a directory');
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
storageUri = '';
|
storageUriValue = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
noMedia = await FileSystem.exists(
|
noMediaValue = await FileSystem.exists(
|
||||||
AndroidScoped.appendPath(storageUri, '.nomedia'),
|
AndroidScoped.appendPath(storageUriValue, '.nomedia'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSettings({
|
setStorageUri(storageUriValue);
|
||||||
storageUri,
|
setNoMedia(noMediaValue);
|
||||||
noMedia,
|
|
||||||
});
|
|
||||||
|
|
||||||
setHasLoaded(true);
|
setHasLoaded(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,14 +105,19 @@ function SettingsProvider({ children }: { children: ReactNode }) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingsContext.Provider value={{ settings, setSettings: updateSettings }}>
|
<SettingsContext.Provider
|
||||||
|
value={{
|
||||||
|
storageUri,
|
||||||
|
noMedia,
|
||||||
|
setStorageUri: updateStorageUri,
|
||||||
|
setNoMedia: updateNoMedia,
|
||||||
|
}}>
|
||||||
{hasLoaded ? (
|
{hasLoaded ? (
|
||||||
settings.storageUri === '' ? (
|
storageUri === '' ? (
|
||||||
<Welcome
|
<Welcome
|
||||||
selectStorageLocation={() => {
|
selectStorageLocation={async () => {
|
||||||
void openDocumentTree(true).then(uri => {
|
const { uri } = await openDocumentTree(true);
|
||||||
updateSettings({ storageUri: uri.uri });
|
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);
|
const context = useContext(SettingsContext);
|
||||||
if (!context) {
|
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 { PaddedView } from '../components';
|
||||||
import styles from '../styles';
|
import styles from '../styles';
|
||||||
import { Meme } from '../database';
|
import { Meme } from '../database';
|
||||||
import { useSettings } from '../contexts';
|
import { useStorageUri, useNoMedia } from '../contexts';
|
||||||
|
|
||||||
const SettingsScreen = () => {
|
const SettingsScreen = () => {
|
||||||
const [optimizingDatabase, setOptimizingDatabase] = useState(false);
|
const [optimizingDatabase, setOptimizingDatabase] = useState(false);
|
||||||
@@ -14,7 +14,8 @@ const SettingsScreen = () => {
|
|||||||
const [snackbarVisible, setSnackbarVisible] = useState(false);
|
const [snackbarVisible, setSnackbarVisible] = useState(false);
|
||||||
const [snackbarMessage, setSnackbarMessage] = useState('');
|
const [snackbarMessage, setSnackbarMessage] = useState('');
|
||||||
|
|
||||||
const { settings, setSettings } = useSettings();
|
const [, setStorageUri] = useStorageUri();
|
||||||
|
const [noMedia, setNoMedia] = useNoMedia();
|
||||||
|
|
||||||
const realm = useRealm();
|
const realm = useRealm();
|
||||||
|
|
||||||
@@ -59,10 +60,9 @@ const SettingsScreen = () => {
|
|||||||
<Button
|
<Button
|
||||||
mode="elevated"
|
mode="elevated"
|
||||||
style={styles.marginBottom}
|
style={styles.marginBottom}
|
||||||
onPress={() => {
|
onPress={async () => {
|
||||||
void openDocumentTree(true).then(uri => {
|
const { uri } = await openDocumentTree(true);
|
||||||
setSettings({ storageUri: uri.uri });
|
void setStorageUri(uri);
|
||||||
});
|
|
||||||
}}>
|
}}>
|
||||||
Change External Storage Path
|
Change External Storage Path
|
||||||
</Button>
|
</Button>
|
||||||
@@ -74,9 +74,9 @@ const SettingsScreen = () => {
|
|||||||
]}>
|
]}>
|
||||||
<Text>Hide media from gallery</Text>
|
<Text>Hide media from gallery</Text>
|
||||||
<Switch
|
<Switch
|
||||||
value={settings.noMedia}
|
value={noMedia}
|
||||||
onValueChange={value => {
|
onValueChange={value => {
|
||||||
setSettings({ noMedia: value });
|
void setNoMedia(value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</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