This repository has been archived on 2025-07-31. You can view files and clone it, but cannot push or open issues or pull requests.
Files
terminally-online/src/state/settings.ts
Nikolaos Karaolidis 3c303e0304 Refactor validation
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2023-07-21 16:34:44 +03:00

117 lines
3.0 KiB
TypeScript

import { createSlice, PayloadAction, createAsyncThunk } from '@reduxjs/toolkit';
import {
createFile,
deleteFile,
getPersistedUriPermissions,
} from 'react-native-scoped-storage';
import { FileSystem, AndroidScoped } from 'react-native-file-access';
import { clearPermissions, isPermissionForPath } from '../utilities';
import { RootState } from '.';
interface SettingsState {
storageUri: string | undefined;
noMedia: boolean;
}
const initialState: SettingsState = {
storageUri: undefined,
noMedia: false,
};
const settingsSlice = createSlice({
name: 'settings',
initialState,
reducers: {
setStorageUri: (state, action: PayloadAction<string | undefined>) => {
state.storageUri = action.payload;
},
setNoMedia: (state, action: PayloadAction<boolean>) => {
state.noMedia = action.payload;
},
},
});
const { setStorageUri, setNoMedia } = settingsSlice.actions;
const updateStorageUri = createAsyncThunk(
'settings/updateStorageUri',
async (newStorageUri: string, { dispatch }) => {
await clearPermissions([newStorageUri]);
dispatch(setStorageUri(newStorageUri));
},
);
const updateNoMedia = createAsyncThunk(
'settings/updateNoMedia',
async (newNoMedia: boolean, { dispatch, getState }) => {
dispatch(setNoMedia(newNoMedia));
const state = getState() as RootState;
const { storageUri } = state.settings;
if (!storageUri) return;
const noMediaExists = await FileSystem.exists(
AndroidScoped.appendPath(storageUri, '.nomedia'),
);
if (newNoMedia && !noMediaExists) {
await createFile(storageUri, '.nomedia', 'text/x-unknown');
} else if (!newNoMedia && noMediaExists) {
await deleteFile(AndroidScoped.appendPath(storageUri, '.nomedia'));
}
},
);
const validateSettings = createAsyncThunk(
'settings/validateSettings',
// eslint-disable-next-line @typescript-eslint/naming-convention
async (_, { dispatch, getState }) => {
const state = getState() as RootState;
const { storageUri, noMedia } = state.settings;
if (!storageUri) {
return;
}
const permissions = await getPersistedUriPermissions();
if (
!permissions.some(permission =>
isPermissionForPath(permission, storageUri),
)
) {
dispatch(setStorageUri());
return;
}
try {
const exists = await FileSystem.exists(storageUri);
if (!exists) {
throw new Error('Storage URI does not exist');
}
const isDirectory = await FileSystem.isDir(storageUri);
if (!isDirectory) {
throw new Error('Storage URI is not a directory');
}
} catch {
dispatch(setStorageUri());
return;
}
const isNoMedia = await FileSystem.exists(
AndroidScoped.appendPath(storageUri, '.nomedia'),
);
if (noMedia !== isNoMedia) {
dispatch(setNoMedia(isNoMedia));
}
},
);
export {
type SettingsState,
updateStorageUri as setStorageUri,
updateNoMedia as setNoMedia,
validateSettings,
};
export default settingsSlice.reducer;