WIP: Re-implement app with vanilla JS & HTML

Signed-off-by: William Brawner <me@wbrawner.com>
This commit is contained in:
William Brawner 2021-04-18 21:06:26 -07:00
parent ac154ed38f
commit d7254da5a6
3 changed files with 380 additions and 566 deletions

View file

@ -17,27 +17,47 @@ body {
overflow: hidden;
}
form label {
display: block;
padding: 0.5em 1em;
}
a:link, a:hover, a:visited, a:active {
color: inherit;
}
.timersLoaded #loader {
display: none;
}
.timersLoaded.noTimers .no-timers {
display: flex;
}
.no-timers {
display: block;
display: none;
padding: 20px;
text-align: center;
font-weight: normal;
font-size: 1.5em;
height: calc(100% - 60px);
box-sizing: border-box;
justify-content: center;
align-items: center;
}
.timersLoaded:not(.noTimers) .timers {
display: block;
}
.timers {
display: none;
position: relative;
padding-top: 60px;
}
.timer {
border-bottom: 1px solid #BDBDBD;
max-height: 200px;
padding:2px;
opacity: 1;
}
@ -188,9 +208,7 @@ a:link, a:hover, a:visited, a:active {
}
header {
position: absolute;
z-index: 999;
top: 0;
position: sticky;
height: 60px;
text-align: center;
width: 100%;
@ -200,17 +218,16 @@ header {
header h1 {
font-weight: normal;
font-size: 1.25em;
font-size: 1.2em;
text-align: left;
line-height: 60px;
padding-left: 60px;
padding: 1em;
}
.hamburger-icon {
position: absolute;
top: 0;
left: 0;
width: 20px;
width: 58px;
height: 12px;
padding: 24px 20px;
}
@ -236,38 +253,12 @@ header h1 {
color: #212121;
padding: 14px 20px;
display: inline-block;
}
.settings-menu {
position: absolute;
top: 0;
left: -100%;
color: inherit;
background-color: #fff;
height: 100vh;
width: 100vw;
overflow-y: scroll;
max-width: 320px;
z-index: 9999;
}
.settings-menu-overlay {
position: fixed;
background-color: rgb(0, 0, 0);
width: 100vw;
height: 100vh;
display: block;
z-index: -1;
top: 0;
transition: opacity 0.25s linear;
opacity: 0;
}
.settings-menu img {
width: 100%;
display: block;
background-color: transparent;
border: none;
height: 100%;
box-sizing: border-box;
vertical-align: middle;
cursor: pointer;
}
.question-circle {
@ -280,32 +271,6 @@ header h1 {
margin-right: 0.5em;
}
.fixed {
position: fixed;
}
.bottom {
bottom: 0;
}
.settings-menu .fixed.bottom {
padding: 15px;
border-top: 1px solid#BDBDBD;
width: 100%;
max-width: 290px;
}
.settings-menu a {
color: #212121;
font-weight: bold;
font-size: 1em;
text-decoration: none;
}
.settings-menu a i {
margin-right: 15px;
}
button.add-timer {
position: absolute;
right: 20px;
@ -318,16 +283,17 @@ button.add-timer {
font-size: 2em;
color: #fff;
background: #FF5722;
cursor: pointer;
}
.top-menu {
position: absolute;
top: 0;
height: 60px;
border-bottom: 1px solid #BDBDBD;
width: 100%;
background-color: #fff;
box-shadow: 0 0 3px 0 #BDBDBD;
display: flex;
justify-content: space-between;
}
.top-menu a:last-of-type {
@ -336,13 +302,23 @@ button.add-timer {
.new-timer {
position: fixed;
top: 100%;
top: 0;
transform: translateY(100vh);
padding: 0;
width: 100vw;
z-index: 999;
background: #fff;
min-height: 100vh;
opacity: 0;
height: 100vh;
transition: transform cubic-bezier(0.22, 0.61, 0.36, 1) 0.25s;
bottom: 0;
left: 0;
right: 0;
margin: auto;
overflow: hidden;
}
.editing .new-timer {
transform: translateY(0);
}
.new-timer.slideUp .top-menu {
@ -350,8 +326,21 @@ button.add-timer {
}
#timer-setup {
overflow: scroll;
padding-top: 62px;
overflow-y: scroll;
max-height: calc(100vh - 60px);
}
@media all and (min-width: 1024px) {
.new-timer {
max-width: 800px;
max-height: 600px;
box-shadow: 0px 0px 3px #bdbdbd;
border-radius: 10px;
}
#timer-setup {
max-height: 540px;
}
}
#timer-setup input, #timer-setup textarea, #timer-setup select {

View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html >
<html lang="en-US">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
@ -27,19 +27,18 @@
<meta name="msapplication-config" content="/img/browserconfig.xml">
<meta name="theme-color" content="#ffeb3b">
</head>
<body>
<body onload="loadTimers()">
<header>
<a href="#" class="hamburger-icon">
<img class="button menu-icon" src="img/menu.svg" />
</a>
<h1>Interval Timer</h1>
</header>
<div class="timers">
<div id="loader">
<img class="loader" src="img/spinner.png" />
<div class="loader-overlay"></div>
<div class="no-timers">
<h3>It looks like you haven't configured any timers yet. Click on the orange "+" icon below to get started!</h3>
</div>
</div>
<div class="no-timers">
<p style="max-width: 600px;">It looks like you haven't configured any timers yet. Click on the orange "+" icon below to get started!</p>
</div>
<div class="timers">
<div class="timer animate-repeat">
<a href="javascript:void(0)">
<h2>Timer Name</h2>
@ -68,89 +67,51 @@
</div>
</div>
</div>
<div class="settings-menu-overlay" ></div>
<div class="settings-menu">
<img src="./img/menu-logo.png" />
<div class="fixed bottom">
<a href="https://wbrawner.com/contact/" target="_blank"><span class="question-circle">?</span>Help &amp; feedback</a>
</div>
</div>
<div class="new-timer" >
<div class="new-timer">
<div class="top-menu">
<a class="menu-button" href="javascript:void(0)" >&#10005;</a>
<a class="menu-button" href="javascript:void(0)" >&#10003;</a>
<button class="menu-button" onclick="cancelEdit()" >&#10005;</a>
<button class="menu-button" onclick="saveTimer()" >&#10003;</a>
</div>
<form id="timer-setup" name="timer-setup">
<div class="input-wrapper">
<input type="text" placeholder="Name">
<label for="timerName">Name:</label>
<input type="text" name="timerName">
</div>
<div class="input-wrapper">
<textarea placeholder="Description"></textarea>
</div>
<div class="select-wrapper">
<select class="min" >
<option value="" disabled selected>Warm-up Min</option>
</select>
<span style="width: 2%;">
:
</span>
<select class="sec" >
<option value="" disabled selected>Warm-up Sec</option>
</select>
</div>
<div class="select-wrapper">
<select class="min" >
<option value="" disabled selected>Low-intensity Min</option>
</select>
<span style="width: 2%;">
:
</span>
<select class="sec" >
<option value="" disabled selected>Low-intensity Sec</option>
</select>
</div>
<div class="select-wrapper">
<select class="min" >
<option value="" disabled selected>High-intensity Min</option>
</select>
<span style="width: 2%;">
:
</span>
<select class="sec" >
<option value="" disabled selected>High-intensity Sec</option>
</select>
</div>
<div class="select-wrapper">
<select class="min" >
<option value="" disabled selected>Rest Min</option>
</select>
<span style="width: 2%;">
:
</span>
<select class="sec" >
<option value="" disabled selected>Rest Sec</option>
</select>
</div>
<div class="select-wrapper">
<select class="min" >
<option value="" disabled selected>CoolDown Min</option>
</select>
<span style="width: 2%;">
:
</span>
<select class="sec" >
<option value="" disabled selected>CoolDown Sec</option>
</select>
<label for="timerDescription">Description:</label>
<textarea name="timerDescription"></textarea>
</div>
<div class="input-wrapper">
<input type="number" placeholder="Rounds">
<label for="warmUp">Warm-up:</label>
<input type="number" name="warmUp" />
</div>
<div class="input-wrapper">
<input type="number" placeholder="Cycles">
<label for="low">Low-intensity:</label>
<input type="number" name="low" />
</div>
<div class="input-wrapper">
<label for="high">High-intensity:</label>
<input type="number" name="high" />
</div>
<div class="input-wrapper">
<label for="rest">Rest:</label>
<input type="number" name="rest" />
</div>
<div class="input-wrapper">
<label for="cool">Cooldown:</label>
<input type="number" name="cool" />
</div>
<div class="input-wrapper">
<label for="sets">Sets:</label>
<input type="number" name="sets">
</div>
<div class="input-wrapper">
<label for="rounds">Rounds:</label>
<input type="number" name="rounds">
</div>
</form>
</div>
<button class="add-timer" onclick="openNewTimer()">+</button>
<button class="add-timer" onclick="editTimer()">+</button>
<script async>
if('serviceWorker' in navigator) {
navigator.serviceWorker

View file

@ -1,423 +1,287 @@
if (!window.indexedDB) {
// TODO: Show this as an inline alert instead
window.alert("Your browser doesn't support a stable version of IndexedDB. You will not be able to save your timers.");
}
(function () {
let wakeLock = null;
var app = angular.module('interval-timer', ['indexedDB', 'itemSwipe', 'ngAnimate', 'ngCookies', 'ngTouch'])
.config(function ($indexedDBProvider) {
$indexedDBProvider
.connection('interval-timer')
.upgradeDatabase(1, function (event, db, tx) {
var objStore = db.createObjectStore('timers', { keyPath: 'id' });
objStore.createIndex('timer_obj', 'timer', { unique: false });
})
});
var defaultTimer = {
"id": 0,
"name": "",
"description": "",
"warmUp": {
"min": 0,
"sec": 0,
"time": 0
},
"highIntensity": {
"min": 0,
"sec": 0,
"time": 0
},
"lowIntensity": {
"min": 0,
"sec": 0,
"time": 0
},
"coolDown": {
"min": 0,
"sec": 0,
"time": 0
},
"rest": {
"min": 0,
"sec": 0,
"time": 0
},
"rounds": 1,
"cycles": 1
};
app.controller('timerCtrl', ['$scope', '$cookies', '$indexedDB', function ($scope, $cookies, $indexedDB) {
$scope.defaults = defaultTimer;
function getSavedTimer() {
var savedTimer = $cookies.getObject("timer");
if (typeof savedTimer == "object") {
return savedTimer;
} else {
return $scope.defaults;
}
}
$scope.lockScreen = function () {
if ($scope.timerActive) {
try {
navigator.wakeLock.request('screen').then((lock) => {
wakeLock = lock;
wakeLock.addEventListener('release', () => {
console.log('Screen Wake Lock was released');
});
console.log('Screen Wake Lock is active');
}).catch((err) => {
console.error(`Failed to aquire wakelock: ${err.name}, ${err.message}`);
})
} catch (err) {
console.error(`Failed to aquire wakelock: ${err.name}, ${err.message}`);
}
} else {
try {
wakeLock.release();
wakeLock = null;
} catch (err) {
console.error(`Failed to release wakelock: ${err.name}, ${err.message}`)
}
}
}
$scope.timers = {}
$scope.periods = [
"warmUp",
"lowIntensity",
"highIntensity",
"rest",
"coolDown"
];
$scope.timersLoaded = false;
$scope.noTimers = false;
$scope.setTimers = function () {
$indexedDB.openStore('timers', function (timers) {
timers.getAll()
.then(function (data) {
$scope.timers = data;
if (data.length == 0) {
$scope.noTimers = false;
} else {
$scope.noTimers = true;
}
$scope.timersLoaded = true;
})
})
}
$scope.setTimers();
$scope.timer = {};
$scope.config = {};
$scope.initObj = new Promise(function (res, rej) {
$scope.periods.forEach(function (period) {
$scope.config[period] = {};
$scope[period] = {};
$scope.timer[period] = {};
})
res($scope.config);
});
$scope.initObj.then(function () {
$scope.config.warmUp.beep = new Audio('audio/warm.mp3');
$scope.config.lowIntensity.beep = new Audio('audio/low.mp3');
$scope.config.highIntensity.beep = new Audio('audio/high.mp3');
$scope.config.rest.beep = new Audio('audio/rest.mp3');
$scope.config.coolDown.beep = new Audio('audio/cool.mp3');
$scope.warmUp.active = true;
})
$scope.round = 1;
$scope.cycle = 1;
$scope.settingsOpen = false;
$scope.closeSettings = false;
$scope.newTimerOpen = false;
$scope.newTimerClosed = false;
$scope.showTimerInterface = false;
$scope.setPeriod = function (period, playBeep) {
if (typeof playBeep == "undefined") {
playBeep = true;
}
clearInterval($scope.countdown);
$scope[period].active = true;
$scope.time = $scope.timer[period].time;
if (playBeep) {
if ($scope.config[period].beep) {
$scope.config[period].beep.play();
}
}
$scope.startTimer();
}
$scope.setWarmUp = function () {
$scope.setPeriod('warmUp');
}
$scope.setCoolDown = function () {
clearInterval($scope.countdown);
$scope.coolDown.active = true;
$scope.time = $scope.timer.coolDown.time;
$scope.coolDownBeep.play();
$scope.startTimer();
}
$scope.setLowIntensity = function () {
clearInterval($scope.countdown);
$scope.lowIntensity.active = true;
$scope.time = $scope.timer.lowIntensity.time;
$scope.lowIntensityBeep.play();
$scope.startTimer();
}
$scope.setHighIntensity = function () {
clearInterval($scope.countdown);
$scope.highIntensity.active = true;
$scope.time = $scope.timer.highIntensity.time;
$scope.highIntensityBeep.play();
$scope.startTimer();
}
$scope.startWarmUp = function () {
if ($scope.time === 0) {
$scope.warmUp.active = false;
$scope.setPeriod('lowIntensity');
}
$scope.$apply(function () {
$scope.time--;
});
};
$scope.startCoolDown = function () {
if ($scope.time === 0) {
$scope.coolDown.active = false;
$scope.resetTimer();
}
$scope.$apply(function () {
$scope.time--;
});
};
$scope.startRest = function () {
if ($scope.time === 0) {
$scope.rest.active = false;
$scope.setPeriod('lowIntensity');
}
$scope.$apply(function () {
$scope.time--;
});
};
$scope.startLowIntensity = function () {
if ($scope.time === 0) {
$scope.lowIntensity.active = false;
$scope.setPeriod('highIntensity');
}
$scope.$apply(function () {
$scope.time--;
});
};
$scope.startHighIntensity = function () {
if ($scope.time === 0) {
$scope.highIntensity.active = false;
if ($scope.round == $scope.timer.rounds && $scope.cycle == $scope.timer.cycles) {
$scope.setPeriod('coolDown');
} else if ($scope.round == $scope.timer.rounds && $scope.cycle < $scope.timer.cycles) {
$scope.cycle++;
$scope.round = 1;
$scope.setPeriod('rest');
} else {
$scope.setPeriod('lowIntensity');
$scope.round++;
}
}
$scope.$apply(function () {
$scope.time--;
});
};
$scope.getTimes = function () {
$scope.periods.forEach(function (period) {
var min = 0;
if (typeof $scope.timer[period].min == "number" && $scope.timer[period].min > 0) {
min = $scope.timer[period].min * 60;
}
var sec = $scope.timer[period].sec;
$scope.timer[period].time = min + sec;
})
};
$scope.startTimer = function () {
$scope.timerActive = true;
$scope.lockScreen();
if ($scope.warmUp.active) {
$scope.countdown = setInterval($scope.startWarmUp, 1000);
}
if ($scope.coolDown.active) {
$scope.countdown = setInterval($scope.startCoolDown, 1000);
}
if ($scope.rest.active) {
$scope.countdown = setInterval($scope.startRest, 1000);
}
if ($scope.highIntensity.active) {
$scope.countdown = setInterval($scope.startHighIntensity, 1000);
}
if ($scope.lowIntensity.active) {
$scope.countdown = setInterval($scope.startLowIntensity, 1000);
}
};
$scope.pauseTimer = function () {
$scope.timerActive = false;
$scope.lockScreen();
clearInterval($scope.countdown);
};
$scope.stepBack = function () {
if ($scope.warmUp.active) {
$scope.resetTimer();
return;
};
if ($scope.lowIntensity.active) {
$scope.lowIntensity.active = false;
if ($scope.round == 1 && $scope.cycle == 1) {
$scope.setPeriod('warmUp');
return;
}
if ($scope.round == 1 && $scope.cycle > 1) {
$scope.setPeriod('rest');
return;
}
$scope.setPeriod('highIntensity');
$scope.round--;
return;
};
if ($scope.highIntensity.active) {
$scope.highIntensity.active = false;
$scope.setPeriod('lowIntensity');
return;
};
if ($scope.rest.active) {
$scope.rest.active = false;
$scope.cycle--;
$scope.round = $scope.timer.rounds;
$scope.setPeriod('highIntensity');
return;
}
if ($scope.coolDown.active) {
$scope.coolDown.active = false;
$scope.setPeriod('highIntensity');
return;
}
};
$scope.stepForward = function () {
if ($scope.warmUp.active) {
$scope.warmUp.active = false;
$scope.setPeriod('lowIntensity');
return;
}
if ($scope.rest.active) {
$scope.rest.active = false;
$scope.setPeriod('lowIntensity');
return;
};
if ($scope.lowIntensity.active) {
$scope.lowIntensity.active = false;
$scope.setPeriod('highIntensity');
return;
};
if ($scope.highIntensity.active) {
$scope.highIntensity.active = false;
if ($scope.round == $scope.timer.rounds && $scope.cycle == $scope.timer.cycles) {
$scope.setPeriod('coolDown');
return;
} else if ($scope.round == $scope.timer.rounds && $scope.cycle < $scope.timer.cycles) {
$scope.cycle++;
$scope.round = 1;
$scope.setPeriod('rest');
return;
}
$scope.setPeriod('lowIntensity');
$scope.round++;
return;
};
};
$scope.resetTimer = function () {
clearInterval($scope.countdown);
$scope.timerActive = false;
$scope.lockScreen();
$scope.round = 1;
$scope.cycle = 1;
$scope.lowIntensity.active = false;
$scope.highIntensity.active = false;
$scope.coolDown.active = false;
$scope.warmUp.active = true;
$scope.time = $scope.timer.warmUp.time;
};
$scope.makeId = function () {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const defaultTimer = {
"id": 0,
"name": "",
"description": "",
"warmUp": 300,
"highIntensity": 60,
"lowIntensity": 30,
"rest": 60,
"coolDown": 300,
"rounds": 4,
"cycles": 2
}
for (var i = 0; i < 5; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
const Phase = {
WARM: {
name: "Warm Up",
sound: new Audio('audio/warm.mp3')
},
LOW: {
name: "Low Intensity",
sound: new Audio('audio/low.mp3')
},
HIGH: {
name: "High Intensity",
sound: new Audio('audio/high.mp3')
},
REST: {
name: "Rest",
sound: new Audio('audio/rest.mp3')
},
COOL: {
name: "Cool Down",
sound: new Audio('audio/cool.mp3')
},
}
return text;
let _state = {
timers: null,
timer: null,
timerJob: null,
timerComplete: false,
set: 1,
round: 1,
phase: Phase.WARM,
timeRemaining: 0,
editingTimer: false,
};
let db = null;
let timerStore = null;
function loadTimers() {
let state = copyState();
const dbRequest = window.indexedDB.open('interval-timer', 1);
dbRequest.onerror = (event) => {
console.error(`Failed to open IndexedDB`, event)
}
dbRequest.onsuccess = (event) => {
db = event.target.result;
let transaction = db.transaction(["timers"]);
let objectStore = transaction.objectStore("timers");
const request = objectStore.getAll();
request.onerror = function (event) {
console.error('Failed to load timers', event)
};
$scope.openTimer = function (id) {
$indexedDB.openStore('timers', function (timers) {
timers.find(id)
.then(function (data) {
$scope.timer = data;
$scope.getTimes();
$scope.resetTimer();
$scope.showTimerInterface = true;
})
})
}
$scope.closeTimer = function () {
$scope.showTimerInterface = false;
}
$scope.deleteTimer = function (item) {
item.removed = true;
setTimeout(function () {
$indexedDB.openStore('timers', function (timers) {
var result = timers.delete(item.id)
.then(function (e) {
$scope.setTimers();
})
})
}, 500);
request.onsuccess = function (event) {
console.log("Loaded timers", event)
state.timers = event.target.result;
updateState(state)
};
$scope.saveTimer = function () {
$scope.newTimer.id = $scope.makeId();
$indexedDB.openStore('timers', function (timers) {
var result = timers.insert($scope.newTimer)
.then(function (e) {
$scope.newTimer = {};
$scope.setTimers();
})
}
dbRequest.onupgradeneeded = (event) => {
db = event.target.result;
timerStore = db.createObjectStore('timers', { keyPath: 'id' });
}
}
function saveTimer() {
// let transaction = db.transaction(["timers"], "readwrite");
// transaction.oncomplete
let state = copyState();
if (!state.timers) {
state.timers = [];
}
// TODO: get values from fields and then clear them here
state.timers.push(defaultTimer)
updateState({
...state,
editingTimer: false,
});
}
function deleteTimer() {
// var request = db.transaction(["customers"], "readwrite")
// .objectStore("customers")
// .delete("444-44-4444");
// request.onsuccess = function(event) {
// It's gone!
// };
}
function openTimer() {
}
function editTimer() {
updateState({
editingTimer: true
})
}
function cancelEdit() {
updateState({
editingTimer: false
})
}
function toggleTimer() {
let state = copyState();
if (state.timerJob != null) {
clearInterval(state.timerJob)
state.timerJob = null
} else {
state.timerJob = setInterval(timerLoop, 1000);
}
updateState(state);
lockScreen();
}
function timerLoop() {
let state = copyState();
state.timeRemaining -= 1;
if (state.timeRemaining <= 0) {
goForward();
}
updateState(state);
}
function goBack() {
let state = copyState();
if (!state.timer) return;
switch (state.phase) {
case Phase.WARM:
state.timeRemaining = state.timer.warmUp;
break;
case Phase.LOW:
if (state.set == state.timer.sets && state.round == state.timer.rounds) {
state.phase = Phase.WARM;
state.timeRemaining = state.timer.warmUp;
} else if (state.set == state.timer.sets && state.round < state.timer.rounds) {
state.phase = Phase.REST;
state.timeRemaining = state.timer.rest;
} else {
state.set += 1;
state.phase = Phase.HIGH;
state.timeRemaining = state.timer.highIntensity;
}
break;
case Phase.HIGH:
state.phase = Phase.LOW;
state.timeRemaining = state.timer.lowIntensity;
break;
case Phase.REST:
state.round += 1;
state.phase = Phase.HIGH;
state.set = state.timer.sets;
state.timeRemaining = state.timer.highIntensity;
break;
case Phase.COOL:
state.phase = Phase.HIGH;
state.timeRemaining = state.timer.highIntensity;
break;
}
updateState({
...state,
timerComplete: false,
})
}
function goForward() {
let state = copyState();
if (!state.timer) return;
state.timerComplete = state.phase === Phase.COOL
switch (state.phase) {
case Phase.WARM:
state.phase = Phase.LOW;
state.timeRemaining = state.timer.lowIntensity;
break;
case Phase.LOW:
state.phase = Phase.HIGH;
state.timeRemaining = state.timer.highIntensity;
break;
case Phase.HIGH:
if (state.set > 1) {
state.set -= 1;
state.phase = Phase.LOW;
state.timeRemaining = state.timer.lowIntensity;
} else if (state.round > 1) {
state.round -= 1;
state.phase = Phase.REST;
state.timeRemaining = state.timer.rest;
} else {
state.phase = Phase.COOL;
state.timeRemaining = state.timer.coolDown;
}
break;
case Phase.REST:
state.set = state.timer.sets;
state.phase = Phase.LOW;
state.timeRemaining = state.timer.lowIntensity;
break;
case Phase.COOL:
state.timeRemaining = 0;
break;
}
updateState(state);
}
function copyState() {
return JSON.parse(JSON.stringify(_state));
}
const debug = false;
function updateState(changes) {
if (debug) console.log("Before", _state)
const immutableChanges = JSON.parse(JSON.stringify(changes));
_state = {
..._state,
...immutableChanges
}
if (debug) console.log("After: ", _state)
if (_state.timers) {
document.body.classList.add('timersLoaded')
if (_state.timers.length === 0) {
document.body.classList.add('noTimers')
} else {
document.body.classList.remove('noTimers')
}
}
if (_state.editingTimer) {
document.body.classList.add('editing')
} else {
document.body.classList.remove('editing')
}
}
// The wakeLock has to be separate from the state because it doesn't get
// transferred correctly when the state is copied
let wakeLock = null;
function lockScreen() {
let state = copyState();
if (state.timerJob) {
if (wakeLock) {
console.log("Ignoring request to lock screen, should already be locked");
return;
}
try {
navigator.wakeLock.request('screen').then((lock) => {
wakeLock = lock;
wakeLock.addEventListener('release', () => {
console.log('Screen Wake Lock was released');
});
console.log('Screen Wake Lock is active');
}).catch((err) => {
console.error(`Failed to aquire wakelock: ${err.name}, ${err.message}`);
})
};
$scope.getTimers = function () {
return $scope.timers;
} catch (err) {
console.error(`Failed to aquire wakelock: ${err.name}, ${err.message}`);
}
$scope.getNumberRange = function (number) {
range = [];
for (var i = 0; i <= number; i++) {
range.push(i);
}
return range
} else {
try {
wakeLock.release();
wakeLock = null;
} catch (err) {
console.error(`Failed to release wakelock: ${err.name}, ${err.message}`)
}
$scope.openNewTimer = function () {
$scope.newTimerClosed = false;
$scope.newTimerOpen = true;
}
$scope.validateNewTimer = function (newTimer) {
timerSkel = $scope.defaults;
angular.merge(timerSkel, newTimer);
if (timerSkel.rounds < 1) {
timerSkel.rounds = 1;
}
if (timerSkel.cycles < 1) {
timerSkel.cycles = 1;
}
return new Promise(function (res, rej) {
res(timerSkel);
})
}
$scope.saveNewTimer = function () {
$scope.validateNewTimer($scope.newTimer)
.then(function (newTimer) {
$scope.newTimer = newTimer;
$scope.saveTimer();
$scope.closeNewTimer();
})
}
$scope.closeNewTimer = function () {
$scope.newTimerOpen = false;
$scope.newTimerClosed = true;
}
}]);
})();
}
}