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/screens/settings.tsx
2023-07-29 22:43:58 +03:00

184 lines
5.2 KiB
TypeScript

import React, { useState } from 'react';
import { ScrollView, StyleSheet, View } from 'react-native';
import {
Button,
List,
Portal,
SegmentedButtons,
Snackbar,
Switch,
Text,
useTheme,
} from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux';
import type {} from 'redux-thunk/extend-redux';
import {
RootState,
setGridColumns,
setMasonryColumns,
setNoMedia,
} from '../state';
import StorageLocationChangeDialog from '../components/storageLocationChangeDialog';
import { useRealm } from '@realm/react';
import { FileSystem, FileStat } from 'react-native-file-access';
import { Meme } from '../database';
const settingsStyles = StyleSheet.create({
scrollView: {
paddingHorizontal: '4%',
},
snackbar: {
marginBottom: 90,
},
marginBottom: {
marginBottom: 15,
},
columnSegmentedButtons: {
marginBottom: 15,
paddingHorizontal: '2%',
},
hideMediaSwitch: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: '2%',
},
});
const Settings = () => {
const { colors } = useTheme();
const noMedia = useSelector((state: RootState) => state.settings.noMedia);
const masonryColumns = useSelector(
(state: RootState) => state.settings.masonryColumns,
);
const gridColumns = useSelector(
(state: RootState) => state.settings.gridColumns,
);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const storageUri = useSelector(
(state: RootState) => state.settings.storageUri,
)!;
const dispatch = useDispatch();
const realm = useRealm();
const [snackbarMessage, setSnackbarMessage] = useState<string>();
const [
storageLocationChangeDialogVisible,
setStorageLocationChangeDialogVisible,
] = useState(false);
const refreshMemeMetadata = async () => {
const stat = await FileSystem.statDir(storageUri);
const statMap = new Map<string, FileStat>();
stat.forEach(s => statMap.set(s.filename, s));
const memes = realm.objects<Meme>(Meme.schema.name);
realm.write(() => {
memes.forEach(meme => {
const fileStat = statMap.get(meme.filename);
meme.size = fileStat?.size ?? 0;
});
});
setSnackbarMessage('Meme metadata refreshed.');
};
return (
<>
<ScrollView
contentContainerStyle={[
settingsStyles.scrollView,
{ backgroundColor: colors.background },
]}>
<List.Section>
<List.Subheader>Views</List.Subheader>
<Text style={settingsStyles.columnSegmentedButtons}>
Masonry Columns
</Text>
<SegmentedButtons
value={masonryColumns.toString()}
onValueChange={value => {
void dispatch(
setMasonryColumns(Number.parseInt(value) as 1 | 2 | 3 | 4),
);
}}
buttons={[
{ label: '1', value: '1' },
{ label: '2', value: '2' },
{ label: '3', value: '3' },
{ label: '4', value: '4' },
]}
style={settingsStyles.marginBottom}
/>
<Text style={settingsStyles.columnSegmentedButtons}>
Grid Columns
</Text>
<SegmentedButtons
value={gridColumns.toString()}
onValueChange={value => {
void dispatch(
setGridColumns(Number.parseInt(value) as 1 | 2 | 3 | 4),
);
}}
buttons={[
{ label: '1', value: '1' },
{ label: '2', value: '2' },
{ label: '3', value: '3' },
{ label: '4', value: '4' },
]}
/>
</List.Section>
<List.Section>
<List.Subheader>Storage</List.Subheader>
<Button
mode="elevated"
style={settingsStyles.marginBottom}
onPress={() => setStorageLocationChangeDialogVisible(true)}>
Change Storage Location
</Button>
<Button
mode="elevated"
style={settingsStyles.marginBottom}
onPress={refreshMemeMetadata}>
Refresh Meme Metadata
</Button>
<View style={settingsStyles.hideMediaSwitch}>
<Text>Hide media from gallery</Text>
<Switch
value={noMedia}
onValueChange={value => {
void dispatch(setNoMedia(value));
}}
/>
</View>
</List.Section>
</ScrollView>
<Portal>
<Portal>
<StorageLocationChangeDialog
visible={storageLocationChangeDialogVisible}
setVisible={setStorageLocationChangeDialogVisible}
setSnackbarMessage={setSnackbarMessage}
/>
</Portal>
<Snackbar
visible={!!snackbarMessage}
// eslint-disable-next-line unicorn/no-useless-undefined
onDismiss={() => setSnackbarMessage(undefined)}
style={settingsStyles.snackbar}
action={{
label: 'Dismiss',
// eslint-disable-next-line unicorn/no-useless-undefined
onPress: () => setSnackbarMessage(undefined),
}}>
{snackbarMessage}
</Snackbar>
</Portal>
</>
);
};
export default Settings;