Write documentation for classes and functions; some cleanup
parent
7a8c56023f
commit
bca633dcec
|
|
@ -1,3 +1,6 @@
|
|||
// Derived from `sched.js` from the `sched` app, with modifications
|
||||
// for features unique to the `tevtimer` app.
|
||||
|
||||
// Chances are boot0.js got run already and scheduled *another*
|
||||
// 'load(sched.js)' - so let's remove it first!
|
||||
if (Bangle.SCHED) {
|
||||
|
|
@ -8,6 +11,8 @@ if (Bangle.SCHED) {
|
|||
const tt = require('tevtimer');
|
||||
|
||||
function showAlarm(alarm) {
|
||||
// Alert the user of the alarm and handle the response
|
||||
|
||||
const settings = require("sched").getSettings();
|
||||
const timer = tt.TIMERS[tt.find_timer_by_id(alarm.id)];
|
||||
if (timer === undefined) {
|
||||
|
|
@ -52,8 +57,8 @@ function showAlarm(alarm) {
|
|||
// Alarm options for chained timer are OK (dismiss) and Halt (dismiss
|
||||
// and pause the triggering timer).
|
||||
let promptButtons = isChainedTimer
|
||||
? { "Halt": 'halt', "OK": 'ok' }
|
||||
: { "Snooze": 'snooze', "OK": 'ok' };
|
||||
? { 'Halt': 'halt', 'OK': 'ok' }
|
||||
: { 'Snooze': 'snooze', 'OK': 'ok' };
|
||||
E.showPrompt(message, {
|
||||
title: 'tev timer',
|
||||
buttons: promptButtons,
|
||||
|
|
@ -108,6 +113,8 @@ function showAlarm(alarm) {
|
|||
});
|
||||
|
||||
function buzz() {
|
||||
// Handle buzzing and screen unlocking
|
||||
|
||||
if (settings.unlockAtBuzz) {
|
||||
Bangle.setLocked(false);
|
||||
}
|
||||
|
|
@ -127,6 +134,9 @@ function showAlarm(alarm) {
|
|||
}
|
||||
|
||||
function setNextRepeatDate(alarm) {
|
||||
// Handle repeating alarms
|
||||
// This is not used in tevtimer
|
||||
|
||||
let date = new Date(alarm.date);
|
||||
let rp = alarm.rp;
|
||||
if (rp===true) { // fallback in case rp is set wrong
|
||||
|
|
|
|||
|
|
@ -14,10 +14,13 @@ const MOVE_TO_TOP_TIMEOUT = 5000;
|
|||
// Min number of pixels of movement to recognize a touchscreen drag/swipe
|
||||
const DRAG_THRESHOLD = 50;
|
||||
|
||||
// Physical left/right button size in UI
|
||||
const ARROW_BTN_SIZE = 15;
|
||||
|
||||
// IDs of main screen labels
|
||||
const ROW_IDS = ['row1', 'row2', 'row3'];
|
||||
|
||||
// Fonts to use for each screen label and display format
|
||||
const FONT = {
|
||||
'row1': {
|
||||
'start hh:mm:ss': '12x20',
|
||||
|
|
@ -30,7 +33,7 @@ const FONT = {
|
|||
|
||||
'name': '12x20',
|
||||
|
||||
'mode': '12x20',
|
||||
'format-menu': '12x20',
|
||||
},
|
||||
|
||||
'row2': {
|
||||
|
|
@ -44,7 +47,7 @@ const FONT = {
|
|||
|
||||
'name': 'Vector:24x42',
|
||||
|
||||
'mode': 'Vector:26x42',
|
||||
'format-menu': 'Vector:26x42',
|
||||
},
|
||||
|
||||
'row3': {
|
||||
|
|
@ -58,10 +61,12 @@ const FONT = {
|
|||
|
||||
'name': 'Vector:24x56',
|
||||
|
||||
'mode': 'Vector:26x56',
|
||||
'format-menu': 'Vector:26x56',
|
||||
}
|
||||
};
|
||||
|
||||
// List of format IDs available in the format menu
|
||||
// (in the order they are displayed in the menu)
|
||||
const FORMAT_MENU = [
|
||||
'start hh:mm:ss',
|
||||
'start hh:mm',
|
||||
|
|
@ -72,6 +77,8 @@ const FORMAT_MENU = [
|
|||
'name',
|
||||
];
|
||||
|
||||
// Mapping of format IDs to their human-friendly names displayed in the
|
||||
// format menu
|
||||
const FORMAT_DISPLAY = {
|
||||
'start hh:mm:ss': 'Start HMS',
|
||||
'start hh:mm': 'Start HM',
|
||||
|
|
@ -83,20 +90,29 @@ const FORMAT_DISPLAY = {
|
|||
};
|
||||
|
||||
|
||||
function row_font(row_name, mode_name) {
|
||||
let font = FONT[row_name][mode_name];
|
||||
function row_font(row_name, format) {
|
||||
// Convenience function to retrieve the font ID for the given display
|
||||
// field and format mode
|
||||
|
||||
let font = FONT[row_name][format];
|
||||
if (font === undefined) {
|
||||
console.error('Unknown font for row_font("' + row_name + '", "' + mode_name + '")');
|
||||
console.error('Unknown font for row_font("' + row_name + '", "' + format + '")');
|
||||
return '12x20';
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
// Determine time in milliseconds until next display update for a timer
|
||||
// that should be updated every `interval` milliseconds.
|
||||
function next_time_update(interval, curr_time, direction) {
|
||||
if (interval <= 0) {
|
||||
// Determine time in milliseconds until next display update for a timer
|
||||
// that should be updated every `interval` milliseconds.
|
||||
//
|
||||
// `curr_time` is the current time in milliseconds, and `direction`
|
||||
// is either 1 (forward) or -1 (backward). The function returns the
|
||||
// time in milliseconds until the next update, or Infinity if there
|
||||
// is no update needed (e.g. if interval is zero or negative).
|
||||
|
||||
if (interval <= 0) {
|
||||
// Don't update if interval is zero or negative
|
||||
return Infinity;
|
||||
}
|
||||
|
|
@ -119,6 +135,10 @@ function next_time_update(interval, curr_time, direction) {
|
|||
|
||||
|
||||
class TimerView {
|
||||
// Primary UI for displaying and operating a timer. The
|
||||
// PrimitiveTimer object is passed to the constructor as a
|
||||
// parameter.
|
||||
|
||||
constructor(timer) {
|
||||
this.timer = timer;
|
||||
|
||||
|
|
@ -128,6 +148,8 @@ class TimerView {
|
|||
}
|
||||
|
||||
start() {
|
||||
// Initialize, display, and activate the UI
|
||||
|
||||
this._initLayout();
|
||||
this.layout.update();
|
||||
this.layout.clear();
|
||||
|
|
@ -175,6 +197,8 @@ class TimerView {
|
|||
}
|
||||
|
||||
stop() {
|
||||
// Shut down the UI and clean up listeners and handlers
|
||||
|
||||
if (this.listeners.timer_render_timeout !== null) {
|
||||
clearTimeout(this.listeners.timer_render_timeout);
|
||||
this.listeners.timer_render_timeout = null;
|
||||
|
|
@ -232,6 +256,10 @@ class TimerView {
|
|||
}
|
||||
|
||||
render(item) {
|
||||
// Draw the timer display and update the status and buttons. The
|
||||
// `item` parameter specifies which part of the display to update.
|
||||
// If `item` is not specified, the entire display is updated.
|
||||
|
||||
console.debug('render called: ' + item);
|
||||
|
||||
if (!item) {
|
||||
|
|
@ -325,6 +353,8 @@ class TimerView {
|
|||
}
|
||||
|
||||
start_stop_timer() {
|
||||
// Start or pause the timer
|
||||
|
||||
if (this.timer.is_running()) {
|
||||
this.timer.pause();
|
||||
} else {
|
||||
|
|
@ -338,6 +368,10 @@ class TimerView {
|
|||
|
||||
|
||||
class TimerFormatView {
|
||||
// UI for selecting the display format of a timer. The
|
||||
// PrimitiveTimer object is passed to the constructor as a
|
||||
// parameter.
|
||||
|
||||
constructor(timer) {
|
||||
this.timer = timer;
|
||||
|
||||
|
|
@ -357,6 +391,8 @@ class TimerFormatView {
|
|||
}
|
||||
|
||||
start() {
|
||||
// Initialize, display, and activate the UI
|
||||
|
||||
this._initLayout();
|
||||
this.layout.update();
|
||||
this.layout.clear();
|
||||
|
|
@ -430,6 +466,8 @@ class TimerFormatView {
|
|||
}
|
||||
|
||||
stop() {
|
||||
// Shut down the UI and clean up listeners and handlers
|
||||
|
||||
Bangle.removeListener('drag', this.listeners.drag);
|
||||
Bangle.removeListener('touch', this.listeners.touch);
|
||||
clearWatch(this.listeners.button);
|
||||
|
|
@ -465,7 +503,7 @@ class TimerFormatView {
|
|||
type: 'txt',
|
||||
id: 'row1',
|
||||
label: FORMAT_DISPLAY[FORMAT_MENU[this.format_idx.row1]],
|
||||
font: row_font('row1', 'mode'),
|
||||
font: row_font('row1', 'format-menu'),
|
||||
fillx: 1,
|
||||
},
|
||||
{
|
||||
|
|
@ -491,7 +529,7 @@ class TimerFormatView {
|
|||
type: 'txt',
|
||||
id: 'row2',
|
||||
label: FORMAT_DISPLAY[FORMAT_MENU[this.format_idx.row2]],
|
||||
font: row_font('row2', 'mode'),
|
||||
font: row_font('row2', 'format-menu'),
|
||||
fillx: 1,
|
||||
},
|
||||
{
|
||||
|
|
@ -517,7 +555,7 @@ class TimerFormatView {
|
|||
type: 'txt',
|
||||
id: 'row3',
|
||||
label: FORMAT_DISPLAY[FORMAT_MENU[this.format_idx.row3]],
|
||||
font: row_font('row3', 'mode'),
|
||||
font: row_font('row3', 'format-menu'),
|
||||
fillx: 1,
|
||||
},
|
||||
{
|
||||
|
|
@ -548,10 +586,15 @@ class TimerFormatView {
|
|||
}
|
||||
|
||||
render() {
|
||||
// Draw the format selection UI.
|
||||
|
||||
this.layout.render();
|
||||
}
|
||||
|
||||
update_row(row_id) {
|
||||
// Render the display format for the given row ID. The row ID
|
||||
// should be one of 'row1', 'row2', or 'row3'.
|
||||
|
||||
const elem = this.layout[row_id];
|
||||
elem.label = FORMAT_DISPLAY[FORMAT_MENU[this.format_idx[row_id]]];
|
||||
this.layout.clear(elem);
|
||||
|
|
@ -559,6 +602,9 @@ class TimerFormatView {
|
|||
}
|
||||
|
||||
incr_format_idx(row_id) {
|
||||
// Increment the selected format for the given row ID. The row ID
|
||||
// should be one of 'row1', 'row2', or 'row3'.
|
||||
|
||||
this.format_idx[row_id] += 1;
|
||||
if (this.format_idx[row_id] >= FORMAT_MENU.length) {
|
||||
this.format_idx[row_id] = 0;
|
||||
|
|
@ -567,6 +613,9 @@ class TimerFormatView {
|
|||
}
|
||||
|
||||
decr_format_idx(row_id) {
|
||||
// Decrement the selected format for the given row ID. The row ID
|
||||
// should be one of 'row1', 'row2', or 'row3'.
|
||||
|
||||
this.format_idx[row_id] -= 1;
|
||||
if (this.format_idx[row_id] < 0) {
|
||||
this.format_idx[row_id] = FORMAT_MENU.length - 1;
|
||||
|
|
@ -574,8 +623,8 @@ class TimerFormatView {
|
|||
this.update_row(row_id);
|
||||
}
|
||||
|
||||
// Save new format settings and return to TimerView
|
||||
ok() {
|
||||
// Save new format settings and return to TimerView
|
||||
for (var row_id of ROW_IDS) {
|
||||
tt.SETTINGS.format[row_id] = FORMAT_MENU[this.format_idx[row_id]];
|
||||
}
|
||||
|
|
@ -583,31 +632,43 @@ class TimerFormatView {
|
|||
switch_UI(new TimerView(this.timer));
|
||||
}
|
||||
|
||||
// Return to TimerViewMenu without saving changes
|
||||
cancel() {
|
||||
// Return to TimerViewMenu without saving changes
|
||||
switch_UI(new TimerViewMenu(this.timer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TimerViewMenu {
|
||||
// UI for displaying the timer menu. The PrimitiveTimer object is
|
||||
// passed to the constructor as a parameter.
|
||||
|
||||
constructor(timer) {
|
||||
this.timer = timer;
|
||||
}
|
||||
|
||||
start() {
|
||||
// Display and activate the top menu of the timer view menu.
|
||||
|
||||
this.top_menu();
|
||||
}
|
||||
|
||||
stop() {
|
||||
// Shut down the UI and clean up listeners and handlers
|
||||
|
||||
E.showMenu();
|
||||
}
|
||||
|
||||
back() {
|
||||
// Return to the timer view
|
||||
// (i.e. the timer that was previously displayed)
|
||||
|
||||
switch_UI(new TimerView(this.timer));
|
||||
}
|
||||
|
||||
top_menu() {
|
||||
// Display the top-level menu for the timer
|
||||
|
||||
const top_menu = {
|
||||
'': {
|
||||
title: this.timer.display_name(),
|
||||
|
|
@ -663,6 +724,9 @@ class TimerViewMenu {
|
|||
}
|
||||
|
||||
edit_menu() {
|
||||
// Display the edit menu for the timer. This can be called in
|
||||
// place of `start` to jump directly to the edit menu.
|
||||
|
||||
let keyboard = null;
|
||||
try { keyboard = require("textinput"); } catch (e) {}
|
||||
|
||||
|
|
@ -724,6 +788,9 @@ class TimerViewMenu {
|
|||
}
|
||||
|
||||
edit_start() {
|
||||
// Display the edit > start menu for the timer
|
||||
// (i.e. the timer's starting value)
|
||||
|
||||
let origin_hms = {
|
||||
h: Math.floor(this.timer.origin / 3600),
|
||||
m: Math.floor(this.timer.origin / 60) % 60,
|
||||
|
|
@ -764,24 +831,37 @@ class TimerViewMenu {
|
|||
|
||||
|
||||
class TimerMenu {
|
||||
// UI for displaying the list of timers. The list of
|
||||
// PrimitiveTimer objects is passed to the constructor as a
|
||||
// parameter. The currently focused timer is passed as the
|
||||
// second parameter.
|
||||
|
||||
constructor(timers, focused_timer) {
|
||||
this.timers = timers;
|
||||
this.focused_timer = focused_timer;
|
||||
}
|
||||
|
||||
start() {
|
||||
// Display the top timer menu
|
||||
|
||||
this.top_menu();
|
||||
}
|
||||
|
||||
stop() {
|
||||
// Shut down the UI and clean up listeners and handlers
|
||||
|
||||
E.showMenu();
|
||||
}
|
||||
|
||||
back() {
|
||||
// Return to the timer's menu
|
||||
|
||||
switch_UI(new TimerViewMenu(this.focused_timer));
|
||||
}
|
||||
|
||||
top_menu() {
|
||||
// Display the top-level menu for the timer list
|
||||
|
||||
let menu = {
|
||||
'': {
|
||||
title: "Timers",
|
||||
|
|
@ -798,6 +878,10 @@ class TimerMenu {
|
|||
|
||||
|
||||
function switch_UI(new_UI) {
|
||||
// Switch from one UI to another. The new UI instance is passed as a
|
||||
// parameter. The old UI is stopped and cleaned up, and the new
|
||||
// UI is started.
|
||||
|
||||
if (CURRENT_UI) {
|
||||
CURRENT_UI.stop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ const Sched = require('sched');
|
|||
const Time_utils = require('time_utils');
|
||||
|
||||
|
||||
// Convenience //
|
||||
// Convenience functions //
|
||||
|
||||
function mod(n, m) {
|
||||
// Modulus function that works like Python's % operator
|
||||
|
|
@ -20,7 +20,20 @@ function ceil(value) {
|
|||
// Data models //
|
||||
|
||||
class PrimitiveTimer {
|
||||
// A simple timer object that can be used as a countdown or countup
|
||||
// timer. It can be paused and resumed, and it can be reset to its
|
||||
// original value. It can also be saved to and loaded from a
|
||||
// persistent storage.
|
||||
|
||||
constructor(origin, is_running, rate, name, id) {
|
||||
// origin: initial value of the timer
|
||||
// is_running: true if the timer should begin running immediately,
|
||||
// false if it should be paused
|
||||
// rate: rate of the timer, in units per second. Positive for
|
||||
// countup, negative for countdown
|
||||
// name: name of the timer (can be empty)
|
||||
// id: ID of the timer
|
||||
|
||||
this.origin = origin || 0;
|
||||
// default rate +1 unit per 1000 ms, countup
|
||||
this.rate = rate || 0.001;
|
||||
|
|
@ -36,18 +49,26 @@ class PrimitiveTimer {
|
|||
}
|
||||
|
||||
display_name() {
|
||||
// Return a string to display as the timer name
|
||||
// If the name is empty, return a generated name
|
||||
return this.name ? this.name : this.provisional_name();
|
||||
}
|
||||
|
||||
provisional_name() {
|
||||
// Return a generated name for the timer based on the timer's
|
||||
// origin and current value
|
||||
|
||||
return (
|
||||
Time_utils.formatDuration(this.origin / Math.abs(this.rate))
|
||||
Time_utils.formatDuration(this.to_msec(this.origin))
|
||||
+ ' / '
|
||||
+ Time_utils.formatDuration(Math.abs(this.get() / Math.abs(this.rate)))
|
||||
+ Time_utils.formatDuration(this.to_msec())
|
||||
);
|
||||
}
|
||||
|
||||
display_status() {
|
||||
// Return a string representing the timer's status
|
||||
// (e.g. running, paused, expired)
|
||||
|
||||
let status = '';
|
||||
|
||||
// Indicate timer expired if its current value is <= 0 and it's
|
||||
|
|
@ -64,10 +85,14 @@ class PrimitiveTimer {
|
|||
}
|
||||
|
||||
is_running() {
|
||||
// Return true if the timer is running, false if it is paused
|
||||
|
||||
return !this._pause_time;
|
||||
}
|
||||
|
||||
start() {
|
||||
// Start the timer if it is paused
|
||||
|
||||
if (!this.is_running()) {
|
||||
this._start_time += Date.now() - this._pause_time;
|
||||
this._pause_time = null;
|
||||
|
|
@ -75,6 +100,8 @@ class PrimitiveTimer {
|
|||
}
|
||||
|
||||
pause() {
|
||||
// Pause the timer if it is running
|
||||
|
||||
if (this.is_running()) {
|
||||
this._pause_time = Date.now();
|
||||
}
|
||||
|
|
@ -85,6 +112,8 @@ class PrimitiveTimer {
|
|||
}
|
||||
|
||||
get() {
|
||||
// Return the current value of the timer, in rate units
|
||||
|
||||
const now = Date.now();
|
||||
const elapsed =
|
||||
(now - this._start_time)
|
||||
|
|
@ -93,6 +122,8 @@ class PrimitiveTimer {
|
|||
}
|
||||
|
||||
set(new_value) {
|
||||
// Set the timer to a new value, in rate units
|
||||
|
||||
const now = Date.now();
|
||||
this._start_time = (now - new_value / this.rate)
|
||||
+ (this.origin / this.rate);
|
||||
|
|
@ -101,9 +132,9 @@ class PrimitiveTimer {
|
|||
}
|
||||
}
|
||||
|
||||
// Convert given timer value to milliseconds using this.rate
|
||||
// Uses the current value of the timer if no value is provided
|
||||
to_msec(value) {
|
||||
// Convert given timer value to milliseconds using this.rate
|
||||
// Uses the current value of the timer if no value is provided
|
||||
if (value === undefined) {
|
||||
value = this.get();
|
||||
}
|
||||
|
|
@ -111,6 +142,8 @@ class PrimitiveTimer {
|
|||
}
|
||||
|
||||
dump() {
|
||||
// Serialize the timer object to a JSON-compatible object
|
||||
|
||||
return {
|
||||
cls: 'PrimitiveTimer',
|
||||
version: 0,
|
||||
|
|
@ -127,6 +160,9 @@ class PrimitiveTimer {
|
|||
}
|
||||
|
||||
static load(data) {
|
||||
// Deserialize a JSON-compatible object to a PrimitiveTimer
|
||||
// object
|
||||
|
||||
if (!(data.cls == 'PrimitiveTimer' && data.version == 0)) {
|
||||
console.error('Incompatible data type for loading PrimitiveTimer state');
|
||||
}
|
||||
|
|
@ -143,6 +179,9 @@ class PrimitiveTimer {
|
|||
|
||||
|
||||
function format_duration(msec, have_seconds) {
|
||||
// Format a duration in milliseconds as a string in HH:MM format
|
||||
// (have_seconds is false) or HH:MM:SS format (have_seconds is true)
|
||||
|
||||
if (msec < 0) {
|
||||
return '-' + format_duration(-msec, have_seconds);
|
||||
}
|
||||
|
|
@ -189,10 +228,13 @@ function find_timer_by_id(id) {
|
|||
}
|
||||
|
||||
function load_timers() {
|
||||
// Load timers from persistent storage
|
||||
// If no timers are found, create and return a default timer
|
||||
|
||||
console.log('loading timers');
|
||||
let timers = Storage.readJSON(TIMERS_FILENAME, true) || [];
|
||||
if (timers.length) {
|
||||
// Deserealize timer objects
|
||||
// Deserialize timer objects
|
||||
timers = timers.map(t => PrimitiveTimer.load(t));
|
||||
} else {
|
||||
timers = [new PrimitiveTimer(600, false, -0.001, '', 1)];
|
||||
|
|
@ -202,6 +244,8 @@ function load_timers() {
|
|||
}
|
||||
|
||||
function save_timers() {
|
||||
// Save TIMERS to persistent storage
|
||||
|
||||
console.log('saving timers');
|
||||
const dumped_timers = TIMERS.map(t => t.dump());
|
||||
if (!Storage.writeJSON(TIMERS_FILENAME, dumped_timers)) {
|
||||
|
|
@ -210,6 +254,11 @@ function save_timers() {
|
|||
}
|
||||
|
||||
function schedule_save_timers() {
|
||||
// Schedule a save of the timers to persistent storage
|
||||
// after a timeout. This is used to reduce the number of
|
||||
// writes to the flash storage when several changes are
|
||||
// made in a short time.
|
||||
|
||||
if (SAVE_TIMERS_TIMEOUT === null) {
|
||||
console.log('scheduling timer save');
|
||||
SAVE_TIMERS_TIMEOUT = setTimeout(() => {
|
||||
|
|
@ -222,6 +271,8 @@ function schedule_save_timers() {
|
|||
}
|
||||
|
||||
function save_settings() {
|
||||
// Save SETTINGS to persistent storage
|
||||
|
||||
console.log('saving settings');
|
||||
if (!Storage.writeJSON(SETTINGS_FILENAME, SETTINGS)) {
|
||||
E.showAlert('Trouble saving settings');
|
||||
|
|
@ -229,6 +280,11 @@ function save_settings() {
|
|||
}
|
||||
|
||||
function schedule_save_settings() {
|
||||
// Schedule a save of the settings to persistent storage
|
||||
// after a timeout. This is used to reduce the number of
|
||||
// writes to the flash storage when several changes are
|
||||
// made in a short time.
|
||||
|
||||
if (SAVE_SETTINGS_TIMEOUT === null) {
|
||||
console.log('scheduling settings save');
|
||||
SAVE_SETTINGS_TIMEOUT = setTimeout(() => {
|
||||
|
|
@ -255,6 +311,10 @@ var TIMERS = load_timers();
|
|||
// Persistent data convenience functions
|
||||
|
||||
function delete_timer(timers, timer) {
|
||||
// Find `timer` in array `timers` and remove it.
|
||||
// Return the next timer in the list, or the last one if `timer`
|
||||
// was the last one in the list.
|
||||
|
||||
const idx = timers.indexOf(timer);
|
||||
if (idx !== -1) {
|
||||
timers.splice(idx, 1);
|
||||
|
|
@ -267,6 +327,11 @@ function delete_timer(timers, timer) {
|
|||
}
|
||||
|
||||
function add_timer(timers, timer) {
|
||||
// Create a independent timer object duplicating `timer`, assign it a
|
||||
// new unique ID, and add it to the top of the array `timers`.
|
||||
// Return the new timer object.
|
||||
// This is used to create a new timer from an existing one.
|
||||
|
||||
// Create a copy of current timer object
|
||||
const new_timer = PrimitiveTimer.load(timer.dump());
|
||||
// Assign a new ID to the timer
|
||||
|
|
@ -277,6 +342,9 @@ function add_timer(timers, timer) {
|
|||
}
|
||||
|
||||
function set_last_viewed_timer(timer) {
|
||||
// Move `timer` to the top of the list of timers, so it will be
|
||||
// displayed first when the timer list is shown.
|
||||
|
||||
const idx = TIMERS.indexOf(timer);
|
||||
if (idx == -1) {
|
||||
console.warn('set_last_viewed_timer: Bug? Called with a timer not found in list');
|
||||
|
|
@ -291,11 +359,17 @@ function set_last_viewed_timer(timer) {
|
|||
}
|
||||
|
||||
function set_timers_dirty() {
|
||||
// Mark the timers as modified and schedule a write to
|
||||
// persistent storage.
|
||||
|
||||
setTimeout(update_system_alarms, 500);
|
||||
schedule_save_timers();
|
||||
}
|
||||
|
||||
function set_settings_dirty() {
|
||||
// Mark the settings as modified and schedule a write to
|
||||
// persistent storage.
|
||||
|
||||
schedule_save_settings();
|
||||
}
|
||||
|
||||
|
|
@ -303,6 +377,9 @@ function set_settings_dirty() {
|
|||
// Alarm handling //
|
||||
|
||||
function delete_system_alarms() {
|
||||
// Delete system alarms associated with the tevtimer app (except those
|
||||
// that are snoozed, so that they will trigger later)
|
||||
|
||||
var alarms = Sched.getAlarms().filter(a => a.appid == 'tevtimer');
|
||||
for (let alarm of alarms) {
|
||||
if (alarm.ot === undefined) {
|
||||
|
|
@ -317,6 +394,9 @@ function delete_system_alarms() {
|
|||
}
|
||||
|
||||
function set_system_alarms() {
|
||||
// Set system alarms (via `sched` app) for running countdown timers
|
||||
// that will expire in the future.
|
||||
|
||||
for (let idx = 0; idx < TIMERS.length; idx++) {
|
||||
let timer = TIMERS[idx];
|
||||
let time_to_next_alarm = timer.to_msec();
|
||||
|
|
@ -335,11 +415,15 @@ function set_system_alarms() {
|
|||
}
|
||||
|
||||
function update_system_alarms() {
|
||||
// Refresh system alarms (`sched` app) to reflect changes to timers
|
||||
|
||||
delete_system_alarms();
|
||||
set_system_alarms();
|
||||
}
|
||||
|
||||
|
||||
// Make sure we save timers and settings when switching to another app
|
||||
// or rebooting
|
||||
E.on('kill', () => { save_timers(); });
|
||||
E.on('kill', () => { save_settings(); });
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue