reverting to chase a bug w expo

This commit is contained in:
Chris Sanden
2026-04-24 22:48:43 +02:00
parent b191a1eced
commit c68aeba709

View File

@@ -23,11 +23,7 @@ const ITEM_SIZE = width * 0.38;
const ITEM_SPACING = (width - ITEM_SIZE) / 2; const ITEM_SPACING = (width - ITEM_SIZE) / 2;
const TIMER_UNIT_IN_SECONDS = 60; // Set to 60 for timer value to represent minutes const TIMER_UNIT_IN_SECONDS = 60; // Set to 60 for timer value to represent minutes
const HOLD_TO_CANCEL_MS = 2000; const HOLD_TO_CANCEL_MS = 2000;
const CANCEL_ANIMATION_DELAY_MS = 250; const CANCEL_ANIMATION_DELAY_MS = 250
const CANCEL_RELEASE_MS = 750;
const START_TRANSITION_MS = 300;
const TIMER_RESET_MS = 300;
const COUNTDOWN_FADE_MS = 180;
const placeholderTask = { const placeholderTask = {
name: 'Read chapter 4', name: 'Read chapter 4',
description: 'Focus on the summary questions and write down anything unclear.', description: 'Focus on the summary questions and write down anything unclear.',
@@ -41,61 +37,31 @@ function formatTime(totalSeconds: number) {
seconds.toString().padStart(2, '0')}`; seconds.toString().padStart(2, '0')}`;
} }
function getCancelOverlayTarget({
containerHeight,
holdStartedAt,
sessionStartedAt,
sessionDurationMs,
}: {
containerHeight: number;
holdStartedAt: number;
sessionStartedAt: number;
sessionDurationMs: number;
}) {
const now = Date.now();
const elapsedHoldMs = now - holdStartedAt;
const remainingHoldMs = Math.max(1, HOLD_TO_CANCEL_MS - elapsedHoldMs);
const elapsedAtCancelMs = now + remainingHoldMs - sessionStartedAt;
const expectedProgress = elapsedAtCancelMs / sessionDurationMs;
const clampedProgress = Math.max(0, Math.min(expectedProgress, 1));
const expectedYAtCancel = containerHeight * clampedProgress;
const cancelOffset = Math.max(0, containerHeight - expectedYAtCancel);
return { cancelOffset, remainingHoldMs };
}
export default function App() { export default function App() {
const [containerHeight, setContainerHeight] = React.useState(0); const [containerHeight, setContainerHeight] = React.useState(0)
const [duration, setDuration] = React.useState(timers[0]); const [duration, setDuration] = React.useState(timers[0])
const [timerIsRunning, setIsRunning] = React.useState(false); const [timerIsRunning, setIsRunning] = React.useState(false)
const [timeRemaining, setTimeRemaining] = React.useState(0); const [timeRemaining, setTimeRemaining] = React.useState(0)
// Animated values
const scrollX = React.useRef(new Animated.Value(0)).current; const scrollX = React.useRef(new Animated.Value(0)).current;
const timerAnimation = React.useRef(new Animated.Value(0)).current; const timerAnimation = React.useRef(new Animated.Value(0)).current;
const buttonAnimation = React.useRef(new Animated.Value(0)).current; const buttonAnimation = React.useRef(new Animated.Value(0)).current;
const taskDetailsAnimation = React.useRef(new Animated.Value(0)).current; const taskDetailsAnimation = React.useRef(new Animated.Value(0)).current;
const countdownAnimation = React.useRef(new Animated.Value(0)).current; const countdownAnimation = React.useRef(new Animated.Value(0)).current;
const cancelButtonAnimation = React.useRef(new Animated.Value(0)).current;
const pressedButtonAnimation = React.useRef(new Animated.Value(0)).current;
const focusModeAnimation = React.useRef(new Animated.Value(0)).current; // 0 = timer inactive, 1 = timer active
const timerOverlayOpacity = React.useRef(new Animated.Value(1)).current;
const cancelOverlayAnimation = React.useRef(new Animated.Value(0)).current;
// Timer/session refs
const countdownRef = React.useRef<ReturnType<typeof setInterval> | null>(null); const countdownRef = React.useRef<ReturnType<typeof setInterval> | null>(null);
const cancelHoldTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
const runningAnimationRef = React.useRef<Animated.CompositeAnimation | null>(null); const runningAnimationRef = React.useRef<Animated.CompositeAnimation | null>(null);
const progressAnimationRef = React.useRef<Animated.CompositeAnimation | null>(null); const progressAnimationRef = React.useRef<Animated.CompositeAnimation | null>(null);
const sessionStartedAtRef = React.useRef<number | null>(null); const sessionStartedAtRef = React.useRef<number | null>(null);
const sessionDurationMsRef = React.useRef(0); const sessionDurationMsRef = React.useRef(0);
const cancelButtonAnimation = React.useRef(new Animated.Value(0)).current;
// Cancel-hold refs const pressedButtonAnimation = React.useRef(new Animated.Value(0)).current;
const cancelHoldTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null); const focusModeAnimation = React.useRef(new Animated.Value(0)).current; // 0 = timer inactive, 1 = timer active
const cancelHoldAnimationDelayRef = React.useRef<ReturnType<typeof setTimeout> | null>(null); const cancelHoldAnimationDelayRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
const cancelAccelStartedRef = React.useRef(false); const cancelAccelStartedRef = React.useRef(false);
const cancelHoldActiveRef = React.useRef(false); const cancelHoldActiveRef = React.useRef(false);
const cancelHoldIdRef = React.useRef(0); const cancelHoldIdRef = React.useRef(0);
const cancelHoldStartedAtRef = React.useRef(0); const cancelHoldStartedAtRef = React.useRef(0);
const cancelOverlayAnimation = React.useRef(new Animated.Value(0)).current;
React.useEffect(() => { React.useEffect(() => {
if (containerHeight > 0 && !timerIsRunning) { if (containerHeight > 0 && !timerIsRunning) {
@@ -103,6 +69,8 @@ export default function App() {
} }
}, [containerHeight, timerIsRunning, timerAnimation]); }, [containerHeight, timerIsRunning, timerAnimation]);
const timerOverlayOpacity = React.useRef(new Animated.Value(1)).current;
const cancelButtonOpacity = cancelButtonAnimation; const cancelButtonOpacity = cancelButtonAnimation;
const pressedButtonScale = pressedButtonAnimation.interpolate({ const pressedButtonScale = pressedButtonAnimation.interpolate({
@@ -139,12 +107,12 @@ export default function App() {
outputRange: [1, 0.55], outputRange: [1, 0.55],
}); });
const startButtonOpacity = buttonAnimation.interpolate({ const opacity = buttonAnimation.interpolate({
inputRange: [0, 1], inputRange: [0, 1],
outputRange: [1, 0] outputRange: [1, 0]
}); });
const startButtonTranslateY = buttonAnimation.interpolate({ const translateY = buttonAnimation.interpolate({
inputRange: [0, 1], inputRange: [0, 1],
outputRange: [0, 200] outputRange: [0, 200]
}); });
@@ -164,35 +132,6 @@ export default function App() {
outputRange: [20, 0] outputRange: [20, 0]
}); });
const clearCountdown = React.useCallback(() => {
if (countdownRef.current) {
clearInterval(countdownRef.current);
countdownRef.current = null;
}
}, []);
const clearCancelHoldTimers = React.useCallback(() => {
if (cancelHoldTimeoutRef.current) {
clearTimeout(cancelHoldTimeoutRef.current);
cancelHoldTimeoutRef.current = null;
}
if (cancelHoldAnimationDelayRef.current) {
clearTimeout(cancelHoldAnimationDelayRef.current);
cancelHoldAnimationDelayRef.current = null;
}
}, []);
const stopTimerAnimations = React.useCallback(() => {
runningAnimationRef.current?.stop();
runningAnimationRef.current = null;
progressAnimationRef.current?.stop();
progressAnimationRef.current = null;
cancelOverlayAnimation.stopAnimation();
}, [cancelOverlayAnimation]);
const animateButtonPress = React.useCallback((pressed: boolean) => { const animateButtonPress = React.useCallback((pressed: boolean) => {
Animated.timing(pressedButtonAnimation, { Animated.timing(pressedButtonAnimation, {
toValue: pressed ? 1 : 0, toValue: pressed ? 1 : 0,
@@ -202,11 +141,19 @@ export default function App() {
}, [pressedButtonAnimation]); }, [pressedButtonAnimation]);
const cancelTimer = React.useCallback(() => { const cancelTimer = React.useCallback(() => {
if (!timerIsRunning) { if (!timerIsRunning){
return; return;
} }
clearCountdown(); if (countdownRef.current) {
stopTimerAnimations(); clearInterval(countdownRef.current);
countdownRef.current = null;
}
runningAnimationRef.current?.stop();
runningAnimationRef.current = null;
progressAnimationRef.current?.stop();
progressAnimationRef.current = null;
cancelOverlayAnimation.stopAnimation();
Animated.parallel([ Animated.parallel([
Animated.timing(cancelButtonAnimation, { Animated.timing(cancelButtonAnimation, {
@@ -226,12 +173,12 @@ export default function App() {
}), }),
Animated.timing(countdownAnimation, { Animated.timing(countdownAnimation, {
toValue: 0, toValue: 0,
duration: COUNTDOWN_FADE_MS, duration: 180,
useNativeDriver: true useNativeDriver: true
}), }),
Animated.timing(timerAnimation, { Animated.timing(timerAnimation, {
toValue: containerHeight, toValue: containerHeight,
duration: TIMER_RESET_MS, duration: 300,
useNativeDriver: true useNativeDriver: true
}), }),
Animated.timing(timerOverlayOpacity, { Animated.timing(timerOverlayOpacity, {
@@ -251,7 +198,7 @@ export default function App() {
useNativeDriver: true useNativeDriver: true
}) })
.start(() => { .start(() => {
timerAnimation.setValue(containerHeight); timerAnimation.setValue(containerHeight)
cancelOverlayAnimation.setValue(0); cancelOverlayAnimation.setValue(0);
timerOverlayOpacity.setValue(1); timerOverlayOpacity.setValue(1);
setTimeRemaining(0); setTimeRemaining(0);
@@ -259,9 +206,8 @@ export default function App() {
}); });
}) })
}, [timerOverlayOpacity, buttonAnimation, cancelButtonAnimation, }, [timerOverlayOpacity, buttonAnimation, cancelButtonAnimation,
cancelOverlayAnimation, clearCountdown, containerHeight, countdownAnimation, cancelOverlayAnimation, containerHeight, countdownAnimation, timerAnimation,
focusModeAnimation, stopTimerAnimations, taskDetailsAnimation, timerIsRunning, taskDetailsAnimation, focusModeAnimation]);
timerAnimation, timerIsRunning]);
const startCancelHold = React.useCallback(() => { const startCancelHold = React.useCallback(() => {
animateButtonPress(true); animateButtonPress(true);
@@ -281,12 +227,14 @@ export default function App() {
cancelAccelStartedRef.current = true; cancelAccelStartedRef.current = true;
cancelOverlayAnimation.setValue(0); cancelOverlayAnimation.setValue(0);
const { cancelOffset, remainingHoldMs } = getCancelOverlayTarget({ const elapsedHoldMs = Date.now() - cancelHoldStartedAtRef.current;
containerHeight, const remainingHoldMs = Math.max(1, HOLD_TO_CANCEL_MS - elapsedHoldMs);
holdStartedAt: cancelHoldStartedAtRef.current, const sessionStartedAt = sessionStartedAtRef.current ?? Date.now();
sessionStartedAt: sessionStartedAtRef.current ?? Date.now(), const elapsedAtCancelMs = Date.now() + remainingHoldMs - sessionStartedAt;
sessionDurationMs: sessionDurationMsRef.current, const expectedProgress = elapsedAtCancelMs / sessionDurationMsRef.current;
}); const clampedProgress = Math.max(0, Math.min(expectedProgress, 1));
const expectedYAtCancel = containerHeight * clampedProgress;
const cancelOffset = Math.max(0, containerHeight - expectedYAtCancel);
Animated.timing(cancelOverlayAnimation, { Animated.timing(cancelOverlayAnimation, {
toValue: cancelOffset, toValue: cancelOffset,
@@ -304,7 +252,7 @@ export default function App() {
cancelHoldActiveRef.current = false; cancelHoldActiveRef.current = false;
cancelHoldIdRef.current += 1; cancelHoldIdRef.current += 1;
cancelAccelStartedRef.current = false; cancelAccelStartedRef.current = false;
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning); Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning)
cancelTimer(); cancelTimer();
cancelHoldTimeoutRef.current = null; cancelHoldTimeoutRef.current = null;
}, HOLD_TO_CANCEL_MS); }, HOLD_TO_CANCEL_MS);
@@ -331,12 +279,12 @@ export default function App() {
Animated.parallel([ Animated.parallel([
Animated.timing(buttonAnimation, { Animated.timing(buttonAnimation, {
toValue: 0, toValue: 0,
duration: START_TRANSITION_MS, duration: 300,
useNativeDriver: true useNativeDriver: true
}), }),
Animated.timing(cancelButtonAnimation, { Animated.timing(cancelButtonAnimation, {
toValue: 0, toValue: 0,
duration: START_TRANSITION_MS, duration: 300,
useNativeDriver: true useNativeDriver: true
}), }),
]).start(() => { ]).start(() => {
@@ -380,7 +328,15 @@ export default function App() {
cancelHoldActiveRef.current = false; cancelHoldActiveRef.current = false;
cancelHoldIdRef.current += 1; cancelHoldIdRef.current += 1;
clearCancelHoldTimers(); if (cancelHoldTimeoutRef.current) {
clearTimeout(cancelHoldTimeoutRef.current);
cancelHoldTimeoutRef.current = null;
}
if (cancelHoldAnimationDelayRef.current) {
clearTimeout(cancelHoldAnimationDelayRef.current);
cancelHoldAnimationDelayRef.current = null;
}
if (!cancelAccelStartedRef.current) { if (!cancelAccelStartedRef.current) {
return; return;
@@ -391,18 +347,18 @@ export default function App() {
cancelOverlayAnimation.setValue(currentOffset); cancelOverlayAnimation.setValue(currentOffset);
Animated.timing(cancelOverlayAnimation, { Animated.timing(cancelOverlayAnimation, {
toValue: 0, toValue: 0,
duration: CANCEL_RELEASE_MS, duration: 750,
easing: Easing.in(Easing.bounce), easing: Easing.in(Easing.bounce),
useNativeDriver: true useNativeDriver: true
}).start(); }).start();
}); });
}, [animateButtonPress, cancelOverlayAnimation, clearCancelHoldTimers]); }, [animateButtonPress, cancelOverlayAnimation]);
const startTimer = React.useCallback(() => { const animation = React.useCallback(() => {
if (timerIsRunning || containerHeight === 0) { if (timerIsRunning || containerHeight === 0) {
return; return;
} }
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success); Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success)
setIsRunning(true); setIsRunning(true);
taskDetailsAnimation.setValue(0); taskDetailsAnimation.setValue(0);
countdownAnimation.setValue(0); countdownAnimation.setValue(0);
@@ -414,14 +370,20 @@ export default function App() {
sessionStartedAtRef.current = Date.now(); sessionStartedAtRef.current = Date.now();
sessionDurationMsRef.current = totalSeconds * 1000; sessionDurationMsRef.current = totalSeconds * 1000;
clearCountdown(); if (countdownRef.current) {
clearInterval(countdownRef.current);
countdownRef.current = null;
}
countdownRef.current = setInterval(() => { countdownRef.current = setInterval(() => {
setTimeRemaining((currentTime) => { setTimeRemaining((currentTime) => {
if (currentTime <= 1) { if (currentTime <= 1) {
clearCountdown(); if (countdownRef.current) {
clearInterval(countdownRef.current);
countdownRef.current = null;
}
return 0; return 0;
} }
return currentTime - 1; return currentTime -1;
}); });
}, 1000); }, 1000);
@@ -429,23 +391,23 @@ export default function App() {
Animated.parallel([ Animated.parallel([
Animated.timing(buttonAnimation, { Animated.timing(buttonAnimation, {
toValue: 1, toValue: 1,
duration: START_TRANSITION_MS, duration: 300,
useNativeDriver: true useNativeDriver: true
}), }),
Animated.timing(cancelButtonAnimation, { Animated.timing(cancelButtonAnimation, {
toValue: 1, toValue: 1,
duration: START_TRANSITION_MS, duration: 300,
useNativeDriver: true useNativeDriver: true
}), }),
Animated.timing(countdownAnimation, { Animated.timing(countdownAnimation, {
toValue: 1, toValue: 1,
duration: START_TRANSITION_MS, duration: 300,
useNativeDriver: true useNativeDriver: true
}), }),
Animated.timing(timerAnimation, { Animated.timing(timerAnimation, {
toValue: 0, toValue: 0,
duration: START_TRANSITION_MS, duration: 300,
useNativeDriver: true useNativeDriver: true
}), }),
]), ]),
@@ -472,20 +434,24 @@ export default function App() {
startProgressAnimation(0); startProgressAnimation(0);
}); });
}, [cancelButtonAnimation, countdownAnimation, }, [cancelButtonAnimation, countdownAnimation,
buttonAnimation, cancelOverlayAnimation, clearCountdown, taskDetailsAnimation, buttonAnimation, cancelOverlayAnimation, taskDetailsAnimation,
timerAnimation, focusModeAnimation, duration, timerIsRunning, containerHeight, startProgressAnimation]); timerAnimation, focusModeAnimation, duration, timerIsRunning, containerHeight, startProgressAnimation]);
const renderTimerOverlay = () => ( return (
<View style={styles.container}
onLayout={(event) => {
setContainerHeight(event.nativeEvent.layout.height);
}}>
<StatusBar hidden />
<Animated.View <Animated.View
style={[StyleSheet.absoluteFillObject, { style={[StyleSheet.absoluteFillObject, {
height: containerHeight, height: containerHeight,
width, width,
backgroundColor: colors.red, backgroundColor: colors.red,
transform: [{ translateY: timerOverlayTranslateY }] transform: [{
translateY: timerOverlayTranslateY
}]
}]} }]}
/> />
);
const renderStartButton = () => (
<Animated.View <Animated.View
style={[ style={[
StyleSheet.absoluteFillObject, StyleSheet.absoluteFillObject,
@@ -493,17 +459,18 @@ export default function App() {
justifyContent: 'flex-end', justifyContent: 'flex-end',
alignItems: 'center', alignItems: 'center',
paddingBottom: 100, paddingBottom: 100,
opacity: startButtonOpacity, opacity,
transform: [{ translateY: startButtonTranslateY }] transform: [{
translateY
}]
}, },
]}> ]}>
<TouchableOpacity <TouchableOpacity
disabled={timerIsRunning} disabled={timerIsRunning}
onPress={startTimer} onPress={animation}
onPressIn={() => animateButtonPress(true)} onPressIn={() => animateButtonPress(true)}
onPressOut={() => animateButtonPress(false)}> onPressOut={() => animateButtonPress(false)}>
<Animated.View style={[ <Animated.View style={[styles.roundButton,
styles.roundButton,
{ {
transform: [{ scale: pressedButtonScale }], transform: [{ scale: pressedButtonScale }],
}, },
@@ -513,9 +480,6 @@ export default function App() {
</Animated.View> </Animated.View>
</TouchableOpacity> </TouchableOpacity>
</Animated.View> </Animated.View>
);
const renderCancelButton = () => (
<Animated.View <Animated.View
pointerEvents={timerIsRunning? 'auto' : 'none'} pointerEvents={timerIsRunning? 'auto' : 'none'}
style={[ style={[
@@ -528,21 +492,18 @@ export default function App() {
<TouchableOpacity <TouchableOpacity
onPressIn={startCancelHold} onPressIn={startCancelHold}
onPressOut={stopCancelHold}> onPressOut={stopCancelHold}>
<Animated.View style={[ <Animated.View style={[styles.cancelButton,
styles.cancelButton,
{ {
transform: [{ scale: pressedButtonScale }], transform: [{ scale: pressedButtonScale }],
}, },
]}> ]}
>
<Text className='text-text-main text-xl'>Hold to end sprint</Text> <Text className='text-text-main text-xl'>Hold to end sprint</Text>
</Animated.View> </Animated.View>
</TouchableOpacity> </TouchableOpacity>
</Animated.View> </Animated.View>
);
const renderCountdownOverlay = () => (
<Animated.View <Animated.View
pointerEvents="none" pointerEvents= 'none'
style={[ style={[
styles.countdownOverlay, { styles.countdownOverlay, {
opacity: countdownAnimation, opacity: countdownAnimation,
@@ -552,12 +513,10 @@ export default function App() {
{scale: countdownScale}, {scale: countdownScale},
], ],
}, },
]}> ]}
<Text style={styles.countdownText}>{formatTime(timeRemaining)}</Text> >
<Text style= {styles.countdownText}>{formatTime(timeRemaining)}</Text>
</Animated.View> </Animated.View>
);
const renderDurationPicker = () => (
<View <View
style={{ style={{
position: 'absolute', position: 'absolute',
@@ -566,6 +525,7 @@ export default function App() {
right: 0, right: 0,
flex: 1, flex: 1,
}}> }}>
<Animated.FlatList <Animated.FlatList
data={timers} data={timers}
scrollEnabled={!timerIsRunning} scrollEnabled={!timerIsRunning}
@@ -586,74 +546,58 @@ export default function App() {
const clampedIndex = Math.max(0, Math.min(index, timers.length - 1)); const clampedIndex = Math.max(0, Math.min(index, timers.length - 1));
setDuration(timers[clampedIndex]); setDuration(timers[clampedIndex]);
}} }}
snapToInterval={ITEM_SIZE} snapToInterval={ITEM_SIZE}
decelerationRate="fast" decelerationRate={"fast"}
style={{flexGrow: 0}} style={{flexGrow: 0}}
contentContainerStyle={{ contentContainerStyle={{
paddingHorizontal: ITEM_SPACING paddingHorizontal: ITEM_SPACING
}} }}
renderItem={({item, index}) => { renderItem={({item, index}) => {
const timerText = item;
const inputRange = [ const inputRange = [
(index - 1) * ITEM_SIZE, (index - 1) * ITEM_SIZE,
index * ITEM_SIZE, index * ITEM_SIZE,
(index + 1) * ITEM_SIZE, (index + 1) * ITEM_SIZE,
]; ]
const normalOpacity = scrollX.interpolate({ const normalOpacity = scrollX.interpolate({
inputRange, inputRange,
outputRange: [.4, 1, .4] outputRange: [.4, 1, .4]
}); })
const timerTextOpacity = Animated.multiply(normalOpacity, inactiveTimerNumberOpacity); const opacity = Animated.multiply(normalOpacity, inactiveTimerNumberOpacity);
const scale = scrollX.interpolate({ const scale = scrollX.interpolate({
inputRange, inputRange,
outputRange: [.7, 1, .7] outputRange: [.7, 1, .7]
}); })
return <View style={{width: ITEM_SIZE, justifyContent: 'center', alignItems: 'center'}}>
<Animated.Text style={[styles.text, {
opacity,
transform: [{
scale
}]
return ( }]}>
<View style={styles.timerItem}> {timerText}
<Animated.Text style={[
styles.text,
{
opacity: timerTextOpacity,
transform: [{ scale }]
}
]}>
{item}
</Animated.Text> </Animated.Text>
</View> </View>
); }
}} }
/> />
</View> </View>
);
const renderTaskDetails = () => (
<Animated.View <Animated.View
pointerEvents="none" pointerEvents="none"
style={[ style={[
styles.taskDetails, styles.taskDetails,
{ {
opacity: taskDetailsOpacity, opacity: taskDetailsOpacity,
transform: [{ translateY: taskDetailsTranslateY }] transform: [{
translateY: taskDetailsTranslateY
}]
} }
]}> ]}>
<Text style={styles.taskName}>{placeholderTask.name}</Text> <Text style={styles.taskName}>{placeholderTask.name}</Text>
<Text style={styles.taskDescription}>{placeholderTask.description}</Text> <Text style={styles.taskDescription}>{placeholderTask.description}</Text>
</Animated.View> </Animated.View>
);
return (
<View
style={styles.container}
onLayout={(event) => {
setContainerHeight(event.nativeEvent.layout.height);
}}>
<StatusBar hidden />
{renderTimerOverlay()}
{renderStartButton()}
{renderCancelButton()}
{renderCountdownOverlay()}
{renderDurationPicker()}
{renderTaskDetails()}
</View> </View>
); );
} }
@@ -677,11 +621,6 @@ const styles = StyleSheet.create({
color: colors.text, color: colors.text,
fontWeight: '900', fontWeight: '900',
}, },
timerItem: {
width: ITEM_SIZE,
justifyContent: 'center',
alignItems: 'center',
},
taskDetails: { taskDetails: {
position: 'absolute', position: 'absolute',
top: height * 0.34, top: height * 0.34,