From 30e4a4a62a896862ef3b125c605519bcc7cd45a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zlatko=20=C4=90uri=C4=87?= Date: Sun, 13 Apr 2025 21:17:17 +0200 Subject: [PATCH] added timer-complete display --- lang/de.json | 19 +++++++++++- lang/en.json | 19 +++++++++++- lang/hr.json | 19 +++++++++++- src/add-timer-screen.js | 38 ++++++++++++++++++++++++ src/timer-complete-screen.js | 27 ++++++++++++++++++ src/{render.js => timer-screen.js} | 33 ++++++++++++++++++++- src/timer.js | 2 +- src/timer.loop.js | 46 +++++++++++++++++++++++++++--- src/timer.repository.js | 8 ++++++ templates/add-timer.hbs | 10 +++++++ templates/timer-complete.hbs | 1 + templates/timer.hbs | 17 +++++++++++ 12 files changed, 230 insertions(+), 9 deletions(-) create mode 100644 src/add-timer-screen.js create mode 100644 src/timer-complete-screen.js rename src/{render.js => timer-screen.js} (72%) create mode 100644 templates/add-timer.hbs create mode 100644 templates/timer-complete.hbs diff --git a/lang/de.json b/lang/de.json index 522707f..13c5fe5 100644 --- a/lang/de.json +++ b/lang/de.json @@ -5,6 +5,23 @@ "time-remaining": "Verbliebend", "resume": "Fortsetzen", "pause": "Anhalten", - "delete": "Löschen" + "delete": "Löschen", + "resume-runner": "Timer fortsetzen", + "pause-runner": "Timer anhalten", + "status": { + "timers-are": "Timers sind", + "timers-paused": "pausiert", + "timers-active": "aktiv", + "add-timer": "Timer hinzufügen" + }, + "timer": { + "complete": "Timer fertig", + "your-timer-is-complete": "Dein Timer \"{name}\" ist ausgelaufen" + }, + "add-timer": { + "timer name": "Timer Name", + "duration": "Dauer", + "format-hint": "Nutze den Format n (nur Sekunden), mm:ss oder hh:mm:ss für Stunden/Minuten/Sekunden.hours/minutes/seconds." + } } } diff --git a/lang/en.json b/lang/en.json index efe28bd..39537c1 100644 --- a/lang/en.json +++ b/lang/en.json @@ -5,6 +5,23 @@ "time-remaining": "Time remaining", "resume": "Resume", "pause": "Pause", - "delete": "Delete" + "delete": "Delete", + "resume-runner": "Resume timer", + "pause-runner": "Pause timer", + "status": { + "timers-are": "Timers are", + "timers-paused": "paused", + "timers-active": "active", + "add-timer": "Add timer" + }, + "timer": { + "complete": "Timer complete", + "your-timer-is-complete": "Your timer \"{name}\" is complete" + }, + "add-timer": { + "timer name": "Timer name", + "duration": "Duration", + "format-hint": "Use format n (for seconds), mm:ss or hh:mm:ss for hours/minutes/seconds." + } } } diff --git a/lang/hr.json b/lang/hr.json index f4e50e7..af7529a 100644 --- a/lang/hr.json +++ b/lang/hr.json @@ -5,6 +5,23 @@ "time-remaining": "Preostalo vrijeme", "resume": "Nastavi", "pause": "Zaustavi", - "delete": "Obriši" + "delete": "Obriši", + "resume-runner": "Nastavi timer", + "pause-runner": "Zaustavi timer", + "status": { + "timers-are": "Brojači su", + "timers-paused": "zaustavljeni", + "timers-active": "aktivni", + "add-timer": "Dodaj timer" + }, + "timer": { + "complete": "Timer gotov", + "your-timer-is-complete": "Tvoj timer \"{name}\" je završen" + }, + "add-timer": { + "timer name": "Ime timera", + "duration": "Trajanje", + "format-hint": "Koristi šprancu n za sekunde, mm:ss ili hh:mm:ss za sate/minute/sekunde." + } } } diff --git a/src/add-timer-screen.js b/src/add-timer-screen.js new file mode 100644 index 0000000..86f25e3 --- /dev/null +++ b/src/add-timer-screen.js @@ -0,0 +1,38 @@ +import { logger } from './logger.js'; + +const templatePath = `modules/yet-another-timer/templates/add-timer.hbs`; + +export class AddTimerScreen extends FormApplication {a + static get defaultOptions() { + const defaults = super.defaultOptions; + + const overrides = { + height: "auto", + id: "yet-another-timer-add-timer", + template: templatePath, + title: game.i18n?.localize("YAT.status.add-timer") || "Add Timer", + }; + return Object.assign({}, defaults, overrides); + } + + getData() { + return { + }; + } + + activateListeners(html) { + logger.debug('Activating listeners...'); + html.on('click', "[data-action]", this.#handleClick.bind(this)); + logger.debug('Activated.'); + } + + #handleClick(event) { + logger.debug('**click**', event); + const el = $(event.currentTarget); + const action = el.data().action; + logger.debug('handle debug on ', action); + const data = $(el).parents('form'); + + logger.debug('Data:', data); + } +} diff --git a/src/timer-complete-screen.js b/src/timer-complete-screen.js new file mode 100644 index 0000000..535fa26 --- /dev/null +++ b/src/timer-complete-screen.js @@ -0,0 +1,27 @@ +import { logger } from './logger.js'; + +const templatePath = `modules/yet-another-timer/templates/timer-complete.hbs`; + +export class TimerCompleteScreen extends FormApplication {a + static get defaultOptions() { + const defaults = super.defaultOptions; + + const overrides = { + height: "auto", + id: "yet-another-timer-add-timer", + template: templatePath, + title: game.i18n?.localize("YAT.timer.complete") || "Timer complete", + }; + return Object.assign({}, defaults, overrides); + } + + data = {}; + + setData(data) { + this.data = data; + } + + getData() { + return this.data; + } +} diff --git a/src/render.js b/src/timer-screen.js similarity index 72% rename from src/render.js rename to src/timer-screen.js index 0a761be..b197e8b 100644 --- a/src/render.js +++ b/src/timer-screen.js @@ -1,5 +1,7 @@ import { logger } from "./logger.js"; import { getTimers } from "./timer.repository.js"; +import { getStatus, pauseTimer, resumeTimer, deleteTimer, flipTimers, subscribe } from './timer.loop.js'; +import { TimerError } from "./error.js"; const templatePath = `modules/yet-another-timer/templates/timer.hbs`; @@ -39,13 +41,20 @@ export class TimerScreen extends FormApplication { getData() { return { timers: getTimers(), + config: { + isPaused: getStatus() + } }; } activateListeners(html) { logger.debug('Activating listeners...'); - html.on('click', "[data-action]", this.#handleClick); + html.on('click', "[data-action]", this.#handleClick.bind(this)); logger.debug('Activated.'); + // also make sure we're always active + subscribe(() => { + this.render(); + }); } #handleClick(event) { @@ -55,6 +64,28 @@ export class TimerScreen extends FormApplication { const timerName = el.parents('[data-timer-name]')?.data()?.timerName; console.log(el); logger.debug('timerName and action', timerName, action); + + switch(action) { + case 'flip-timers': + flipTimers(); + break; + case 'pause': + pauseTimer(timerName); + break; + case 'resume': + resumeTimer(timerName); + break; + case 'delete': + deleteTimer(timerName); + break; + case 'add-timer': + showAddAction() + break; + default: + logger.error(`Unknown timer action: ${action}`); + throw new TimerError(`Unknown timer action: ${action}`); + } + this.render(); } } diff --git a/src/timer.js b/src/timer.js index f5d6b73..2b9df5a 100644 --- a/src/timer.js +++ b/src/timer.js @@ -1,7 +1,7 @@ import { logger } from './logger.js'; import { startTimers, stopTimers, resumeTimer } from './timer.loop.js'; import { createTimer } from './timer.repository.js'; -import { TimerScreen } from "./render.js"; +import { TimerScreen } from "./timer-screen.js"; let isPaused = true; diff --git a/src/timer.loop.js b/src/timer.loop.js index 35fc695..12c3029 100644 --- a/src/timer.loop.js +++ b/src/timer.loop.js @@ -1,14 +1,28 @@ import { logger } from "./logger.js"; import { TimerError } from "./error.js"; -import { getActiveTimers, getTimer } from "./timer.repository.js"; -import { logTimer } from "./render.js"; +import { getActiveTimers, getTimer, deleteTimer as repoDeleteTimer } from "./timer.repository.js"; +import { logTimer } from "./timer-screen.js"; +import { TimerCompleteScreen } from "./timer-complete-screen.js"; const INTERVAL_MS = 1000; // main loop interval const state = { timerInterval: null, + subscribers: [], }; +export function getStatus() { + return state.timerInterval === null; +} + +export function flipTimers() { + if (getStatus()) { + startTimers(); + } else { + stopTimers(); + } +} + export function startTimers() { if (state.timerInterval !== null) { throw new TimerError('Loop already running'); @@ -16,6 +30,11 @@ export function startTimers() { logger.debug(`Starting main timer loop`); state.timerInterval = setInterval(() => runLoop(), INTERVAL_MS); + ping(); +} + +export function subscribe(cb) { + state.subscribers.push(cb); } export function stopTimers() { @@ -23,10 +42,10 @@ export function stopTimers() { throw new TimerError('Loop not running.'); } + logger.debug('Stopping main timer loop.'); clearInterval(state.timerInterval); state.timerInterval = null; - - logger.debug('Stopping main timer loop.'); + ping(); } export function pauseTimer(timerName = '') { @@ -36,6 +55,7 @@ export function pauseTimer(timerName = '') { } else { logger.info(`Pausing timer ${timerName}.`); timer.isPaused = true; + ping(); } } @@ -46,9 +66,14 @@ export function resumeTimer(timerName = '') { } else { logger.info(`Resuming timer ${timerName}.`); timer.isPaused = false; + ping(); } } +export function deleteTimer(timerName) { + repoDeleteTimer(timerName); +} + function runLoop() { logger.debug(`Running loop...`); const timers = getActiveTimers(); @@ -58,6 +83,15 @@ function runLoop() { advance(timer, INTERVAL_MS); logTimer(timer); } + if (timers.length > 0) { + ping(); + } +} + +function ping() { + for (const sub of state.subscribers) { + sub(); + } } function advance(timer, interval_ms) { @@ -76,4 +110,8 @@ function advance(timer, interval_ms) { function completeTimer(timer) { logger.log(`Timer ${timer.name} completed.`); timer.isPaused = true; + // ping? close something? + const timerComplete = new TimerCompleteScreen(); + timerComplete.setData({ name: timer.name }); + timerComplete.render(true); } diff --git a/src/timer.repository.js b/src/timer.repository.js index 33458b2..338390e 100644 --- a/src/timer.repository.js +++ b/src/timer.repository.js @@ -49,6 +49,14 @@ export function getTimer(timerName = '') { return timerMap.get(timerName); } +export function deleteTimer(timerName = '') { + if (timerMap.has(timerName)) { + timerMap.delete(timerName); + } else { + throw new TimerError(`Trying to delete non-existent timer ${timerName}.`); + } +} + /** * Create a new timer. * @param {TimeString} [durationString='01:00'] - the timer duration diff --git a/templates/add-timer.hbs b/templates/add-timer.hbs new file mode 100644 index 0000000..07fb801 --- /dev/null +++ b/templates/add-timer.hbs @@ -0,0 +1,10 @@ +

{{ localize "YAT.status.add-timer" }}

+ +
+ + + {{ localize "YAT.add-timer.format-hint" }} + + + +
diff --git a/templates/timer-complete.hbs b/templates/timer-complete.hbs new file mode 100644 index 0000000..db6dc99 --- /dev/null +++ b/templates/timer-complete.hbs @@ -0,0 +1 @@ +

{{ localize "YAT.timer.your-timer-is-complete" name=name }}!

diff --git a/templates/timer.hbs b/templates/timer.hbs index 32cff09..b8e8daf 100644 --- a/templates/timer.hbs +++ b/templates/timer.hbs @@ -1,5 +1,22 @@

{{localize "YAT.title" }}

+
+

{{ localize "YAT.status.timers-are" }} {{#if config.isPaused }}{{ localize "YAT.status.timers-paused" }}{{else}}{{ localize "YAT.status.timers-active"}}{{/if}}.

+ + + +
+ +
+
{{#each timers }}