BangleApps/apps/pomoplus/common.js

118 lines
5.9 KiB
JavaScript

const storage = require("Storage");
const heatshrink = require("heatshrink");
exports.STATE_PATH = "pomoplus.state.json";
exports.SETTINGS_PATH = "pomoplus.json";
exports.PHASE_WORKING = 0;
exports.PHASE_SHORT_BREAK = 1;
exports.PHASE_LONG_BREAK = 2;
exports.BUTTON_ICONS = {
play: heatshrink.decompress(atob("jEYwMAkAGBnACBnwCBn+AAQPgAQPwAQP8AQP/AQXAAQPwAQP8AQP+AQgICBwQUCEAn4FggyBHAQ+CIgQ")),
pause: heatshrink.decompress(atob("jEYwMA/4BBAX4CEA")),
reset: heatshrink.decompress(atob("jEYwMA/4BB/+BAQPDAQPnAQIAKv///0///8j///EP//wAQQICBwQUCEhgyCHAQ+CIgI=")),
skip: heatshrink.decompress(atob("jEYwMAwEIgHAhkA8EOgHwh8A/EPwH8h/A/0P8H/h/w/+P/H/5/8//v/3/AAoICBwQUCDQIgCEwQsCGQQ4CHwRECA"))
};
exports.settings = storage.readJSON(exports.SETTINGS_PATH);
if (!exports.settings) {
exports.settings = {
workTime: 1500000, //Work for 25 minutes
shortBreak: 300000, //5 minute short break
longBreak: 900000, //15 minute long break
numShortBreaks: 3, //3 short breaks for every long break
pausedTimerExpireTime: 21600000, //If the timer was left paused for >6 hours, reset it on next launch
widget: false //If a widget is added in the future, whether the user wants it
};
}
//Store the minimal amount of information to be able to reconstruct the state of the timer at any given time.
//This is necessary because it is necessary to write to flash to let the timer run in the background, so minimizing the writes is necessary.
exports.STATE_DEFAULT = {
wasRunning: false, //If the timer ever was running. Used to determine whether to display a reset button
running: false, //Whether the timer is currently running
startTime: 0, //When the timer was last started. Difference between this and now is how long timer has run continuously.
pausedTime: 0, //When the timer was last paused. Used for expiration and displaying timer while paused.
elapsedTime: 0, //How much time the timer had spent running before the current start time. Update on pause or user skipping stages.
phase: exports.PHASE_WORKING, //What phase the timer is currently in
numShortBreaks: 0 //Number of short breaks that have occured so far
};
exports.state = storage.readJSON(exports.STATE_PATH);
if (!exports.state) {
exports.state = exports.STATE_DEFAULT;
}
//Get the number of milliseconds until the next phase change
exports.getTimeLeft = function () {
if (!exports.state.wasRunning) {
//If the timer never ran, the time left is just the amount of work time.
return exports.settings.workTime;
} else if (exports.state.running) {
//If the timer is running, the time left is current time - start time + preexisting time
var runningTime = (new Date()).getTime() - exports.state.startTime + exports.state.elapsedTime;
} else {
//If the timer is not running, the same as above but use when the timer was paused instead of now.
var runningTime = exports.state.pausedTime - exports.state.startTime + exports.state.elapsedTime;
}
if (exports.state.phase == exports.PHASE_WORKING) {
return exports.settings.workTime - runningTime;
} else if (exports.state.phase == exports.PHASE_SHORT_BREAK) {
return exports.settings.shortBreak - runningTime;
} else {
return exports.settings.longBreak - runningTime;
}
}
//Get the next phase to change to
exports.getNextPhase = function () {
if (exports.state.phase == exports.PHASE_WORKING) {
if (exports.state.numShortBreaks < exports.settings.numShortBreaks) {
return exports.PHASE_SHORT_BREAK;
} else {
return exports.PHASE_LONG_BREAK;
}
} else {
return exports.PHASE_WORKING;
}
}
//Change to the next phase and update numShortBreaks, and optionally vibrate. DOES NOT WRITE STATE CHANGE TO STORAGE!
exports.nextPhase = function (vibrate) {
a = {
startTime: 0, //When the timer was last started. Difference between this and now is how long timer has run continuously.
pausedTime: 0, //When the timer was last paused. Used for expiration and displaying timer while paused.
elapsedTime: 0, //How much time the timer had spent running before the current start time. Update on pause or user skipping stages.
phase: exports.PHASE_WORKING, //What phase the timer is currently in
numShortBreaks: 0 //Number of short breaks that have occured so far
}
let now = (new Date()).getTime();
exports.state.startTime = now; //The timer is being reset, so say it starts now.
exports.state.pausedTime = now; //This prevents a paused timer from having the start time moved to the future and therefore having been run for negative time.
exports.state.elapsedTime = 0; //Because we are resetting the timer, we no longer need to care about whether it was paused previously.
let oldPhase = exports.state.phase; //Cache the old phase because we need to remember it when counting the number of short breaks
exports.state.phase = exports.getNextPhase();
if (oldPhase == exports.PHASE_SHORT_BREAK) {
//If we just left a short break, increase the number of short breaks
exports.state.numShortBreaks++;
} else if (oldPhase == exports.PHASE_LONG_BREAK) {
//If we just left a long break, set the number of short breaks to zero
exports.state.numShortBreaks = 0;
}
if (vibrate) {
if (exports.state.phase == exports.PHASE_WORKING) {
Bangle.buzz(800, 1);
} else if (exports.state.phase == exports.PHASE_SHORT_BREAK) {
Bangle.buzz();
setTimeout(Bangle.buzz, 400);
} else {
Bangle.buzz();
setTimeout(Bangle.buzz, 400, 400);
}
}
}