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/settings.tsx
Nikolaos Karaolidis d2054b028a Reorganize files
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2023-08-01 14:53:10 +03:00

199 lines
5.7 KiB
TypeScript

import React, { useState } from 'react';
import { ScrollView, StyleSheet, View } from 'react-native';
import {
Button,
List,
Portal,
SegmentedButtons,
Switch,
Text,
useTheme,
} from 'react-native-paper';
import { useDispatch, useSelector } from 'react-redux';
import type {} from 'redux-thunk/extend-redux';
import { useRealm } from '@realm/react';
import { FileSystem, FileStat } from 'react-native-file-access';
import {
RootState,
setAutofocusMemesSearch,
setAutofocusTagsSearch,
setGridColumns,
setMasonryColumns,
setNoMedia,
setSnackbarMessage,
} from '../../state';
import { Meme } from '../../database';
import StorageLocationChangeDialog from './storageLocationChangeDialog';
const settingsStyles = StyleSheet.create({
scrollView: {
paddingHorizontal: '4%',
},
marginBottom: {
marginBottom: 15,
},
columnSegmentedButtons: {
marginBottom: 15,
paddingHorizontal: '2%',
},
autoFocusSwitch: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: '2%',
marginBottom: 15,
},
hideMediaSwitch: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: '2%',
},
});
const Settings = () => {
const { colors } = useTheme();
const noMedia = useSelector((state: RootState) => state.settings.noMedia);
const autoFocusMemesSearch = useSelector(
(state: RootState) => state.settings.autoFocusMemesSearch,
);
const autoFocusTagsSearch = useSelector(
(state: RootState) => state.settings.autoFocusTagsSearch,
);
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 [
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;
});
});
dispatch(setSnackbarMessage('Meme metadata refreshed.'));
};
return (
<>
<ScrollView
contentContainerStyle={[
settingsStyles.scrollView,
{ backgroundColor: colors.background },
]}>
<List.Section>
<List.Subheader>Views</List.Subheader>
<View style={settingsStyles.autoFocusSwitch}>
<Text>Autofocus Memes Searchbar</Text>
<Switch
value={autoFocusMemesSearch}
onValueChange={value => {
void dispatch(setAutofocusMemesSearch(value));
}}
/>
</View>
<View style={settingsStyles.autoFocusSwitch}>
<Text>Autofocus Tags Searchbar</Text>
<Switch
value={autoFocusTagsSearch}
onValueChange={value => {
void dispatch(setAutofocusTagsSearch(value));
}}
/>
</View>
<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>
<StorageLocationChangeDialog
visible={storageLocationChangeDialogVisible}
setVisible={setStorageLocationChangeDialogVisible}
setSnackbarMessage={message => {
dispatch(setSnackbarMessage(message));
}}
/>
</Portal>
</>
);
};
export default Settings;