This commit is contained in:
279
App.js
Normal file
279
App.js
Normal file
@@ -0,0 +1,279 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { BackHandler, Platform, StatusBar } from 'react-native';
|
||||
import * as ScreenOrientation from 'expo-screen-orientation';
|
||||
import FocusScreen from './src/screens/FocusScreen';
|
||||
import HomeScreen from './src/screens/HomeScreen';
|
||||
import TimeUntilScreen from './src/screens/TimeUntilScreen';
|
||||
import TimerScreen from './src/screens/TimerScreen';
|
||||
import { createStyles } from './src/styles';
|
||||
import { getTheme } from './src/theme';
|
||||
|
||||
export default function App() {
|
||||
const styles = useMemo(() => createStyles(), []);
|
||||
|
||||
const [screen, setScreen] = useState('home');
|
||||
const [focusMode, setFocusMode] = useState(false);
|
||||
const [darkMode, setDarkMode] = useState(true);
|
||||
const [pinkMode, setPinkMode] = useState(false);
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
const [now, setNow] = useState(new Date());
|
||||
|
||||
const [targetTime, setTargetTime] = useState(null);
|
||||
const [tuHour, setTuHour] = useState('');
|
||||
const [tuMinute, setTuMinute] = useState('');
|
||||
const [tuIsOver, setTuIsOver] = useState(false);
|
||||
|
||||
const [timerRunning, setTimerRunning] = useState(false);
|
||||
const [timerDone, setTimerDone] = useState(false);
|
||||
const [timerRemaining, setTimerRemaining] = useState(0);
|
||||
const [timerHInput, setTimerHInput] = useState('');
|
||||
const [timerMInput, setTimerMInput] = useState('');
|
||||
const [timerSInput, setTimerSInput] = useState('');
|
||||
|
||||
const timerRef = useRef(null);
|
||||
const theme = getTheme(darkMode, pinkMode);
|
||||
|
||||
useEffect(() => {
|
||||
if (Platform.OS !== 'web') {
|
||||
ScreenOrientation.unlockAsync();
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => setNow(new Date()), 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (targetTime && now >= targetTime) {
|
||||
setTuIsOver(true);
|
||||
} else {
|
||||
setTuIsOver(false);
|
||||
}
|
||||
}, [now, targetTime]);
|
||||
|
||||
useEffect(() => {
|
||||
if (timerRunning) {
|
||||
timerRef.current = setInterval(() => {
|
||||
setTimerRemaining((r) => {
|
||||
if (r <= 1) {
|
||||
clearInterval(timerRef.current);
|
||||
setTimerRunning(false);
|
||||
setTimerDone(true);
|
||||
return 0;
|
||||
}
|
||||
return r - 1;
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
return () => clearInterval(timerRef.current);
|
||||
}, [timerRunning]);
|
||||
|
||||
useEffect(() => {
|
||||
if (Platform.OS !== 'android') return undefined;
|
||||
|
||||
const sub = BackHandler.addEventListener('hardwareBackPress', () => {
|
||||
if (focusMode) {
|
||||
setFocusMode(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (screen !== 'home') {
|
||||
setScreen('home');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return () => sub.remove();
|
||||
}, [focusMode, screen]);
|
||||
|
||||
const toggleFullscreen = () => {
|
||||
if (Platform.OS !== 'web') return;
|
||||
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen();
|
||||
setIsFullscreen(true);
|
||||
} else {
|
||||
document.exitFullscreen();
|
||||
setIsFullscreen(false);
|
||||
}
|
||||
};
|
||||
|
||||
const setTuTimer = () => {
|
||||
const h = parseInt(tuHour, 10);
|
||||
const m = parseInt(tuMinute, 10);
|
||||
|
||||
if (isNaN(h) || isNaN(m) || h < 0 || h > 23 || m < 0 || m > 59) return;
|
||||
|
||||
const target = new Date();
|
||||
target.setHours(h, m, 0, 0);
|
||||
if (target <= new Date()) {
|
||||
target.setDate(target.getDate() + 1);
|
||||
}
|
||||
|
||||
setTargetTime(target);
|
||||
setTuIsOver(false);
|
||||
};
|
||||
|
||||
const resetTuTimer = () => {
|
||||
setTargetTime(null);
|
||||
setTuIsOver(false);
|
||||
setTuHour('');
|
||||
setTuMinute('');
|
||||
};
|
||||
|
||||
const getTuCountdown = () => {
|
||||
if (!targetTime) return null;
|
||||
const diff = targetTime - now;
|
||||
if (diff <= 0) return null;
|
||||
|
||||
const t = Math.floor(diff / 1000);
|
||||
return {
|
||||
hours: Math.floor(t / 3600),
|
||||
minutes: Math.floor((t % 3600) / 60),
|
||||
seconds: t % 60,
|
||||
};
|
||||
};
|
||||
|
||||
const startTimer = () => {
|
||||
const h = parseInt(timerHInput, 10) || 0;
|
||||
const m = parseInt(timerMInput, 10) || 0;
|
||||
const s = parseInt(timerSInput, 10) || 0;
|
||||
const total = h * 3600 + m * 60 + s;
|
||||
|
||||
if (total <= 0) return;
|
||||
|
||||
setTimerRemaining(total);
|
||||
setTimerDone(false);
|
||||
setTimerRunning(true);
|
||||
};
|
||||
|
||||
const resetTimerState = () => {
|
||||
clearInterval(timerRef.current);
|
||||
setTimerRunning(false);
|
||||
setTimerDone(false);
|
||||
setTimerRemaining(0);
|
||||
setTimerHInput('');
|
||||
setTimerMInput('');
|
||||
setTimerSInput('');
|
||||
};
|
||||
|
||||
const timerHr = Math.floor(timerRemaining / 3600);
|
||||
const timerMin = Math.floor((timerRemaining % 3600) / 60);
|
||||
const timerSec = timerRemaining % 60;
|
||||
const tuCountdown = getTuCountdown();
|
||||
|
||||
if (focusMode) {
|
||||
return (
|
||||
<FocusScreen
|
||||
styles={styles}
|
||||
theme={theme}
|
||||
screen={screen}
|
||||
pinkMode={pinkMode}
|
||||
tuIsOver={tuIsOver}
|
||||
tuCountdown={tuCountdown}
|
||||
targetTime={targetTime}
|
||||
timerDone={timerDone}
|
||||
timerHr={timerHr}
|
||||
timerMin={timerMin}
|
||||
timerSec={timerSec}
|
||||
onShowUI={() => setFocusMode(false)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const barStyle = darkMode ? 'light-content' : 'dark-content';
|
||||
|
||||
if (screen === 'home') {
|
||||
return (
|
||||
<>
|
||||
<StatusBar barStyle={barStyle} backgroundColor={theme.bg} />
|
||||
<HomeScreen
|
||||
styles={styles}
|
||||
theme={theme}
|
||||
now={now}
|
||||
darkMode={darkMode}
|
||||
pinkMode={pinkMode}
|
||||
isFullscreen={isFullscreen}
|
||||
onToggleDark={() => setDarkMode((d) => !d)}
|
||||
onTogglePink={() => setPinkMode((p) => !p)}
|
||||
onToggleFullscreen={toggleFullscreen}
|
||||
onSelectTimeUntil={() => setScreen('timeuntil')}
|
||||
onSelectTimer={() => setScreen('timer')}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (screen === 'timeuntil') {
|
||||
return (
|
||||
<>
|
||||
<StatusBar barStyle={barStyle} backgroundColor={theme.bg} />
|
||||
<TimeUntilScreen
|
||||
styles={styles}
|
||||
theme={theme}
|
||||
now={now}
|
||||
darkMode={darkMode}
|
||||
pinkMode={pinkMode}
|
||||
isFullscreen={isFullscreen}
|
||||
targetTime={targetTime}
|
||||
tuHour={tuHour}
|
||||
tuMinute={tuMinute}
|
||||
tuIsOver={tuIsOver}
|
||||
tuCountdown={tuCountdown}
|
||||
onChangeHour={setTuHour}
|
||||
onChangeMinute={setTuMinute}
|
||||
onSetTimer={setTuTimer}
|
||||
onResetTimer={resetTuTimer}
|
||||
onBackToMenu={() => setScreen('home')}
|
||||
onToggleDark={() => setDarkMode((d) => !d)}
|
||||
onTogglePink={() => setPinkMode((p) => !p)}
|
||||
onToggleFullscreen={toggleFullscreen}
|
||||
onFocus={() => setFocusMode(true)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<StatusBar barStyle={barStyle} backgroundColor={theme.bg} />
|
||||
<TimerScreen
|
||||
styles={styles}
|
||||
theme={theme}
|
||||
now={now}
|
||||
darkMode={darkMode}
|
||||
pinkMode={pinkMode}
|
||||
isFullscreen={isFullscreen}
|
||||
timerRunning={timerRunning}
|
||||
timerDone={timerDone}
|
||||
timerRemaining={timerRemaining}
|
||||
timerHInput={timerHInput}
|
||||
timerMInput={timerMInput}
|
||||
timerSInput={timerSInput}
|
||||
timerHr={timerHr}
|
||||
timerMin={timerMin}
|
||||
timerSec={timerSec}
|
||||
onChangeH={setTimerHInput}
|
||||
onChangeM={setTimerMInput}
|
||||
onChangeS={setTimerSInput}
|
||||
onStart={startTimer}
|
||||
onPause={() => setTimerRunning(false)}
|
||||
onResume={() => {
|
||||
if (timerRemaining > 0) {
|
||||
setTimerRunning(true);
|
||||
}
|
||||
}}
|
||||
onReset={resetTimerState}
|
||||
onBackToMenu={() => setScreen('home')}
|
||||
onToggleDark={() => setDarkMode((d) => !d)}
|
||||
onTogglePink={() => setPinkMode((p) => !p)}
|
||||
onToggleFullscreen={toggleFullscreen}
|
||||
onFocus={() => setFocusMode(true)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user