feat: Add Settings and Translations (#548)

* started setting repositioning

* started setting repositioning

* added novel badges and sort to general + some js to ts

* translations General

* readersettingsscreen + fix font style selection in Bottomsheet

* started setting repositioning

* added novel badges and sort to general + some js to ts

* translations General

* readersettingsscreen + fix font style selection in Bottomsheet

* update

* ts map

* small fix
This commit is contained in:
Patrick Loser
2023-02-17 17:09:30 +01:00
committed by GitHub
parent f238b20f6d
commit 0abdff25eb
15 changed files with 778 additions and 325 deletions
-49
View File
@@ -1,49 +0,0 @@
import React from 'react';
import { Pressable, StyleSheet, View, Text } from 'react-native';
import color from 'color';
import { Switch, List } from 'react-native-paper';
const SwitchSetting = ({ label, description, onPress, theme, icon, value }) => (
<Pressable
android_ripple={{ color: color(theme.primary).alpha(0.12).rgb().string() }}
style={[styles.container, { paddingVertical: description ? 16 : 12 }]}
onPress={onPress}
>
<View style={{ flexDirection: 'row', flex: 1 }}>
{icon && (
<List.Icon color={theme.primary} icon={icon} style={{ margin: 0 }} />
)}
<View style={[icon && { marginLeft: 16 }]}>
<Text
style={{
color: theme.textColorPrimary,
fontSize: 16,
flex: 1,
textAlignVertical: 'center',
}}
>
{label}
</Text>
{description && (
<Text style={{ color: theme.textColorSecondary }}>{description}</Text>
)}
</View>
</View>
<Switch
value={value}
onValueChange={onPress}
color={theme.primary}
style={{ marginLeft: 8 }}
/>
</Pressable>
);
export default SwitchSetting;
const styles = StyleSheet.create({
container: {
paddingHorizontal: 16,
flexDirection: 'row',
justifyContent: 'space-between',
},
});
+82
View File
@@ -0,0 +1,82 @@
import React from 'react';
import { Pressable, StyleSheet, View, Text } from 'react-native';
import color from 'color';
import { Switch, List } from 'react-native-paper';
import { MD3ThemeType } from '@theme/types';
interface SwitchProps {
label: string;
description?: string;
onPress: () => void;
theme: MD3ThemeType;
icon?: string;
value: boolean;
}
const SwitchSetting: React.FC<SwitchProps> = ({
label,
description,
onPress,
theme,
icon,
value,
}) => {
const styles = StyleSheet.create({
container: {
paddingHorizontal: 16,
flexDirection: 'row',
justifyContent: 'space-between',
paddingVertical: description ? 16 : 12,
},
row: {
flexDirection: 'row',
flex: 1,
},
icon: {
margin: 0,
},
textContainer: {
marginLeft: icon && 16,
},
text: {
fontSize: 16,
flex: 1,
textAlignVertical: 'center',
},
switch: { marginLeft: 8 },
});
return (
<Pressable
android_ripple={{
color: color(theme.primary).alpha(0.12).rgb().string(),
}}
style={styles.container}
onPress={onPress}
>
<View style={styles.row}>
{icon && (
<List.Icon color={theme.primary} icon={icon} style={styles.icon} />
)}
<View style={styles.textContainer}>
<Text style={[styles.text, { color: theme.textColorPrimary }]}>
{label}
</Text>
{description && (
<Text style={{ color: theme.textColorSecondary }}>
{description}
</Text>
)}
</View>
</View>
<Switch
value={value}
onValueChange={onPress}
color={theme.primary}
style={styles.switch}
/>
</Pressable>
);
};
export default SwitchSetting;
+1 -1
View File
@@ -9,7 +9,7 @@ import TrackerSettings from '../screens/settings/SettingsTrackerScreen';
import ReaderSettings from '../screens/settings/SettingsReaderScreen/SettingsReaderScreen';
import BackupSettings from '../screens/settings/SettingsBackupScreen';
import AdvancedSettings from '../screens/settings/SettingsAdvancedScreen';
import GeneralSettings from '../screens/settings/SettingsGeneralScreen';
import GeneralSettings from '../screens/settings/SettingsGeneralScreen/SettingsGeneralScreen';
import DownloadQueue from '../screens/more/DownloadQueueScreen';
import Downloads from '../screens/more/DownloadsScreen';
import AppearanceSettings from '../screens/settings/SettingsAppearanceScreen';
+5 -5
View File
@@ -44,27 +44,27 @@ export enum LibrarySortOrder {
export const librarySortOrderList = [
{
label: 'Alphabetically',
label: getString('libraryScreen.bottomSheet.sortOrders.alphabetically'),
ASC: LibrarySortOrder.Alphabetically_ASC,
DESC: LibrarySortOrder.Alphabetically_DESC,
},
{
label: 'Last Read',
label: getString('libraryScreen.bottomSheet.sortOrders.lastRead'),
ASC: LibrarySortOrder.LastRead_ASC,
DESC: LibrarySortOrder.LastRead_DESC,
},
{
label: 'Unread',
label: getString('libraryScreen.bottomSheet.sortOrders.unread'),
ASC: LibrarySortOrder.Unread_ASC,
DESC: LibrarySortOrder.Unread_DESC,
},
{
label: 'Downloaded',
label: getString('libraryScreen.bottomSheet.sortOrders.download'),
ASC: LibrarySortOrder.Downloaded_ASC,
DESC: LibrarySortOrder.Downloaded_DESC,
},
{
label: 'Total chapters',
label: getString('libraryScreen.bottomSheet.sortOrders.totalChapters'),
ASC: LibrarySortOrder.TotalChapters_ASC,
DESC: LibrarySortOrder.TotalChapters_DESC,
},
@@ -99,7 +99,7 @@ const GeneralTab: React.FC = () => {
theme={theme}
/>
<ReaderSheetPreferenceItem
label={'Remove extra paragraph spacing'}
label={getString('readerScreen.bottomSheet.removeExtraSpacing')}
onPress={() =>
dispatch(
setAppSettings(
@@ -112,7 +112,7 @@ const GeneralTab: React.FC = () => {
theme={theme}
/>
<ReaderSheetPreferenceItem
label={'Volume buttons scroll'}
label={getString('readerScreen.bottomSheet.volumeButtonsScroll')}
onPress={() =>
dispatch(setAppSettings('useVolumeButtons', !useVolumeButtons))
}
@@ -1,5 +1,5 @@
import React from 'react';
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import color from 'color';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
@@ -9,6 +9,7 @@ import { useTheme } from '@hooks/useTheme';
import { setReaderSettings } from '../../../../redux/settings/settings.actions';
import { Font, readerFonts } from '../../../../utils/constants/readerConstants';
import { FlatList } from 'react-native-gesture-handler';
const ReaderFontPicker = () => {
const dispatch = useAppDispatch();
@@ -23,61 +24,66 @@ const ReaderFontPicker = () => {
<Text style={[{ color: theme.textColorSecondary }, styles.title]}>
{getString('readerScreen.bottomSheet.fontStyle')}
</Text>
<ScrollView
<FlatList
data={readerFonts}
renderItem={FontChipItem}
horizontal={true}
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.scrollContainer}
>
{readerFonts.map(item => (
<View
key={item.fontFamily}
style={[
styles.container,
{
backgroundColor: theme.surfaceVariant,
},
]}
>
<Pressable
style={styles.content}
onPress={() =>
dispatch(setReaderSettings('fontFamily', item.fontFamily))
}
android_ripple={{
color: color(theme.primary).alpha(0.12).string(),
}}
>
{isSelected(item) ? (
<MaterialCommunityIcons
name="check"
color={theme.primary}
size={16}
/>
) : null}
<Text
style={[
styles.label,
{
fontFamily: item.fontFamily,
color: isSelected(item)
? theme.primary
: theme.textColorPrimary,
},
isSelected(item) && styles.mLeft,
]}
>
{item.name}
</Text>
</Pressable>
</View>
))}
</ScrollView>
/>
</View>
);
interface FontChipProps {
item: Font;
}
function FontChipItem({ item }: FontChipProps) {
return (
<View
key={item.fontFamily}
style={[
styles.container,
{
backgroundColor: theme.surfaceVariant,
},
]}
>
<Pressable
style={styles.content}
onPress={() =>
dispatch(setReaderSettings('fontFamily', item.fontFamily))
}
android_ripple={{
color: color(theme.primary).alpha(0.12).string(),
}}
>
{isSelected(item) ? (
<MaterialCommunityIcons
name="check"
color={theme.primary}
size={16}
/>
) : null}
<Text
style={[
styles.label,
{
fontFamily: item.fontFamily,
color: isSelected(item)
? theme.primary
: theme.textColorPrimary,
},
isSelected(item) && styles.mLeft,
]}
>
{item.name}
</Text>
</Pressable>
</View>
);
}
};
export default ReaderFontPicker;
const styles = StyleSheet.create({
container: {
borderRadius: 8,
@@ -85,12 +91,13 @@ const styles = StyleSheet.create({
marginHorizontal: 6,
},
content: {
flexGrow: 1,
flexDirection: 'row',
alignItems: 'center',
borderRadius: 8,
paddingVertical: 4,
paddingVertical: 1,
justifyContent: 'center',
paddingHorizontal: 10,
minHeight: 32,
alignItems: 'center',
},
row: {
flexDirection: 'row',
@@ -102,9 +109,6 @@ const styles = StyleSheet.create({
title: {
marginRight: 16,
},
scrollContainer: {
alignItems: 'center',
},
label: {
fontSize: 16,
},
@@ -1,192 +0,0 @@
import React from 'react';
import { ScrollView } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import SwitchSetting from '../../components/Switch/Switch';
import DisplayModeModal from '../more/components/DisplayModeModal';
import GridSizeModal from '../more/components/GridSizeModal';
import { useSettings } from '../../hooks/reduxHooks';
import { useTheme } from '@hooks/useTheme';
import { setAppSettings } from '../../redux/settings/settings.actions';
import { SHOW_LAST_UPDATE_TIME } from '../../redux/updates/updates.types';
import DefaultChapterSortModal from './components/DefaultChapterSortModal';
import {
DisplayModes,
displayModesList,
} from '@screens/library/constants/constants';
import { useLibrarySettings } from '@hooks/useSettings';
import useBoolean from '@hooks/useBoolean';
import { Appbar, List } from '@components';
const GenralSettings = ({ navigation }) => {
const theme = useTheme();
const dispatch = useDispatch();
const { displayMode = DisplayModes.Comfortable, novelsPerRow = 3 } =
useLibrarySettings();
const {
updateLibraryOnLaunch = false,
downloadNewChapters = false,
onlyUpdateOngoingNovels = false,
defaultChapterSort = 'ORDER BY chapterId ASC',
refreshNovelMetadata = false,
disableHapticFeedback = false,
useLibraryFAB = false,
} = useSettings();
const { showLastUpdateTime = true } = useSelector(
state => state.updatesReducer,
);
/**
* Display Mode Modal
*/
const displayModalRef = useBoolean();
/**
* Grid Size Modal
*/
const gridSizeModalRef = useBoolean();
const defaultChapterSortModal = useBoolean();
return (
<>
<Appbar title="General" handleGoBack={navigation.goBack} theme={theme} />
<ScrollView contentContainerStyle={{ paddingBottom: 32 }}>
<List.Section>
<List.SubHeader theme={theme}>Display</List.SubHeader>
<List.Item
title="Display Mode"
description={displayModesList[displayMode].label}
onPress={displayModalRef.setTrue}
theme={theme}
/>
<List.Item
title="Items per row in library"
description={`${novelsPerRow} items per row`}
onPress={gridSizeModalRef.setTrue}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>Library</List.SubHeader>
<SwitchSetting
label="Update library on launch"
value={updateLibraryOnLaunch}
onPress={() =>
dispatch(
setAppSettings('updateLibraryOnLaunch', !updateLibraryOnLaunch),
)
}
theme={theme}
/>
<SwitchSetting
label="Use FAB in Library"
value={useLibraryFAB}
onPress={() =>
dispatch(setAppSettings('useLibraryFAB', !useLibraryFAB))
}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>Novel</List.SubHeader>
<List.Item
title="Default chapter sort"
description={`By source ${
defaultChapterSort === 'ORDER BY chapterId ASC'
? '(Ascending)'
: '(Descending)'
}`}
onPress={defaultChapterSortModal.setTrue}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>Global update</List.SubHeader>
<SwitchSetting
label="Only update ongoing novels"
value={onlyUpdateOngoingNovels}
onPress={() =>
dispatch(
setAppSettings(
'onlyUpdateOngoingNovels',
!onlyUpdateOngoingNovels,
),
)
}
theme={theme}
/>
<SwitchSetting
label="Automatically refresh metadata"
description="Check for new cover and details when updating library"
value={refreshNovelMetadata}
onPress={() =>
dispatch(
setAppSettings('refreshNovelMetadata', !refreshNovelMetadata),
)
}
theme={theme}
/>
<SwitchSetting
label="Show last update time"
value={showLastUpdateTime}
onPress={() =>
dispatch({
type: SHOW_LAST_UPDATE_TIME,
payload: !showLastUpdateTime,
})
}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>Auto-download</List.SubHeader>
<SwitchSetting
label="Download new chapters"
value={downloadNewChapters}
onPress={() =>
dispatch(
setAppSettings('downloadNewChapters', !downloadNewChapters),
)
}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>General</List.SubHeader>
<SwitchSetting
label="Disable haptic feedback"
value={disableHapticFeedback}
onPress={() =>
dispatch(
setAppSettings('disableHapticFeedback', !disableHapticFeedback),
)
}
theme={theme}
/>
</List.Section>
</ScrollView>
<DisplayModeModal
displayMode={displayMode}
displayModalVisible={displayModalRef.value}
hideDisplayModal={displayModalRef.setFalse}
theme={theme}
/>
<DefaultChapterSortModal
defaultChapterSort={defaultChapterSort}
displayModalVisible={defaultChapterSortModal.value}
hideDisplayModal={defaultChapterSortModal.setFalse}
dispatch={dispatch}
theme={theme}
/>
<GridSizeModal
novelsPerRow={novelsPerRow}
gridSizeModalVisible={gridSizeModalRef.value}
hideGridSizeModal={gridSizeModalRef.setFalse}
theme={theme}
/>
</>
);
};
export default GenralSettings;
@@ -0,0 +1,328 @@
import React from 'react';
import { ScrollView } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import SwitchSetting from '../../../components/Switch/Switch';
import DisplayModeModal from './modals/DisplayModeModal';
import GridSizeModal from './modals/GridSizeModal';
import { useSettings } from '../../../hooks/reduxHooks';
import { useTheme } from '@hooks/useTheme';
import { setAppSettings } from '../../../redux/settings/settings.actions';
import { SHOW_LAST_UPDATE_TIME } from '../../../redux/updates/updates.types';
import DefaultChapterSortModal from '../components/DefaultChapterSortModal';
import {
DisplayModes,
displayModesList,
LibrarySortOrder,
} from '@screens/library/constants/constants';
import { useLibrarySettings } from '@hooks/useSettings';
import useBoolean from '@hooks/useBoolean';
import { Appbar, List } from '@components';
import NovelSortModal from './modals/NovelSortModal';
import NovelBadgesModal from './modals/NovelBadgesModal';
import { RootState } from '@redux/store';
import { NavigationState } from '@react-navigation/native';
import { getString } from '@strings/translations';
interface GenralSettingsProps {
navigation: NavigationState;
}
const GenralSettings: React.FC<GenralSettingsProps> = ({ navigation }) => {
const theme = useTheme();
const dispatch = useDispatch();
const {
displayMode = DisplayModes.Comfortable,
novelsPerRow = 3,
showDownloadBadges = true,
showNumberOfNovels = false,
showUnreadBadges = true,
sortOrder = LibrarySortOrder.DateAdded_DESC,
} = useLibrarySettings();
const sortOrderDisplay: string[] = sortOrder.split(' ');
const sortOrderNameMap = new Map<string, string>([
['lastReadAt', 'libraryScreen.bottomSheet.sortOrders.lastRead'],
['novels.novelName', 'libraryScreen.bottomSheet.sortOrders.alphabetically'],
['novels.unread', 'libraryScreen.bottomSheet.sortOrders.unread'],
['chaptersDownloaded', 'libraryScreen.bottomSheet.sortOrders.download'],
['novelId', 'libraryScreen.bottomSheet.sortOrders.dateAdded'],
['chaptersUnread', 'libraryScreen.bottomSheet.sortOrders.totalChapters'],
]);
const {
updateLibraryOnLaunch = false,
downloadNewChapters = false,
onlyUpdateOngoingNovels = false,
defaultChapterSort = 'ORDER BY chapterId ASC',
refreshNovelMetadata = false,
disableHapticFeedback = false,
useLibraryFAB = false,
} = useSettings();
const { showLastUpdateTime = true } = useSelector(
(state: RootState) => state.updatesReducer,
);
const generateNovelBadgesDescription = () => {
let res = [];
if (showDownloadBadges) {
res.push('Download');
}
if (showUnreadBadges) {
res.push('Unread');
}
if (showNumberOfNovels) {
res.push('Number of Items');
}
return res.join(', ');
};
/**
* Display Mode Modal
*/
const displayModalRef = useBoolean();
/**
* Grid Size Modal
*/
const gridSizeModalRef = useBoolean();
/**
* Novel Badges Modal
*/
const novelBadgesModalRef = useBoolean();
const novelBadgesDescription = generateNovelBadgesDescription();
/**
* Novel Sort Modal
*/
const novelSortModalRef = useBoolean();
/**
* Chapter Sort Modal
*/
const defaultChapterSortModal = useBoolean();
return (
<>
<Appbar
title={getString('moreScreen.settingsScreen.generalSettings')}
// @ts-ignore
handleGoBack={navigation.goBack}
theme={theme}
/>
<ScrollView contentContainerStyle={{ paddingBottom: 32 }}>
<List.Section>
<List.SubHeader theme={theme}>
{getString(
'moreScreen.settingsScreen.generalSettingsScreen.display',
)}
</List.SubHeader>
<List.Item
title={getString(
'moreScreen.settingsScreen.generalSettingsScreen.displayMode',
)}
description={displayModesList[displayMode].label}
onPress={displayModalRef.setTrue}
theme={theme}
/>
<List.Item
title={getString(
'moreScreen.settingsScreen.generalSettingsScreen.itemsPerRowLibrary',
)}
description={
novelsPerRow +
' ' +
getString(
'moreScreen.settingsScreen.generalSettingsScreen.itemsPerRow',
)
}
onPress={gridSizeModalRef.setTrue}
theme={theme}
/>
<List.Item
title={getString(
'moreScreen.settingsScreen.generalSettingsScreen.novelBadges',
)}
// @ts-ignore
description={novelBadgesDescription}
onPress={novelBadgesModalRef.setTrue}
theme={theme}
/>
<List.Item
title={getString(
'moreScreen.settingsScreen.generalSettingsScreen.novelSort',
)}
description={
// @ts-ignore
getString(sortOrderNameMap.get(sortOrderDisplay[0])) +
' ' +
sortOrderDisplay[1]
}
onPress={novelSortModalRef.setTrue}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>{getString('library')}</List.SubHeader>
<SwitchSetting
label={getString(
'moreScreen.settingsScreen.generalSettingsScreen.updateLibrary',
)}
value={updateLibraryOnLaunch}
onPress={() =>
dispatch(
setAppSettings('updateLibraryOnLaunch', !updateLibraryOnLaunch),
)
}
theme={theme}
/>
<SwitchSetting
label={getString(
'moreScreen.settingsScreen.generalSettingsScreen.useFAB',
)}
value={useLibraryFAB}
onPress={() =>
dispatch(setAppSettings('useLibraryFAB', !useLibraryFAB))
}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>
{getString('moreScreen.settingsScreen.generalSettingsScreen.novel')}
</List.SubHeader>
<List.Item
title={getString(
'moreScreen.settingsScreen.generalSettingsScreen.chapterSort',
)}
description={`By source ${
defaultChapterSort === 'ORDER BY chapterId ASC'
? getString(
'moreScreen.settingsScreen.generalSettingsScreen.asc',
)
: getString(
'moreScreen.settingsScreen.generalSettingsScreen.desc',
)
}`}
onPress={defaultChapterSortModal.setTrue}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>
{getString(
'moreScreen.settingsScreen.generalSettingsScreen.globalUpdate',
)}
</List.SubHeader>
<SwitchSetting
label={getString(
'moreScreen.settingsScreen.generalSettingsScreen.updateOngoing',
)}
value={onlyUpdateOngoingNovels}
onPress={() =>
dispatch(
setAppSettings(
'onlyUpdateOngoingNovels',
!onlyUpdateOngoingNovels,
),
)
}
theme={theme}
/>
<SwitchSetting
label={getString(
'moreScreen.settingsScreen.generalSettingsScreen.refreshMetadata',
)}
description={getString(
'moreScreen.settingsScreen.generalSettingsScreen.refreshMetadataDescription',
)}
value={refreshNovelMetadata}
onPress={() =>
dispatch(
setAppSettings('refreshNovelMetadata', !refreshNovelMetadata),
)
}
theme={theme}
/>
<SwitchSetting
label={getString(
'moreScreen.settingsScreen.generalSettingsScreen.updateTime',
)}
value={showLastUpdateTime}
onPress={() =>
dispatch({
type: SHOW_LAST_UPDATE_TIME,
payload: !showLastUpdateTime,
})
}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>
{getString(
'moreScreen.settingsScreen.generalSettingsScreen.autoDownload',
)}
</List.SubHeader>
<SwitchSetting
label={getString(
'moreScreen.settingsScreen.generalSettingsScreen.downloadNewChapters',
)}
value={downloadNewChapters}
onPress={() =>
dispatch(
setAppSettings('downloadNewChapters', !downloadNewChapters),
)
}
theme={theme}
/>
<List.Divider theme={theme} />
<List.SubHeader theme={theme}>
{getString('moreScreen.settingsScreen.generalSettings')}
</List.SubHeader>
<SwitchSetting
label={getString(
'moreScreen.settingsScreen.generalSettingsScreen.disableHapticFeedback',
)}
value={disableHapticFeedback}
onPress={() =>
dispatch(
setAppSettings('disableHapticFeedback', !disableHapticFeedback),
)
}
theme={theme}
/>
</List.Section>
</ScrollView>
<DisplayModeModal
displayMode={displayMode}
displayModalVisible={displayModalRef.value}
hideDisplayModal={displayModalRef.setFalse}
theme={theme}
/>
<DefaultChapterSortModal
defaultChapterSort={defaultChapterSort}
displayModalVisible={defaultChapterSortModal.value}
hideDisplayModal={defaultChapterSortModal.setFalse}
dispatch={dispatch}
theme={theme}
/>
<GridSizeModal
novelsPerRow={novelsPerRow}
gridSizeModalVisible={gridSizeModalRef.value}
hideGridSizeModal={gridSizeModalRef.setFalse}
theme={theme}
/>
<NovelBadgesModal
novelBadgesModalVisible={novelBadgesModalRef.value}
hideNovelBadgesModal={novelBadgesModalRef.setFalse}
theme={theme}
/>
<NovelSortModal
novelSortModalVisible={novelSortModalRef.value}
hideNovelSortModal={novelSortModalRef.setFalse}
theme={theme}
/>
</>
);
};
export default GenralSettings;
@@ -1,13 +1,24 @@
import { displayModesList } from '@screens/library/constants/constants';
import {
DisplayModes,
displayModesList,
} from '@screens/library/constants/constants';
import React from 'react';
import { StyleSheet } from 'react-native';
import { Text, StyleSheet } from 'react-native';
import { Portal, Modal, overlay } from 'react-native-paper';
import { RadioButton } from '../../../components/RadioButton/RadioButton';
import { RadioButton } from '../../../../components/RadioButton/RadioButton';
import { useLibrarySettings } from '@hooks/useSettings';
import { MD3ThemeType } from '@theme/types';
const DisplayModeModal = ({
interface DisplayModeModalProps {
displayMode: DisplayModes;
displayModalVisible: boolean;
hideDisplayModal: () => void;
theme: MD3ThemeType;
}
const DisplayModeModal: React.FC<DisplayModeModalProps> = ({
theme,
displayMode,
hideDisplayModal,
@@ -25,6 +36,9 @@ const DisplayModeModal = ({
{ backgroundColor: overlay(2, theme.surface) },
]}
>
<Text style={[styles.modalHeader, { color: theme.textColorPrimary }]}>
Display Mode
</Text>
{displayModesList.map(mode => (
<RadioButton
key={mode.value}
@@ -47,4 +61,9 @@ const styles = StyleSheet.create({
margin: 20,
borderRadius: 28,
},
modalHeader: {
paddingHorizontal: 24,
fontSize: 24,
marginBottom: 10,
},
});
@@ -3,11 +3,19 @@ import { Text, StyleSheet } from 'react-native';
import { Portal, Modal, overlay } from 'react-native-paper';
import { RadioButton } from '../../../components/RadioButton/RadioButton';
import { RadioButton } from '../../../../components/RadioButton/RadioButton';
import { useLibrarySettings } from '@hooks/useSettings';
import { MD3ThemeType } from '@theme/types';
const GridSizeModal = ({
interface GridSizeModalProps {
novelsPerRow: number;
gridSizeModalVisible: boolean;
hideGridSizeModal: () => void;
theme: MD3ThemeType;
}
const GridSizeModal: React.FC<GridSizeModalProps> = ({
novelsPerRow,
gridSizeModalVisible,
hideGridSizeModal,
@@ -41,16 +49,20 @@ const GridSizeModal = ({
>
{`${novelsPerRow} per row`}
</Text>
{Object.keys(gridSizes).map(item => (
<RadioButton
key={item}
status={item == novelsPerRow}
label={gridSizes[item]}
onPress={() => setLibrarySettings({ novelsPerRow: item })}
theme={theme}
style={{ paddingHorizontal: 20 }}
/>
))}
{Object.keys(gridSizes).map(item => {
let it = Number(item);
return (
<RadioButton
key={item}
status={it === novelsPerRow}
// @ts-ignore
label={gridSizes[it]}
onPress={() => setLibrarySettings({ novelsPerRow: it })}
theme={theme}
style={styles.radiobutton}
/>
);
})}
</Modal>
</Portal>
);
@@ -78,4 +90,5 @@ const styles = StyleSheet.create({
width: '100%',
height: 40,
},
radiobutton: { paddingHorizontal: 20 },
});
@@ -0,0 +1,102 @@
import React from 'react';
import { Text, StyleSheet } from 'react-native';
import { Portal, Modal, overlay } from 'react-native-paper';
import { useLibrarySettings } from '@hooks/useSettings';
import { Checkbox } from '@components';
import { getString } from '@strings/translations';
import { MD3ThemeType } from '@theme/types';
interface NovelBadgesModalProps {
novelBadgesModalVisible: boolean;
hideNovelBadgesModal: () => void;
theme: MD3ThemeType;
}
const NovelBadgesModal: React.FC<NovelBadgesModalProps> = ({
novelBadgesModalVisible,
hideNovelBadgesModal,
theme,
}) => {
const {
showDownloadBadges = true,
showNumberOfNovels = false,
showUnreadBadges = true,
setLibrarySettings,
} = useLibrarySettings();
return (
<Portal>
<Modal
visible={novelBadgesModalVisible}
onDismiss={hideNovelBadgesModal}
contentContainerStyle={[
styles.container,
{ backgroundColor: overlay(2, theme.surface) },
]}
>
<Text style={[styles.modalHeader, { color: theme.textColorPrimary }]}>
{getString('libraryScreen.bottomSheet.display.badges')}
</Text>
<Checkbox
label={getString('libraryScreen.bottomSheet.display.downloadBadges')}
status={showDownloadBadges}
onPress={() =>
setLibrarySettings({
showDownloadBadges: !showDownloadBadges,
})
}
theme={theme}
/>
<Checkbox
label={getString('libraryScreen.bottomSheet.display.unreadBadges')}
status={showUnreadBadges}
onPress={() =>
setLibrarySettings({
showUnreadBadges: !showUnreadBadges,
})
}
theme={theme}
/>
<Checkbox
label={getString('libraryScreen.bottomSheet.display.showNoOfItems')}
status={showNumberOfNovels}
onPress={() =>
setLibrarySettings({
showNumberOfNovels: !showNumberOfNovels,
})
}
theme={theme}
/>
</Modal>
</Portal>
);
};
export default NovelBadgesModal;
const styles = StyleSheet.create({
container: {
paddingVertical: 24,
margin: 20,
borderRadius: 28,
},
modalHeader: {
paddingHorizontal: 24,
fontSize: 24,
marginBottom: 10,
},
modalDescription: {
paddingHorizontal: 24,
fontSize: 16,
marginBottom: 16,
},
slider: {
width: '100%',
height: 40,
},
sectionHeader: {
padding: 16,
paddingBottom: 8,
},
});
@@ -0,0 +1,92 @@
import React from 'react';
import { Text, StyleSheet } from 'react-native';
import { Portal, Modal, overlay } from 'react-native-paper';
import { useLibrarySettings } from '@hooks/useSettings';
import {
LibrarySortOrder,
librarySortOrderList,
} from '@screens/library/constants/constants';
import { MD3ThemeType } from '@theme/types';
import { FlashList } from '@shopify/flash-list';
import { SortItem } from '@components/Checkbox/Checkbox';
interface NovelSortModalProps {
novelSortModalVisible: boolean;
hideNovelSortModal: () => void;
theme: MD3ThemeType;
}
const NovelSortModal: React.FC<NovelSortModalProps> = ({
novelSortModalVisible,
hideNovelSortModal,
theme,
}) => {
const { sortOrder = LibrarySortOrder.DateAdded_DESC, setLibrarySettings } =
useLibrarySettings();
return (
<Portal>
<Modal
visible={novelSortModalVisible}
onDismiss={hideNovelSortModal}
contentContainerStyle={[
styles.container,
{ backgroundColor: overlay(2, theme.surface) },
]}
>
<Text style={[styles.modalHeader, { color: theme.textColorPrimary }]}>
Sort Order
</Text>
<FlashList
data={librarySortOrderList}
extraData={[sortOrder]}
estimatedItemSize={6}
renderItem={({ item }) => (
<SortItem
label={item.label}
theme={theme}
status={
sortOrder === item.ASC
? 'asc'
: sortOrder === item.DESC
? 'desc'
: undefined
}
onPress={() =>
setLibrarySettings({
sortOrder: sortOrder === item.ASC ? item.DESC : item.ASC,
})
}
/>
)}
/>
</Modal>
</Portal>
);
};
export default NovelSortModal;
const styles = StyleSheet.create({
container: {
paddingVertical: 24,
margin: 20,
borderRadius: 28,
height: 397.8,
},
modalHeader: {
paddingHorizontal: 24,
fontSize: 24,
marginBottom: 10,
},
modalDescription: {
paddingHorizontal: 24,
fontSize: 16,
marginBottom: 16,
},
slider: {
width: '100%',
height: 40,
},
});
@@ -185,7 +185,7 @@ const SettingsReaderScreen = () => {
theme={theme}
/>
<SwitchItem
label={'Volume buttons scroll'}
label={getString('readerScreen.bottomSheet.volumeButtonsScroll')}
value={useVolumeButtons}
onPress={() =>
dispatch(setAppSettings('useVolumeButtons', !useVolumeButtons))
@@ -202,7 +202,7 @@ const SettingsReaderScreen = () => {
/>
{swipeGestures ? (
<SwitchItem
label={'Show swipe margins'}
label={getString('readerScreen.bottomSheet.showSwipeMargins')}
value={showSwipeMargins}
theme={theme}
onPress={() =>
+31 -3
View File
@@ -33,7 +33,10 @@
"sortOrders": {
"dateAdded": "Date added",
"alphabetically": "Alphabetically",
"totalChapters": "Total chapters"
"totalChapters": "Total chapters",
"download": "Downloaded",
"unread": "Unread",
"lastRead": "Last Read"
},
"display": {
"displayMode": "Display mode",
@@ -88,7 +91,10 @@
"showProgressPercentage": "Show progress percentage",
"swipeGestures": "Swipe left or right to navigate between chapters",
"allowTextSelection": "Allow text selection",
"useChapterDrawerSwipeNavigation": "Swipe right to open drawer"
"useChapterDrawerSwipeNavigation": "Swipe right to open drawer",
"removeExtraSpacing":"Remove extra paragraph spacing",
"volumeButtonsScroll":"Volume buttons scroll",
"showSwipeMargins": "Show swipe margins"
},
"drawer": {
"scrollToCurrentChapter": "Scroll to current chapter",
@@ -124,7 +130,29 @@
"settings": "Settings",
"settingsScreen": {
"generalSettings": "General",
"generalSettingsScreen": {},
"generalSettingsScreen": {
"display": "Display",
"displayMode": "Display Mode",
"itemsPerRow":"Items per row",
"itemsPerRowLibrary":"Items per row in library",
"novelBadges":"Novel Badges",
"novelSort":"Novel Sort",
"updateLibrary":"Update library on launch",
"useFAB":"Use FAB in Library",
"novel": "Novel",
"chapterSort": "Default chapter sort",
"bySource": "By source",
"asc": "(Ascending)",
"desc":"(Descending)",
"globalUpdate": "Global update",
"updateOngoing": "Only update ongoing novels",
"refreshMetadata":"Automatically refresh metadata",
"refreshMetadataDescription":"Check for new cover and details when updating library",
"updateTime":"Show last update time",
"autoDownload":"Auto-download",
"downloadNewChapters":"Download new chapters",
"disableHapticFeedback": "Disable haptic feedback"
},
"readerSettings": {
"title": "Reader",
"readerTheme": "Reader theme",
+26
View File
@@ -31,6 +31,9 @@ export interface StringMap {
'libraryScreen.bottomSheet.sortOrders.dateAdded': 'string';
'libraryScreen.bottomSheet.sortOrders.alphabetically': 'string';
'libraryScreen.bottomSheet.sortOrders.totalChapters': 'string';
'libraryScreen.bottomSheet.sortOrders.lastRead': 'string';
'libraryScreen.bottomSheet.sortOrders.unread': 'string';
'libraryScreen.bottomSheet.sortOrders.download': 'string';
'libraryScreen.bottomSheet.display.displayMode': 'string';
'libraryScreen.bottomSheet.display.compact': 'string';
'libraryScreen.bottomSheet.display.comfortable': 'string';
@@ -73,6 +76,9 @@ export interface StringMap {
'readerScreen.bottomSheet.swipeGestures': 'string';
'readerScreen.bottomSheet.allowTextSelection': 'string';
'readerScreen.bottomSheet.useChapterDrawerSwipeNavigation': 'string';
'readerScreen.bottomSheet.removeExtraSpacing': 'string';
'readerScreen.bottomSheet.volumeButtonsScroll': 'string';
'readerScreen.bottomSheet.showSwipeMargins': 'string';
'readerScreen.drawer.scrollToCurrentChapter': 'string';
'readerScreen.drawer.scrollToTop': 'string';
'readerScreen.drawer.scrollToBottom': 'string';
@@ -94,6 +100,26 @@ export interface StringMap {
'more': 'string';
'moreScreen.settings': 'string';
'moreScreen.settingsScreen.generalSettings': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.display': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.displayMode': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.itemsPerRowLibrary': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.itemsPerRow': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.novelBadges': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.novelSort': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.updateLibrary': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.useFAB': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.novel': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.chapterSort': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.asc': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.desc': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.globalUpdate': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.updateOngoing': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.refreshMetadata': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.refreshMetadataDescription': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.autoDownload': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.downloadNewChapters': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.disableHapticFeedback': 'string';
'moreScreen.settingsScreen.generalSettingsScreen.updateTime': 'string';
'moreScreen.settingsScreen.readerSettings.title': 'string';
'moreScreen.settingsScreen.readerSettings.readerTheme': 'string';
'moreScreen.settingsScreen.readerSettings.preset': 'string';