diff --git a/src/assets/icons/timer-icon.svg b/src/assets/icons/timer-icon.svg
new file mode 100644
index 0000000..3b2302f
--- /dev/null
+++ b/src/assets/icons/timer-icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/screens/Settings/index.tsx b/src/screens/Settings/index.tsx
index ac789b5..aeb2e77 100644
--- a/src/screens/Settings/index.tsx
+++ b/src/screens/Settings/index.tsx
@@ -16,7 +16,6 @@ import ColorScheme from './stacks/ColorScheme';
import PlaybackReporting from './stacks/PlaybackReporting';
import { SafeScrollView } from '@/components/SafeNavigatorView';
import PrivacyPolicy from './components/PrivacyPolicy';
-import Timer from './stacks/timer/Timer';
export function SettingsList() {
const navigation = useNavigation();
@@ -26,12 +25,10 @@ export function SettingsList() {
const handlePlaybackReportingClick = useCallback(() => { navigation.navigate('Playback Reporting'); }, [navigation]);
const handleColorSchemeClick = useCallback(() => { navigation.navigate('Color Scheme'); }, [navigation]);
const handlePrivacyPolicyClick = useCallback(() => { navigation.navigate('PrivacyPolicy'); }, [navigation]);
- const handleTimerClick = useCallback(() => { navigation.navigate('Timer'); }, [navigation]);
return (
{t('jellyfin-library')}
- Set Sleep Timer
{t('setting-cache')}
{t('error-reporting')}
{t('playback-reporting')}
@@ -55,7 +52,6 @@ export default function Settings() {
}}>
-
diff --git a/src/screens/Settings/stacks/timer/Timer.tsx b/src/screens/Settings/stacks/timer/Timer.tsx
deleted file mode 100644
index 12326ec..0000000
--- a/src/screens/Settings/stacks/timer/Timer.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import React, { useCallback, useState } from 'react';
-import Container from '../../components/Container';
-import { Text } from '@/components/Typography';
-import { InputContainer } from '../../components/Input';
-import { useTimeStyles } from './styles';
-import { Switch } from 'react-native-gesture-handler';
-import { SwitchContainer, SwitchLabel } from '../../components/Switch';
-import Button from '@/components/Button';
-import { View } from 'react-native';
-import DateTimePickerModal from 'react-native-modal-datetime-picker';
-import { useTypedSelector } from '@/store';
-import { useDispatch } from 'react-redux';
-import { setDateTime, setEnableSleepTime } from '@/store/settings/actions';
-
-function Timer() {
- const [show, setShow] = useState(false);
- const { dateTime } = useTypedSelector(state => state.settings);
- const [date, setDate] = useState(dateTime === undefined ? 'Set Time' : dateTime.toString());
-
- const timerStyles = useTimeStyles();
- const { enableSleepTime } = useTypedSelector(state => state.settings);
-
- const dispatch = useDispatch();
-
- const handleEnabledSleeper = useCallback((value: boolean) => {
- dispatch(setEnableSleepTime(value));
- }, [dispatch]);
-
- const handleConfirm = (date: Date) => {
- setShow(false);
- setDate(date.toString());
- dispatch(setDateTime(date));
- };
-
- const showDateTimePicker = () => {
- setShow(!show);
- };
-
- const handleCancelDatePicker = () => {
- setShow(false);
- };
-
- return (
-
-
- {'Set Sleep Time.'}
-
- handleEnabledSleeper(value)}
- />
- {'Enable Timer'}
-
-
-
- {'Set Time'}
-
-
- {'Set this to automatically stop the audio when time runs out.'}
-
-
-
-
- );
-}
-
-export default Timer;
\ No newline at end of file
diff --git a/src/screens/Settings/stacks/timer/styles.tsx b/src/screens/Settings/stacks/timer/styles.tsx
deleted file mode 100644
index df93286..0000000
--- a/src/screens/Settings/stacks/timer/styles.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import useDefaultStyles from '@/components/Colors';
-import { StyleSheet } from 'react-native';
-
-export function useTimeStyles() {
- const styles = useDefaultStyles();
-
- return StyleSheet.create({
- ...styles,
- timer: {
- display: 'flex',
- flexDirection: 'row'
- },
- timeInput: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- gap: 3
- },
- checkbox: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center'
- },
- timerSetting: {
- marginStart: 10
- },
- timerSettingsDisabled: {
- color: '#cbcbcb',
- marginStart: 10
- },
- showDateTime: {
- display: 'flex'
- },
- hideDateTime: {
- display: 'none'
- }
- });
-}
\ No newline at end of file
diff --git a/src/screens/modals/Player/components/Queue.tsx b/src/screens/modals/Player/components/Queue.tsx
index e57b492..d3541da 100644
--- a/src/screens/modals/Player/components/Queue.tsx
+++ b/src/screens/modals/Player/components/Queue.tsx
@@ -27,7 +27,7 @@ const Header = styled.View`
flex-direction: row;
align-items: center;
padding-bottom: 8px;
- padding-top: 52px;
+ padding-top: 27px;
`;
const IconButton = styled.TouchableOpacity`
diff --git a/src/screens/modals/Player/components/Timer.tsx b/src/screens/modals/Player/components/Timer.tsx
new file mode 100644
index 0000000..33952ad
--- /dev/null
+++ b/src/screens/modals/Player/components/Timer.tsx
@@ -0,0 +1,62 @@
+import React, { useState } from 'react';
+import DateTimePickerModal from 'react-native-modal-datetime-picker';
+import styled from 'styled-components/native';
+import { THEME_COLOR } from '@/CONSTANTS';
+import { useDispatch } from 'react-redux';
+import { setDateTime } from '@/store/settings/actions';
+import { useTypedSelector } from '@/store';
+import TimerIcon from '@/assets/icons/timer-icon.svg';
+
+const Container = styled.View`
+ align-item: left;
+ margin-top: 60px;
+`;
+
+const View = styled.View`
+ display: flex;
+ flex-direction: row;
+ gap: 4px;
+`;
+
+const Text = styled.Text`
+ font-size: 10px;
+`;
+
+export default function Timer() {
+ const [showPicker, setShowPicker] = useState(false);
+ const { remainingSleepTime } = useTypedSelector(state => state.settings);
+
+ const dispatch = useDispatch();
+
+ const handleConfirm = (date: Date) => {
+ date.setSeconds(0);
+ dispatch(setDateTime(date));
+ setShowPicker(false);
+ };
+
+ const handleCancelDatePicker = () => {
+ console.log('Handle cancel implement this event');
+ };
+
+ const showDatePicker = () => {
+ setShowPicker(true);
+ };
+
+ return (
+
+
+
+ {remainingSleepTime === '' ? 'Sleep Timer' : remainingSleepTime}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/screens/modals/Player/index.tsx b/src/screens/modals/Player/index.tsx
index d940854..63a584b 100644
--- a/src/screens/modals/Player/index.tsx
+++ b/src/screens/modals/Player/index.tsx
@@ -8,6 +8,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
import StreamStatus from './components/StreamStatus';
import { Platform } from 'react-native';
import BackButton from './components/Backbutton';
+import Timer from './components/Timer';
export default function Player() {
return (
@@ -20,6 +21,7 @@ export default function Player() {
+
>
)} />
diff --git a/src/store/index.ts b/src/store/index.ts
index 1ae9d93..817628e 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -62,7 +62,8 @@ const persistConfig: PersistConfig> = {
settings: {
...state.settings,
enableSleepTime: false,
- dateTime: Date
+ dateTime: Date,
+ remainingSleepTime: String
}
};
},
diff --git a/src/store/settings/actions.ts b/src/store/settings/actions.ts
index 0e3ea26..06607f7 100644
--- a/src/store/settings/actions.ts
+++ b/src/store/settings/actions.ts
@@ -9,4 +9,4 @@ export const setEnablePlaybackReporting = createAction('SET_ENABLE_PLAY
export const setColorScheme = createAction('SET_COLOR_SCHEME');
export const setDateTime = createAction('SET_DATE_TIME');
export const setEnableSleepTime = createAction('SET_ENABLE_SLEEP_TIME');
-export const setRemainingSleepTime = createAction('SET_REMAINING_SLEEP_TIME');
+export const setRemainingSleepTime = createAction('SET_REMAINING_SLEEP_TIME');
diff --git a/src/store/settings/index.ts b/src/store/settings/index.ts
index bd44216..4928f3e 100644
--- a/src/store/settings/index.ts
+++ b/src/store/settings/index.ts
@@ -15,7 +15,7 @@ interface State {
enablePlaybackReporting: boolean;
colorScheme: ColorScheme;
dateTime?: Date;
- enableSleepTime: boolean
+ remainingSleepTime: String
}
const initialState: State = {
@@ -24,8 +24,7 @@ const initialState: State = {
hasReceivedErrorReportingAlert: false,
enablePlaybackReporting: true,
colorScheme: ColorScheme.System,
- dateTime: new Date(),
- enableSleepTime: false
+ remainingSleepTime: ''
};
const settings = createReducer(initialState, builder => {
diff --git a/src/utility/PlaybackService.ts b/src/utility/PlaybackService.ts
index 609e4ac..84799db 100644
--- a/src/utility/PlaybackService.ts
+++ b/src/utility/PlaybackService.ts
@@ -10,6 +10,7 @@
import TrackPlayer, { Event, State } from 'react-native-track-player';
import store from '@/store';
import { sendPlaybackEvent } from './JellyfinApi';
+import { setRemainingSleepTime } from '@/store/settings/actions';
export default async function() {
@@ -61,26 +62,53 @@ export default async function() {
sendPlaybackEvent('/Sessions/Playing/Progress', settings.jellyfin);
}
- // regularly check if sleeper is enabled, pause the audio after 30 minutes.
- if (settings.enableSleepTime && settings.dateTime !== undefined) {
- const dateSet = new Date(settings.dateTime.toString());
- const dateNow = new Date(Date.now());
- const diff = Math.abs(dateSet.getMinutes() - dateNow.getMinutes());
+ // check if datetime is undefined, otherwise start timer
+ if (settings.dateTime === undefined) {
+ store.dispatch(setRemainingSleepTime(''));
+ } else {
+ const millisecondsDiff = settings.dateTime.valueOf() - new Date().valueOf();
- console.log(`Difference: ${diff}`);
+ const timeDiff = new Date(millisecondsDiff);
+ let interval = setInterval(() => {});
- if (diff >= 30 && dateNow >= dateSet) {
- console.log('Music Paused');
- TrackPlayer.pause();
+ if (timeDiff.getTime() > 0) {
+ interval = setInterval(() => {
+ const settings = store.getState().settings;
+
+ if (settings.dateTime !== undefined) {
+ const millisecondsDiff = settings.dateTime.valueOf() - new Date().valueOf();
+
+ const timeDiff = new Date(millisecondsDiff);
+
+ if (timeDiff.getTime() > 0) {
+ let sec = Math.floor(timeDiff.getTime() / 1000);
+ let min = Math.floor(sec/60);
+ sec = sec%60;
+ const hours = Math.floor(min/60);
+ min = min%60;
+
+ const timer = `${hours.toString().length === 1 ? '0' + hours : hours}:${min.toString().length === 1 ? '0' + min : min}:${sec.toString().length === 1 ? '0' + sec : sec}`;
+
+ store.dispatch(setRemainingSleepTime(timer));
+ } else {
+ store.dispatch(setRemainingSleepTime(''));
+ TrackPlayer.pause();
+ clearInterval(interval);
+ }
+ } else {
+ clearInterval(interval);
+ }
+ }, 1000);
}
}
});
TrackPlayer.addEventListener(Event.PlaybackState, (event) => {
+ // Retrieve the current settings from the Redux store
+ const settings = store.getState().settings;
+
// GUARD: Only respond to stopped events
if (event.state === State.Stopped) {
- // Retrieve the current settings from the Redux store
- const settings = store.getState().settings;
// GUARD: Only report playback when the settings is enabled
if (settings.enablePlaybackReporting) {