Skip to content

Commit

Permalink
added more timer functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
ginny100 committed Dec 27, 2024
1 parent 0aca126 commit 7f524c3
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 102 deletions.
6 changes: 3 additions & 3 deletions packages/storage/lib/impl/zenStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ type ZenStorage = BaseStorage<ZenSettings> & {
};

const defaultSettings: ZenSettings = {
sessions: 0,
focusMinutes: 0,
breakMinutes: 0,
sessions: 1,
focusMinutes: 3, // Human Comments: For testing, set to 3, otherwise set to 25
breakMinutes: 2, // Human Comments: For testing, set to 2, otherwise set to 5
blockedApps: [],
timerActive: false,
currentSession: 1,
Expand Down
12 changes: 6 additions & 6 deletions pages/popup/src/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ const NumberInput = ({ label, value, onChange, suffix, isLight, type }: NumberIn
onChange(0);
break;
}
const focusValues = [25, 50, 100, 200];
const focusValues = [1,2,3]; // Human Comments: For testing, set to [3], otherwise set to [25, 50, 100, 200]

Check failure on line 254 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
const closestFocus = focusValues.reduce((prev, curr) =>

Check failure on line 255 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
Math.abs(curr - newValue) < Math.abs(prev - newValue) ? curr : prev
);
Expand All @@ -262,7 +262,7 @@ const NumberInput = ({ label, value, onChange, suffix, isLight, type }: NumberIn
onChange(0);
break;
}
const breakValues = [5, 10, 20, 40];
const breakValues = [1,2,3]; // Human Comments: For testing, set to [2], otherwise set to [5, 10, 20, 40]

Check failure on line 265 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
const closestBreak = breakValues.reduce((prev, curr) =>

Check failure on line 266 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
Math.abs(curr - newValue) < Math.abs(prev - newValue) ? curr : prev
);
Expand All @@ -281,7 +281,7 @@ const NumberInput = ({ label, value, onChange, suffix, isLight, type }: NumberIn
onChange(25);
break;
}
const focusValues = [25, 50, 100, 200];
const focusValues = [1, 2, 3]; // Human Comments: For testing, set to [1,2,3], otherwise set to [25, 50, 100, 200]

Check failure on line 284 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
const nextFocus = focusValues.find(v => v > value) ?? 200;

Check failure on line 285 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
onChange(nextFocus);
break;
Expand All @@ -290,7 +290,7 @@ const NumberInput = ({ label, value, onChange, suffix, isLight, type }: NumberIn
onChange(5);
break;
}
const breakValues = [5, 10, 20, 40];
const breakValues = [1, 2, 3]; // Human Comments: For testing, set to [1,2,3], otherwise set to [5, 10, 20, 40]

Check failure on line 293 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
const nextBreak = breakValues.find(v => v > value) ?? 40;

Check failure on line 294 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
onChange(nextBreak);
break;
Expand All @@ -303,12 +303,12 @@ const NumberInput = ({ label, value, onChange, suffix, isLight, type }: NumberIn
onChange(Math.max(0, value - 1));
break;
case 'focus':
const focusValues = [0, 25, 50, 100, 200];
const focusValues = [0, 1, 2, 3]; // Human Comments: For testing, set to [0, 1, 2, 3], otherwise set to [0, 25, 50, 100, 200]

Check failure on line 306 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
const prevFocus = focusValues.reverse().find(v => v < value) ?? 0;

Check failure on line 307 in pages/popup/src/Popup.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected lexical declaration in case block
onChange(prevFocus);
break;
case 'break':
const breakValues = [0, 5, 10, 20, 40];
const breakValues = [0, 1, 2, 3]; // Human Comments: For testing, set to [0, 1, 2, 3], otherwise set to [0, 5, 10, 20, 40]
const prevBreak = breakValues.reverse().find(v => v < value) ?? 0;
onChange(prevBreak);
break;
Expand Down
231 changes: 138 additions & 93 deletions pages/popup/src/Timer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { themeStorage } from '@extension/storage';
import ThemeSwitcher from './components/ThemeSwitcher';
import { useEffect, useState } from 'react';
import { zenStorage } from '@extension/storage';
import ConfirmDialog from './components/ConfirmDialog';

interface TimerProps {
onBack: () => void;
Expand Down Expand Up @@ -33,6 +34,7 @@ const Timer = ({ onBack, sessions, focusMinutes, breakMinutes }: TimerProps) =>
return Math.max(0, zenSettings.timeLeft - elapsedSeconds);
});
const [isRunning, setIsRunning] = useState(zenSettings.timerActive);
const [showConfirm, setShowConfirm] = useState(false);

// Persist timer state changes
useEffect(() => {
Expand All @@ -52,20 +54,54 @@ const Timer = ({ onBack, sessions, focusMinutes, breakMinutes }: TimerProps) =>
setTimeLeft(prev => {
if (prev <= 1) {
if (timerState === 'focus') {
if (currentSession < sessions) {
// Focus time is up
if (currentSession <= sessions) { // Changed from < to <= since we're still in current session
// Start break time for current session
const newBreakTime = breakMinutes * 60;
setTimerState('break');
return breakMinutes * 60;
zenStorage.updateTimerState({
timerActive: true,
currentSession, // Keep same session number during break
timerState: 'break',
timeLeft: newBreakTime
});
return newBreakTime;
}
} else {
// Break time is up
if (currentSession < sessions) {
// Start next session's focus time
const nextSession = currentSession + 1;
const newFocusTime = focusMinutes * 60;
setTimerState('focus');
setCurrentSession(nextSession);
zenStorage.updateTimerState({
timerActive: true,
currentSession: nextSession,
timerState: 'focus',
timeLeft: newFocusTime
});
return newFocusTime;
} else {
// All sessions completed (after last break)
setIsRunning(false);
zenStorage.updateTimerState({
timerActive: false,
timeLeft: 0
});
return 0;
}
} else {
setTimerState('focus');
setCurrentSession(prev => prev + 1);
return focusMinutes * 60;
}
}
return prev - 1;
// Normal countdown
const newTime = prev - 1;
zenStorage.updateTimerState({
timerActive: true,
currentSession,
timerState,
timeLeft: newTime
});
return newTime;
});
}, 1000);

Expand All @@ -85,15 +121,7 @@ const Timer = ({ onBack, sessions, focusMinutes, breakMinutes }: TimerProps) =>

const handleBackClick = () => {
if (isRunning) {
if (window.confirm('Timer is still running. Are you sure you want to go back?')) {
zenStorage.updateTimerState({
timerActive: false,
currentSession: 1,
timerState: 'focus',
timeLeft: 0
});
onBack();
}
setShowConfirm(true);
} else {
zenStorage.updateTimerState({
timerActive: false,
Expand All @@ -105,92 +133,109 @@ const Timer = ({ onBack, sessions, focusMinutes, breakMinutes }: TimerProps) =>
}
};

const handleConfirm = () => {
zenStorage.updateTimerState({
timerActive: false,
currentSession: 1,
timerState: 'focus',
timeLeft: 0
});
onBack();
};

return (
<div className={`App size-full overflow-hidden p-2 transition-colors ${
isLight ? 'bg-[#CDE8F6]' : 'bg-[#364E68]'
}`}>
<ThemeSwitcher />

{/* Box Wrapper */}
<div className={`mx-8 my-9 rounded-xl p-4 shadow-lg shadow-black/20 ${
isLight ? 'bg-[#F8FAFC]' : 'bg-[#27374D]'
<>
<div className={`App size-full overflow-hidden p-2 transition-colors ${
isLight ? 'bg-[#CDE8F6]' : 'bg-[#364E68]'
}`}>
<div className="flex flex-col items-center justify-between">
<h1 className={`text-4xl font-['Agbalumo'] ${
isLight ? 'text-gray-900' : 'text-white'
}`}>
Focus Time
</h1>

{/* Timer Circle */}
<div className="my-9 relative flex size-64 items-center justify-center">
{/* SVG Circle */}
<svg className="absolute size-full -rotate-90">
{/* Background Circle - White */}
<circle
cx="128"
cy="128"
r="120"
fill="none"
stroke="white"
strokeWidth="12"
/>
{/* Progress Circle - Blue */}
<circle
cx="128"
cy="128"
r="120"
fill="none"
stroke={isLight ? '#769FCD' : '#B9D7EA'}
strokeWidth="12"
strokeDasharray={`${progress * 7.54} 754`}
strokeLinecap="round"
className="transition-all"
/>
</svg>

{/* Timer Display */}
<div className={`z-10 font-['Inria_Sans'] text-7xl font-normal ${
isLight ? 'text-[#1E1E1E]' : 'text-[#F8FAFC]'
<ThemeSwitcher />

{/* Box Wrapper */}
<div className={`mx-8 my-9 rounded-xl p-4 shadow-lg shadow-black/20 ${
isLight ? 'bg-[#F8FAFC]' : 'bg-[#27374D]'
}`}>
<div className="flex flex-col items-center justify-between">
<h1 className={`text-4xl font-['Agbalumo'] transition-all ${
isLight ? 'text-gray-900' : 'text-white'
}`}>
{formatTime(timeLeft)}
{timerState === 'focus' ? 'Focus Time' : 'Break Time'}
</h1>

{/* Timer Circle */}
<div className="my-9 relative flex size-64 items-center justify-center">
{/* SVG Circle */}
<svg className="absolute size-full -rotate-90">
{/* Background Circle - White */}
<circle
cx="128"
cy="128"
r="120"
fill="none"
stroke={isLight ? '#F8FAFC' : '#27374D'}
strokeWidth="12"
/>
{/* Progress Circle - Blue */}
<circle
cx="128"
cy="128"
r="120"
fill="none"
stroke={isLight ? '#769FCD' : '#B9D7EA'}
strokeWidth="12"
strokeDasharray={`${progress * 7.54} 754`}
strokeLinecap="round"
className="transition-all"
/>
</svg>

{/* Timer Display */}
<div className={`z-10 font-['Inria_Sans'] text-7xl font-normal ${
isLight ? 'text-[#1E1E1E]' : 'text-[#F8FAFC]'
}`}>
{formatTime(timeLeft)}
</div>
</div>
</div>

{/* Lotus Icons */}
<div className="flex gap-4">
{Array(sessions).fill('🪷').map((lotus, index) => (
<span
key={index}
role="img"
aria-label="lotus"
className="text-4xl"
style={{
filter: 'saturate(1.5) brightness(1.1)',
transform: 'scale(1.2)',
opacity: index < currentSession ? 0.4 : 1
}}
>
{lotus}
</span>
))}
{/* Lotus Icons */}
<div className="flex gap-4">
{Array(sessions).fill('🪷').map((lotus, index) => (
<span
key={index}
role="img"
aria-label="lotus"
className="text-4xl"
style={{
filter: 'saturate(1.5) brightness(1.1)',
transform: 'scale(1.2)',
opacity: index < currentSession ? 0.4 : 1
}}
>
{lotus}
</span>
))}
</div>
</div>
</div>
</div>

{/* Back Button */}
<div className="mt-4 flex justify-center">
<button
onClick={handleBackClick}
className={`rounded-full px-8 py-2 text-xl font-bold shadow-lg shadow-black/20 transition-colors ${
isLight
? 'bg-[#39A2DB] hover:bg-[#769FCD] text-[#1E1E1E]'
: 'bg-[#91C8E4] hover:bg-[#B9D7EA] text-[#F8FAFC]'
}`}>
Back
</button>
{/* Back Button */}
<div className="mt-4 flex justify-center">
<button
onClick={handleBackClick}
className={`rounded-full px-8 py-2 text-xl font-bold shadow-lg shadow-black/20 transition-colors ${
isLight
? 'bg-[#39A2DB] hover:bg-[#769FCD] text-[#1E1E1E]'
: 'bg-[#91C8E4] hover:bg-[#B9D7EA] text-[#F8FAFC]'
}`}>
Back
</button>
</div>
</div>
</div>
<ConfirmDialog
isOpen={showConfirm}
onConfirm={handleConfirm}
onCancel={() => setShowConfirm(false)}
/>
</>
);
};

Expand Down

0 comments on commit 7f524c3

Please sign in to comment.