/* * Copyright (c) 2015-2017, Michael A. Updike All rights reserved. * Licensed under the BSD-3-Clause * https://opensource.org/licenses/BSD-3-Clause * https://github.com/opus1269/photo-screen-saver/blob/master/LICENSE.md */ window.app = window.app || {}; /** * Control the running of a {@link app.Screensaver} * @namespace */ app.SSRunner = (function() { 'use strict'; new ExceptionHandler(); /** * Instance variables * @type {Object} * @property {boolean} started - true if slideshow started * @property {int} replaceIdx - page to replace with next photo * @property {int} lastSelected - last selected page * @property {int} waitTime - wait time when looking for photo in milliSecs * @property {boolean} interactive - is interaction allowed * @property {boolean} paused - is screensaver paused * @property {number} timeOutId - id of setTimeout * @private * @memberOf app.SSRunner */ const _VARS = { started: false, replaceIdx: -1, lastSelected: -1, waitTime: 30000, interactive: false, paused: false, timeOutId: 0, }; /** * Stop the animation * @private * @memberOf app.SSRunner */ function _stop() { window.clearTimeout(_VARS.timeOutId); } /** * Restart the slideshow * @param {?int} [newIdx=null] optional idx to use for current idx * @private * @memberOf app.SSRunner */ function _restart(newIdx = null) { const transTime = Chrome.Storage.get('transitionTime'); if (transTime) { app.SSRunner.setWaitTime(transTime.base * 1000); } _runShow(newIdx); } /** * Increment the slide show manually * @param {?int} [newIdx=null] optional idx to use for current idx * @private * @memberOf app.SSRunner */ function _step(newIdx = null) { if (app.SSRunner.isPaused()) { app.SSRunner.togglePaused(newIdx); app.SSRunner.togglePaused(); } else { _stop(); _restart(newIdx); } } /** * Self called at fixed time intervals to cycle through the photos * @param {?int} [newIdx=null] override selected * @private * @memberOf app.SSRunner */ function _runShow(newIdx = null) { if (app.Screensaver.noPhotos()) { // no usable photos to show return; } const selected = app.SSViews.getSelectedIndex(); const viewLen = app.SSViews.getCount(); let curIdx = (newIdx === null) ? selected : newIdx; curIdx = !app.SSRunner.isStarted() ? 0 : curIdx; let nextIdx = (curIdx === viewLen - 1) ? 0 : curIdx + 1; if (!app.SSRunner.isStarted()) { // special case for first page. neon-animated-pages is configured // to run the entry animation for the first selection nextIdx = 0; } nextIdx = app.SSFinder.getNext(nextIdx); if (nextIdx !== -1) { // the next photo is ready if (!app.SSRunner.isStarted()) { _VARS.started = true; app.SSTime.setTime(); } // setup photo const view = app.SSViews.get(nextIdx); view.render(); // track the photo history app.SSHistory.add(newIdx, nextIdx, _VARS.replaceIdx); // update selected so the animation runs _VARS.lastSelected = selected; app.SSViews.setSelectedIndex(nextIdx); if (newIdx === null) { // load next photo from master array app.SSFinder.replacePhoto(_VARS.replaceIdx); _VARS.replaceIdx = _VARS.lastSelected; } } // set the next timeout, then call ourselves - runs unless interrupted _VARS.timeOutId = window.setTimeout(() => { _runShow(); }, _VARS.waitTime); } return { /** * Start the slideshow * @param {int} [delay=2000] - delay before start * @memberOf app.SSRunner */ start: function(delay = 2000) { const transTime = Chrome.Storage.get('transitionTime'); if (transTime) { app.SSRunner.setWaitTime(transTime.base * 1000); } _VARS.interactive = Chrome.Storage.get('interactive'); app.SSHistory.initialize(); // start slide show. slight delay at beginning so we have a smooth start window.setTimeout(_runShow, delay); }, /** * Get wait time between _runShow calls * @returns {int} current wait time * @memberOf app.SSRunner */ getWaitTime: function() { return _VARS.waitTime; }, /** * Set wait time between _runShow calls in milliSecs * @param {int} waitTime - wait time for next attempt to get photo * @memberOf app.SSRunner */ setWaitTime: function(waitTime) { _VARS.waitTime = waitTime; }, /** * Set last selected index * @param {int} lastSelected - last index in {@link app.SSViews} * @memberOf app.SSRunner */ setLastSelected: function(lastSelected) { _VARS.lastSelected = lastSelected; }, /** * Set last selected index * @param {int} idx - replace index in {@link app.SSViews} * @memberOf app.SSRunner */ setReplaceIdx: function(idx) { _VARS.replaceIdx = idx; }, /** * Has the first page run * @returns {boolean} if animation has started * @memberOf app.SSRunner */ isStarted: function() { return _VARS.started; }, /** * Is interactive mode allowed * @returns {boolean} true if allowed * @memberOf app.SSRunner */ isInteractive: function() { return _VARS.interactive; }, /** * Are we paused * @returns {boolean} true if paused * @memberOf app.SSRunner */ isPaused: function() { return _VARS.paused; }, /** * Is the given idx a part of the current animation pair * @param {int} idx - index into {@link app.SSViews} * @returns {boolean} if selected or last selected * @memberOf app.SSRunner */ isCurrentPair: function(idx) { const selected = app.SSViews.getSelectedIndex(); return ((idx === selected) || (idx === _VARS.lastSelected)); }, /** * Toggle paused state of the slideshow * @param {?int} [newIdx=null] optional idx to use for current idx * @memberOf app.SSRunner */ togglePaused: function(newIdx = null) { if (_VARS.started) { _VARS.paused = !_VARS.paused; app.Screensaver.setPaused(_VARS.paused); if (_VARS.paused) { _stop(); } else { _restart(newIdx); } } }, /** * Forward one slide * @memberOf app.SSRunner */ forward: function() { if (_VARS.started) { _step(); } }, /** * Backup one slide * @memberOf app.SSRunner */ back: function() { if (_VARS.started) { const nextStep = app.SSHistory.back(); if (nextStep !== null) { _step(nextStep); } } }, }; })();