@@ -40,6 +40,11 @@ const photoBooth = (function () {
4040 loaderMessage = loader . find ( '.stage-message' ) ,
4141 loaderImage = loader . find ( '.stage-image' ) ,
4242 resultPage = $ ( '.stage[data-stage="result"]' ) ,
43+ idleOverlay = $ ( '#idle-overlay' ) ,
44+ idleVideo = $ ( '#idle-video' ) ,
45+ idleImage = $ ( '#idle-image' ) ,
46+ idleTextTop = $ ( '#idle-text-top' ) ,
47+ idleTextBottom = $ ( '#idle-text-bottom' ) ,
4348 previewIpcam = $ ( '#preview--ipcam' ) ,
4449 previewVideo = $ ( '#preview--video' ) ,
4550 previewFramePicture = $ ( '#previewframe--picture' ) ,
@@ -61,7 +66,16 @@ const photoBooth = (function () {
6166 timeToLive = config . picture . time_to_live * 1000 ,
6267 continuousCollageTime = config . collage . continuous_time * 1000 ,
6368 retryTimeout = config . picture . retry_timeout * 1000 ,
64- notificationTimeout = config . ui . notification_timeout * 1000 ;
69+ notificationTimeout = config . ui . notification_timeout * 1000 ,
70+ idleMode = config . idle . mode ,
71+ idleEnabled =
72+ config . idle . enabled &&
73+ config . idle . timeout_minutes > 0 &&
74+ ( idleMode === 'gallery' ||
75+ idleMode === 'folder' ||
76+ ( idleMode === 'video' ? ! ! config . idle . video_source : ! ! config . idle . image_source ) ) ,
77+ idleTimeoutMs = ( config . idle . timeout_minutes || 0 ) * 60000 ,
78+ idleSwitchMs = ( config . idle . switch_minutes || 1 ) * 60000 ;
6579
6680 let timeOut ,
6781 chromaFile = '' ,
@@ -71,7 +85,10 @@ const photoBooth = (function () {
7185 command ,
7286 startTime ,
7387 endTime ,
74- totalTime ;
88+ totalTime ,
89+ idleTimeout ,
90+ idleSwitchTimeout ,
91+ idleLastTextTop = true ;
7592
7693 api . takingPic = false ;
7794 api . nextCollageNumber = 0 ;
@@ -136,6 +153,136 @@ const photoBooth = (function () {
136153 rotaryController . focusSet ( startPage ) ;
137154
138155 initPhotoSwipeFromDOM ( '#galimages' ) ;
156+
157+ api . idle . resetTimer ( ) ;
158+ } ;
159+
160+ api . idle = {
161+ pickImageFromGallery : function ( ) {
162+ const anchors = $ ( '#galimages a' ) ;
163+ if ( ! anchors . length ) {
164+ return '' ;
165+ }
166+ const randomIndex = Math . floor ( Math . random ( ) * anchors . length ) ;
167+ return $ ( anchors [ randomIndex ] ) . attr ( 'href' ) ;
168+ } ,
169+ resolveSource : function ( ) {
170+ const base = environment . publicFolders . api ;
171+ switch ( idleMode ) {
172+ case 'video' :
173+ return config . idle . video_source ;
174+ case 'image' :
175+ return config . idle . image_source ;
176+ case 'folder' :
177+ return base + '/randomImg.php?dir=' + encodeURIComponent ( 'screensavers' ) ;
178+ case 'gallery' :
179+ return api . idle . pickImageFromGallery ( ) ;
180+ default :
181+ return '' ;
182+ }
183+ } ,
184+ hide : function ( ) {
185+ if ( ! idleOverlay . length ) {
186+ return ;
187+ }
188+ idleOverlay . removeClass ( 'idle-overlay--active' ) ;
189+ startPage . removeClass ( 'stage--idle' ) ;
190+ clearTimeout ( idleSwitchTimeout ) ;
191+ if ( idleVideo . length ) {
192+ const vid = idleVideo . get ( 0 ) ;
193+ vid . pause ( ) ;
194+ vid . currentTime = 0 ;
195+ idleVideo . attr ( 'src' , '' ) ;
196+ }
197+ idleImage . hide ( ) . attr ( 'src' , '' ) ;
198+ idleTextTop . text ( '' ) . hide ( ) ;
199+ idleTextBottom . text ( '' ) . hide ( ) ;
200+ } ,
201+ toggleGalleryText : function ( ) {
202+ const text = config . idle . gallery_text ;
203+
204+ if ( ! text ) {
205+ idleTextTop . hide ( ) ;
206+ idleTextBottom . hide ( ) ;
207+ return ;
208+ }
209+
210+ if ( idleLastTextTop ) {
211+ idleTextBottom . text ( text ) . show ( ) ;
212+ idleTextTop . hide ( ) ;
213+ } else {
214+ idleTextTop . text ( text ) . show ( ) ;
215+ idleTextBottom . hide ( ) ;
216+ }
217+
218+ idleLastTextTop = ! idleLastTextTop ;
219+ } ,
220+ show : function ( ) {
221+ if ( ! idleEnabled || ! idleOverlay . length ) {
222+ return ;
223+ }
224+ if ( ! startPage . hasClass ( 'stage--active' ) ) {
225+ api . idle . resetTimer ( ) ;
226+ return ;
227+ }
228+
229+ const mode = idleMode ;
230+ const source = api . idle . resolveSource ( ) ;
231+ if ( ! source ) {
232+ api . idle . resetTimer ( ) ;
233+ return ;
234+ }
235+
236+ if ( mode === 'video' ) {
237+ idleOverlay . css ( 'background-image' , 'none' ) ;
238+ idleVideo . attr ( 'src' , source || '' ) ;
239+ idleVideo . show ( ) ;
240+ const vid = idleVideo . get ( 0 ) ;
241+ vid . play ( ) . catch ( ( ) => { } ) ;
242+ idleImage . hide ( ) ;
243+ idleTextTop . hide ( ) ;
244+ idleTextBottom . hide ( ) ;
245+ } else if ( mode === 'gallery' ) {
246+ idleVideo . hide ( ) ;
247+ idleOverlay . css ( 'background-image' , 'none' ) ;
248+ idleImage . attr ( 'src' , source ) . show ( ) ;
249+ api . idle . toggleGalleryText ( ) ;
250+ } else {
251+ idleVideo . hide ( ) ;
252+ idleImage . hide ( ) ;
253+ idleTextTop . hide ( ) ;
254+ idleTextBottom . hide ( ) ;
255+ idleOverlay . css ( 'background-image' , source ? `url(${ source } )` : 'none' ) ;
256+ idleOverlay . css ( 'background-size' , 'cover' ) ;
257+ }
258+
259+ startPage . addClass ( 'stage--idle' ) ;
260+ idleOverlay . addClass ( 'idle-overlay--active' ) ;
261+
262+ clearTimeout ( idleSwitchTimeout ) ;
263+ if ( ( mode === 'folder' || mode === 'gallery' ) && idleSwitchMs > 0 ) {
264+ idleSwitchTimeout = setTimeout ( function nextIdleFrame ( ) {
265+ const nextSource = api . idle . resolveSource ( ) ;
266+ if ( nextSource ) {
267+ if ( mode === 'folder' ) {
268+ idleOverlay . css ( 'background-image' , `url(${ nextSource } )` ) ;
269+ } else if ( mode === 'gallery' ) {
270+ idleImage . attr ( 'src' , nextSource ) . show ( ) ;
271+ api . idle . toggleGalleryText ( ) ;
272+ }
273+ }
274+ idleSwitchTimeout = setTimeout ( nextIdleFrame , idleSwitchMs ) ;
275+ } , idleSwitchMs ) ;
276+ }
277+ } ,
278+ resetTimer : function ( ) {
279+ if ( ! idleEnabled ) {
280+ return ;
281+ }
282+ clearTimeout ( idleTimeout ) ;
283+ api . idle . hide ( ) ;
284+ idleTimeout = setTimeout ( api . idle . show , idleTimeoutMs ) ;
285+ }
139286 } ;
140287
141288 api . navbar = {
@@ -503,6 +650,7 @@ const photoBooth = (function () {
503650 videoBackground . hide ( ) ;
504651 startPage . removeClass ( 'stage--active' ) ;
505652 loader . addClass ( 'stage--active' ) ;
653+ api . idle . hide ( ) ;
506654
507655 if ( config . get_request . countdown ) {
508656 let getMode ;
@@ -1250,6 +1398,8 @@ const photoBooth = (function () {
12501398 if ( config . commands . post_photo ) {
12511399 api . shellCommand ( 'post-command' , filename ) ;
12521400 }
1401+
1402+ api . idle . resetTimer ( ) ;
12531403 } ;
12541404
12551405 api . addImage = function ( imageName ) {
@@ -1460,6 +1610,17 @@ const photoBooth = (function () {
14601610 rotaryController . focusSet ( startPage ) ;
14611611 } ) ;
14621612
1613+ if ( idleEnabled ) {
1614+ $ ( document ) . on ( 'click touchstart keydown mousemove' , function ( ) {
1615+ api . idle . resetTimer ( ) ;
1616+ } ) ;
1617+
1618+ idleOverlay . on ( 'click touchstart' , function ( e ) {
1619+ e . preventDefault ( ) ;
1620+ api . idle . resetTimer ( ) ;
1621+ } ) ;
1622+ }
1623+
14631624 $ ( '.cups-button' ) . on ( 'click' , function ( ev ) {
14641625 ev . preventDefault ( ) ;
14651626
0 commit comments