11// fetch params in url for quick settings
2- import { updateTimer } from "./utils.mjs" ;
2+ import { updateBackground , updateTimer , parseDuration } from "./utils.mjs" ;
3+ import { showSettings , hideSettings , submitSettings , resetDefaultSettings , initSettings } from "./settings.mjs" ;
34
45// Lecture du paramètre "duration" dans l'URL (en secondes)
56const params = new URLSearchParams ( globalThis . location . search ) ;
@@ -18,128 +19,10 @@ let pause = true;
1819const pauseChar = '⏸️' ;
1920const playChar = '▶️' ;
2021
21- const defaultSettings = {
22- "durationInSeconds" : 600 ,
23- "showTimer" : true ,
24- "colorScheme" : "zenika-colors" ,
25- "firstThreshold" : 0.8 ,
26- "secondThreshold" : 0.9 ,
27- "thirdThreshold" : 0.95 ,
28- "soundEnabled" : false ,
29- "orientation" : "upward"
30- }
31-
32- let settings = {
33- "durationInSeconds" : parseDuration ( params . get ( "duration" ) ) ,
34- "showTimer" : true ,
35- "colorScheme" : "zenika-colors" ,
36- "firstThreshold" : 0.8 ,
37- "secondThreshold" : 0.9 ,
38- "thirdThreshold" : 0.95 ,
39- "soundEnabled" : params . get ( "sound" ) === "true" ,
40- "orientation" : "upward"
41- }
42-
4322let wakeLock = null ;
4423
45-
46- // ------------- Settings ----------------
47-
48- function parseDuration ( durationStr ) {
49- const DEFAULT = 600 ; // 10 minutes by default
50- if ( ! durationStr ) return DEFAULT ;
51-
52- durationStr = durationStr . toLowerCase ( ) . trim ( ) ;
53- let totalSeconds = 0 ;
54- const regex = / ( \d + ) ( [ m s : ] ? ) / g;
55- let match ;
56- let found = false ;
57-
58- while ( ( match = regex . exec ( durationStr ) ) !== null ) {
59- found = true ;
60- const value = Number . parseInt ( match [ 1 ] , 10 ) ;
61- const unit = match [ 2 ] || "s" ;
62- if ( unit === "m" || unit === ":" ) {
63- totalSeconds += value * 60 ;
64- } else {
65- totalSeconds += value ;
66- }
67- }
68-
69- if ( ! found || totalSeconds <= 0 ) {
70- console . warn ( `Durée invalide ("${ durationStr } "), utilisation de la valeur par défaut: ${ DEFAULT } s` ) ;
71- return DEFAULT ;
72- }
73- return totalSeconds ;
74- }
75-
76-
77- function showSettings ( ) {
78- settingsModal . showModal ( ) ;
79- }
80-
81- function hideSettings ( ) {
82- settingsModal . close ( ) ;
83- }
84-
85- function submitSettings ( ) {
86- settings . durationInSeconds = Number ( settingsForm [ "durationMinutes" ] . value * 60 ) + Number ( settingsForm [ "durationSeconds" ] . value )
87- settings . colorScheme = settingsForm [ "color-scheme" ] . value ;
88- settings . showTimer = settingsForm [ "show-timer" ] . checked ;
89- settings . firstThreshold = settingsForm [ "threshold1" ] . value / 100 ;
90- settings . secondThreshold = settingsForm [ "threshold2" ] . value / 100 ;
91- settings . thirdThreshold = settingsForm [ "threshold3" ] . value / 100 ;
92- settings . soundEnabled = settingsForm [ "play-sound" ] . checked ;
93- settings . orientation = settingsForm [ "orientation" ] . value ;
94-
95- applySettings ( ) ;
96- hideSettings ( ) ;
97- }
98-
99- function applySettings ( ) {
100- timer . textContent = updateTimer ( settings . durationInSeconds ) ;
101- document . documentElement . className = settings . colorScheme ;
102-
103- if ( settings . showTimer === false ) {
104- // maybe only hide the timer once it's started, but keep it visible until start to show the duration?
105- timer . style . display = "none" ;
106- } else {
107- timer . style . display = "block" ;
108- }
109-
110- updateSettingsForm ( ) ;
111-
112- // Currently : apply changes to running timer. Maybe start the timer over?
113- }
114-
115- function updateSettingsForm ( ) {
116- // Apply the settings to the form so it reflects current settings
117- settingsForm [ "durationMinutes" ] . value = Math . floor ( settings . durationInSeconds / 60 ) ;
118- settingsForm [ "durationSeconds" ] . value = settings . durationInSeconds % 60 ;
119- settingsForm [ "show-timer" ] . checked = settings . showTimer ;
120- settingsForm [ "color-scheme" ] . value = settings . colorScheme ;
121- settingsForm [ "threshold1" ] . value = settings . firstThreshold * 100 ;
122- settingsForm [ "threshold2" ] . value = settings . secondThreshold * 100 ;
123- settingsForm [ "threshold3" ] . value = settings . thirdThreshold * 100 ;
124- settingsForm [ "play-sound" ] . checked = settings . soundEnabled ;
125- settingsForm [ "orientation" ] . value = settings . orientation ;
126- }
127-
128- function resetDefaultSettings ( ) {
129- settings = defaultSettings ;
130- updateSettingsForm ( ) ;
131- }
132-
13324// ------------- Animation ----------------
134- function getClassByProgress ( p ) {
135- // p = percentage between 0 and 1
136- if ( p < settings . firstThreshold ) return 'start' ;
137- if ( p < settings . secondThreshold ) return 'critical' ;
138- if ( p < settings . thirdThreshold ) return 'very-critical' ;
139- return 'ending' ;
140- }
141-
142- function switchPause ( ) {
25+ function switchPause ( settings ) {
14326 pause = ! pause ;
14427 if ( pause ) {
14528 displayStart ( ) ;
@@ -148,7 +31,7 @@ function switchPause() {
14831 timer . classList . add ( "pause" ) ;
14932 timer . setAttribute ( 'title' , "Click to continue" ) ;
15033 } else {
151- startAnimation ( performance . now ( ) - elapsed )
34+ startAnimation ( performance . now ( ) - elapsed , settings )
15235 timer . classList . remove ( "blinking" ) ;
15336 timer . classList . remove ( "pause" ) ;
15437 timer . title = "Click to pause" ;
@@ -165,31 +48,28 @@ function displayStart() {
16548 startBtn . title = 'start' ;
16649}
16750
168- function updateBackground ( progress ) {
169- const currentHeight = Math . floor ( totalHeight * progress ) ;
170- background . style . height = `${ currentHeight } px` ;
171- background . classList = getClassByProgress ( progress ) ;
172- }
17351
174- function startAnimation ( startTime = performance . now ( ) ) {
52+
53+ function startAnimation ( startTime = performance . now ( ) , settings ) {
17554 requestWakeLock ( ) ;
17655 displayPause ( ) ;
56+ const { durationInSeconds } = settings ;
17757
178- function animate ( time , durationInSeconds = settings . durationInSeconds ) {
58+ function animate ( time ) {
17959 elapsed = time - startTime ;
18060 const progress = Math . min ( elapsed / ( durationInSeconds * 1000 ) , 1 ) ; // 0 → 1
18161 const remaining = durationInSeconds - ( elapsed / 1000 ) ;
18262 timer . textContent = updateTimer ( remaining ) ;
18363
184- updateBackground ( progress )
64+ updateBackground ( { background , totalHeight , progress, settings } )
18565
18666 if ( pause ) {
18767 return ;
18868 } else if ( progress < 1 ) {
18969 requestAnimationFrame ( animate ) ;
19070 } else {
19171 timer . textContent = "00:00" ;
192- playBeep ( ) ;
72+ playBeep ( settings ) ;
19373 timer . classList . add ( "blinking" ) ; // démarre le clignotement
19474
19575 // Arrête le clignotement après 5 secondes
@@ -216,7 +96,7 @@ async function requestWakeLock() {
21696 }
21797}
21898
219- function playBeep ( ) {
99+ function playBeep ( settings ) {
220100 if ( ! settings . soundEnabled ) return ;
221101
222102 const AudioContext = window . AudioContext || window . webkitAudioContext ;
@@ -236,23 +116,40 @@ function playBeep() {
236116 oscillator . stop ( audioCtx . currentTime + 0.3 ) ; // play for 0.3s
237117}
238118
119+ function applySettings ( settings , timer ) {
120+ timer . textContent = updateTimer ( settings . durationInSeconds ) ;
121+ document . documentElement . className = settings . colorScheme ;
122+
123+ if ( settings . showTimer === false ) {
124+ // maybe only hide the timer once it's started, but keep it visible until start to show the duration?
125+ timer . style . display = "none" ;
126+ } else {
127+ timer . style . display = "block" ;
128+ }
129+ }
130+
239131
240132export function init ( ) {
133+ const settings = initSettings ( {
134+ durationInSeconds : parseDuration ( params . get ( "duration" ) ) , soundEnabled : params . get ( "sound" ) === "true" , settingsModalElement : settingsModal , settingsFormElement : settingsForm
135+ } )
136+
241137 // Wakelock: réactiver si la page revient au premier plan
242138 document . addEventListener ( 'visibilitychange' , ( ) => {
243139 if ( wakeLock !== null && document . visibilityState === 'visible' ) {
244140 requestWakeLock ( ) ;
245141 }
246142 } ) ;
247143
248-
249144 showSettingsBtn . addEventListener ( 'click' , showSettings ) ;
250145 closeSettingsBtn . addEventListener ( 'click' , hideSettings ) ;
251146 resetBtn . addEventListener ( 'click' , resetDefaultSettings ) ;
252- submitBtn . addEventListener ( 'click' , submitSettings ) ;
253- startBtn . addEventListener ( 'click' , switchPause ) ;
254- displayStart ( ) ;
147+ submitBtn . addEventListener ( 'click' , ( ) => {
148+ submitSettings ( )
149+ applySettings ( settings , timer ) ;
150+ } ) ;
151+ startBtn . addEventListener ( 'click' , ( ) => switchPause ( settings ) ) ;
255152
256- applySettings ( ) ;
153+ displayStart ( ) ;
154+ applySettings ( settings , timer ) ;
257155}
258-
0 commit comments