Update: allow user to set time
This commit is contained in:
committed by
Lei Nelissen
parent
cf29516c00
commit
9cbc5a26ba
11
package-lock.json
generated
11
package-lock.json
generated
@@ -42,6 +42,7 @@
|
|||||||
"react-native-reanimated": "^3.6.2",
|
"react-native-reanimated": "^3.6.2",
|
||||||
"react-native-safe-area-context": "^4.4.1",
|
"react-native-safe-area-context": "^4.4.1",
|
||||||
"react-native-screens": "^3.18.2",
|
"react-native-screens": "^3.18.2",
|
||||||
|
"react-native-select-dropdown": "^3.3.4",
|
||||||
"react-native-shadow-2": "^7.0.6",
|
"react-native-shadow-2": "^7.0.6",
|
||||||
"react-native-skia": "^0.0.1",
|
"react-native-skia": "^0.0.1",
|
||||||
"react-native-svg": "^13.5.0",
|
"react-native-svg": "^13.5.0",
|
||||||
@@ -13762,6 +13763,11 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-select-dropdown": {
|
||||||
|
"version": "3.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-select-dropdown/-/react-native-select-dropdown-3.3.4.tgz",
|
||||||
|
"integrity": "sha512-Ld6BGGgCnbiv7uORAP+KnvDQiqeuqdlasKk9woJH9XtFMD44rwjKwelGzsDxFUM9hIAwZdac4UAFmOmXRaMeRg=="
|
||||||
|
},
|
||||||
"node_modules/react-native-shadow-2": {
|
"node_modules/react-native-shadow-2": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-shadow-2/-/react-native-shadow-2-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-shadow-2/-/react-native-shadow-2-7.0.6.tgz",
|
||||||
@@ -26664,6 +26670,11 @@
|
|||||||
"warn-once": "^0.1.0"
|
"warn-once": "^0.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-native-select-dropdown": {
|
||||||
|
"version": "3.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-select-dropdown/-/react-native-select-dropdown-3.3.4.tgz",
|
||||||
|
"integrity": "sha512-Ld6BGGgCnbiv7uORAP+KnvDQiqeuqdlasKk9woJH9XtFMD44rwjKwelGzsDxFUM9hIAwZdac4UAFmOmXRaMeRg=="
|
||||||
|
},
|
||||||
"react-native-shadow-2": {
|
"react-native-shadow-2": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-shadow-2/-/react-native-shadow-2-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-shadow-2/-/react-native-shadow-2-7.0.6.tgz",
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
"react-native-reanimated": "^3.6.2",
|
"react-native-reanimated": "^3.6.2",
|
||||||
"react-native-safe-area-context": "^4.4.1",
|
"react-native-safe-area-context": "^4.4.1",
|
||||||
"react-native-screens": "^3.18.2",
|
"react-native-screens": "^3.18.2",
|
||||||
|
"react-native-select-dropdown": "^3.3.4",
|
||||||
"react-native-shadow-2": "^7.0.6",
|
"react-native-shadow-2": "^7.0.6",
|
||||||
"react-native-skia": "^0.0.1",
|
"react-native-skia": "^0.0.1",
|
||||||
"react-native-svg": "^13.5.0",
|
"react-native-svg": "^13.5.0",
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { TouchableOpacityProps } from 'react-native';
|
import { StyleSheet, TouchableOpacityProps, View } from 'react-native';
|
||||||
import ChevronRight from '@/assets/icons/chevron-right.svg';
|
import ChevronRight from '@/assets/icons/chevron-right.svg';
|
||||||
import styled from 'styled-components/native';
|
import styled from 'styled-components/native';
|
||||||
import { THEME_COLOR } from '@/CONSTANTS';
|
import { THEME_COLOR } from '@/CONSTANTS';
|
||||||
import useDefaultStyles from './Colors';
|
import useDefaultStyles from './Colors';
|
||||||
|
import { Text } from './Typography';
|
||||||
|
|
||||||
const BUTTON_SIZE = 14;
|
const BUTTON_SIZE = 14;
|
||||||
|
|
||||||
@@ -19,10 +20,28 @@ const Container = styled.Pressable<{ active?: boolean }>`
|
|||||||
const Label = styled.Text<{ active?: boolean }>`
|
const Label = styled.Text<{ active?: boolean }>`
|
||||||
color: ${THEME_COLOR};
|
color: ${THEME_COLOR};
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
display: flex;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
function generateListButtonStyles() {
|
||||||
|
const styles = useDefaultStyles();
|
||||||
|
return StyleSheet.create({
|
||||||
|
...styles,
|
||||||
|
descriptionNote: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column'
|
||||||
|
},
|
||||||
|
showDescription: {
|
||||||
|
display: 'flex'
|
||||||
|
},
|
||||||
|
hideDescription: {
|
||||||
|
display: 'none'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const ListButton: React.FC<TouchableOpacityProps> = ({ children, ...props }) => {
|
const ListButton: React.FC<TouchableOpacityProps> = ({ children, ...props }) => {
|
||||||
const defaultStyles = useDefaultStyles();
|
const defaultStyles = generateListButtonStyles();
|
||||||
const [isPressed, setPressed] = useState(false);
|
const [isPressed, setPressed] = useState(false);
|
||||||
const handlePressIn = useCallback(() => setPressed(true), []);
|
const handlePressIn = useCallback(() => setPressed(true), []);
|
||||||
const handlePressOut = useCallback(() => setPressed(false), []);
|
const handlePressOut = useCallback(() => setPressed(false), []);
|
||||||
|
|||||||
@@ -16,12 +16,11 @@ import ColorScheme from './stacks/ColorScheme';
|
|||||||
import PlaybackReporting from './stacks/PlaybackReporting';
|
import PlaybackReporting from './stacks/PlaybackReporting';
|
||||||
import { SafeScrollView } from '@/components/SafeNavigatorView';
|
import { SafeScrollView } from '@/components/SafeNavigatorView';
|
||||||
import PrivacyPolicy from './components/PrivacyPolicy';
|
import PrivacyPolicy from './components/PrivacyPolicy';
|
||||||
import Timer from './stacks/Timer';
|
import Timer from './stacks/timer/Timer';
|
||||||
import { Paragraph, Text } from '@/components/Typography';
|
import { Paragraph, Text } from '@/components/Typography';
|
||||||
import { useTypedSelector } from '@/store';
|
import { useTypedSelector } from '@/store';
|
||||||
|
|
||||||
export function SettingsList() {
|
export function SettingsList() {
|
||||||
const defaultStyles = useDefaultStyles();
|
|
||||||
const navigation = useNavigation<SettingsNavigationProp>();
|
const navigation = useNavigation<SettingsNavigationProp>();
|
||||||
const handleLibraryClick = useCallback(() => { navigation.navigate('Library'); }, [navigation]);
|
const handleLibraryClick = useCallback(() => { navigation.navigate('Library'); }, [navigation]);
|
||||||
const handleCacheClick = useCallback(() => { navigation.navigate('Cache'); }, [navigation]);
|
const handleCacheClick = useCallback(() => { navigation.navigate('Cache'); }, [navigation]);
|
||||||
@@ -33,10 +32,28 @@ export function SettingsList() {
|
|||||||
|
|
||||||
const { sleepTime } = useTypedSelector(state => state.settings);
|
const { sleepTime } = useTypedSelector(state => state.settings);
|
||||||
|
|
||||||
|
const getTime = () => {
|
||||||
|
if (!Number.isNaN(sleepTime)) {
|
||||||
|
const hours = Math.round(sleepTime / 3600);
|
||||||
|
const timeRemaining = sleepTime % 3600;
|
||||||
|
let minutes = 0;
|
||||||
|
|
||||||
|
if (timeRemaining > 60) {
|
||||||
|
minutes = Math.round(timeRemaining / 60);
|
||||||
|
}
|
||||||
|
return `${hours} hrs ${minutes} min`;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeScrollView>
|
<SafeScrollView>
|
||||||
<ListButton onPress={handleLibraryClick}>{t('jellyfin-library')}</ListButton>
|
<ListButton onPress={handleLibraryClick}>{t('jellyfin-library')}</ListButton>
|
||||||
<ListButton onPress={handleTimerClick}>{t('timer')} <Text>Set Time: {sleepTime}</Text></ListButton>
|
<ListButton onPress={handleTimerClick}>
|
||||||
|
{t('timer')}
|
||||||
|
<Text> {`Set Time: ${getTime()}s`}</Text>
|
||||||
|
</ListButton>
|
||||||
<ListButton onPress={handleCacheClick}>{t('setting-cache')}</ListButton>
|
<ListButton onPress={handleCacheClick}>{t('setting-cache')}</ListButton>
|
||||||
<ListButton onPress={handleSentryClick}>{t('error-reporting')}</ListButton>
|
<ListButton onPress={handleSentryClick}>{t('error-reporting')}</ListButton>
|
||||||
<ListButton onPress={handlePlaybackReportingClick}>{t('playback-reporting')}</ListButton>
|
<ListButton onPress={handlePlaybackReportingClick}>{t('playback-reporting')}</ListButton>
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
import React, { useCallback, useState } from 'react';
|
|
||||||
import Container from '../components/Container';
|
|
||||||
import { Text } from '@/components/Typography';
|
|
||||||
import { InputContainer } from '../components/Input';
|
|
||||||
import Input from '@/components/Input';
|
|
||||||
import useDefaultStyles from '@/components/Colors';
|
|
||||||
import { setSleepTime } from '@/store/settings/actions';
|
|
||||||
import { useNavigation } from '@react-navigation/native';
|
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
|
|
||||||
function Timer() {
|
|
||||||
const defaultStyles = useDefaultStyles();
|
|
||||||
|
|
||||||
const navigation = useNavigation();
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
const setSleeper = useCallback((sleepTime) => {
|
|
||||||
dispatch(setSleepTime(Number.parseInt(sleepTime)));
|
|
||||||
}, [navigation, dispatch]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<InputContainer>
|
|
||||||
<Text>Set Sleep Timer (min)</Text>
|
|
||||||
<Input
|
|
||||||
placeholder='60'
|
|
||||||
editable={true}
|
|
||||||
style={defaultStyles.input}
|
|
||||||
onChangeText={setSleeper}/>
|
|
||||||
|
|
||||||
<Text>Set this to automatically stop the audio when time runs out.</Text>
|
|
||||||
</InputContainer>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Timer;
|
|
||||||
90
src/screens/Settings/stacks/timer/Timer.tsx
Normal file
90
src/screens/Settings/stacks/timer/Timer.tsx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import React, { useCallback, useState } from 'react';
|
||||||
|
import Container from '../../components/Container';
|
||||||
|
import { Text } from '@/components/Typography';
|
||||||
|
import { InputContainer } from '../../components/Input';
|
||||||
|
import Input from '@/components/Input';
|
||||||
|
import useDefaultStyles from '@/components/Colors';
|
||||||
|
import { setSleepTime } from '@/store/settings/actions';
|
||||||
|
import { useNavigation } from '@react-navigation/native';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { ScrollView, ToastAndroid, View } from 'react-native';
|
||||||
|
import { generateTimerStyles } from './styles';
|
||||||
|
import { useTypedSelector } from '@/store';
|
||||||
|
import SelectableFilter from '@/screens/Search/stacks/Search/components/SelectableFilter';
|
||||||
|
import MicrophoneIcon from '@/assets/icons/microphone.svg';
|
||||||
|
import AlbumIcon from '@/assets/icons/collection.svg';
|
||||||
|
import TrackIcon from '@/assets/icons/note.svg';
|
||||||
|
import SelectDropdown from 'react-native-select-dropdown';
|
||||||
|
import { time } from 'console';
|
||||||
|
|
||||||
|
function Timer() {
|
||||||
|
const { sleepTime } = useTypedSelector(state => state.settings);
|
||||||
|
|
||||||
|
const [minutes, setMinutes] = useState<number>();
|
||||||
|
const [hours, setHours] = useState<number>();
|
||||||
|
|
||||||
|
const timerStyles = generateTimerStyles();
|
||||||
|
|
||||||
|
const navigation = useNavigation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const setSleeper = useCallback((value: number, timeType: string) => {
|
||||||
|
if (timeType == 'Hours' && value > 0) {
|
||||||
|
dispatch(setSleepTime(value * 3600));
|
||||||
|
} else if (timeType == 'Minutes' && value > 0) {
|
||||||
|
dispatch(setSleepTime(value * 60));
|
||||||
|
}
|
||||||
|
}, [navigation, dispatch]);
|
||||||
|
|
||||||
|
const getTime = () => {
|
||||||
|
if (!Number.isNaN(sleepTime)) {
|
||||||
|
const hours = Math.round(sleepTime / 3600);
|
||||||
|
const timeRemaining = sleepTime % 3600;
|
||||||
|
let minutes = 0;
|
||||||
|
|
||||||
|
if (timeRemaining > 60) {
|
||||||
|
minutes = Math.round(timeRemaining / 60);
|
||||||
|
}
|
||||||
|
return `${hours} hrs ${minutes} min`;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<InputContainer>
|
||||||
|
<Text>Set Sleep Timer. Time Set Previously: {getTime()}</Text>
|
||||||
|
<View style={timerStyles.timer}>
|
||||||
|
<View style={timerStyles.timeInput}>
|
||||||
|
<Text>H:</Text>
|
||||||
|
<Input
|
||||||
|
placeholder='60'
|
||||||
|
editable={true}
|
||||||
|
style={timerStyles.input}
|
||||||
|
keyboardType='phone-pad'
|
||||||
|
onChangeText={(value: string) => {
|
||||||
|
setSleeper(parseInt(value), 'Hours');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={timerStyles.timeInput}>
|
||||||
|
<Text>M:</Text>
|
||||||
|
<Input
|
||||||
|
placeholder='60'
|
||||||
|
editable={true}
|
||||||
|
style={timerStyles.input}
|
||||||
|
keyboardType='phone-pad'
|
||||||
|
onChangeText={(value: string) => {
|
||||||
|
setSleeper(parseInt(value), 'Minutes');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<Text>Set this to automatically stop the audio when time runs out.</Text>
|
||||||
|
</InputContainer>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Timer;
|
||||||
21
src/screens/Settings/stacks/timer/styles.tsx
Normal file
21
src/screens/Settings/stacks/timer/styles.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import useDefaultStyles from "@/components/Colors";
|
||||||
|
import { ColorScheme } from "@/store/settings/types";
|
||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
|
||||||
|
export function generateTimerStyles() {
|
||||||
|
const styles = useDefaultStyles();
|
||||||
|
|
||||||
|
return StyleSheet.create({
|
||||||
|
...styles,
|
||||||
|
timer: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row'
|
||||||
|
},
|
||||||
|
timeInput: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 3
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ const persistConfig: PersistConfig<Omit<AppState, '_persist'>> = {
|
|||||||
settings: {
|
settings: {
|
||||||
...state.settings,
|
...state.settings,
|
||||||
enableSleepTimer: false,
|
enableSleepTimer: false,
|
||||||
sleepTime: 60,
|
sleepTime: 0,
|
||||||
remainingSleepTime: 0
|
remainingSleepTime: 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user