Add quick settings timer

Adds a new quick settings timer/stopwatch module with timer and chrono modes, preset controls, and finish notifications. Updates the README with usage details and screenshots, and adds the new icon/image assets.
This commit is contained in:
√(noham)²
2026-07-06 12:32:44 +02:00
parent 422af63bdb
commit 7bf4c219e4
9 changed files with 390 additions and 2 deletions

2
.gitignore vendored
View File

@@ -4,3 +4,5 @@ hashchange
.DS_Store .DS_Store
DOC.md DOC.md
.opencode/skills/qmd-port/SKILL.md .opencode/skills/qmd-port/SKILL.md
NOTIFICATION.md
SLEEP.md

View File

@@ -0,0 +1,368 @@
; Quick Settings Timer/Chrono
; Adds a countdown timer and stopwatch to the quick settings panel
; Timer state lives in Values.timerManager so it persists across menu opens/closes
AFFECT [[1658694193319203921]]
TRAVERSE [[6502786168]]
LOCATE AFTER ALL
INSERT {
property ~&214620122227&~ timerManager: _timerManager
~&6502786168&~ {
~&5972374&~: _timerManager
property ~&6503679477&~ timerMode: ~&6504329801&~
property ~&197088788&~ totalMs: 0
property ~&197088788&~ remainMs: 0
property ~&6503679477&~ isRunning: ~&214625660372&~
property ~&7083178290016&~ ~&478322454160073828&~: "00:00"
property ~&6503679477&~ ~&16765420033347753489&~: ~&214625660372&~
property ~&197088788&~ presetMs: 60000
property ~&6503679477&~ addMode: ~&6504329801&~
function fmt(~&5972521&~) {
~&197102514&~ ~&180970&~ = ~&6502909715&~.~&197079679&~(~&5972521&~);
~&197102514&~ ~&180977&~ = ~&6502909715&~.~&214626058827&~(~&180970&~ / 3600000);
~&197102514&~ ~&180982&~ = ~&6502909715&~.~&214626058827&~((~&180970&~ % 3600000) / 60000);
~&197102514&~ ~&180988&~ = ~&6502909715&~.~&214626058827&~((~&180970&~ % 60000) / 1000);
~&197102514&~ mm = ~&180982&~.~&7713616118928163&~().~&7713428190834284&~(2, ~&'180921&~);
~&197102514&~ ss = ~&180988&~.~&7713616118928163&~().~&7713428190834284&~(2, ~&'180921&~);
~&5972376&~ (~&180977&~ > 0) {
~&7083121450889&~ ~&180977&~.~&7713616118928163&~().~&7713428190834284&~(2, ~&'180921&~) + ~&"180931&~ + mm + ~&"180931&~ + ss;
}
~&7083121450889&~ mm + ~&"180931&~ + ss;
}
function refresh() {
~&5972376&~ (timerMode) {
~&478322454160073828&~ = fmt(remainMs > 0 ? remainMs : 0);
} ~&6503784146&~ {
~&478322454160073828&~ = fmt(totalMs);
}
}
function go() {
~&5972376&~ (timerMode) {
~&5972376&~ (remainMs <= 0) ~&7083121450889&~;
}
~&16765420033347753489&~ = ~&214625660372&~;
isRunning = ~&6504329801&~;
_tick.~&214641748151&~();
}
function ~&6504295855&~() {
isRunning = ~&214625660372&~;
_tick.~&6504295855&~();
}
function doReset() {
~&6504295855&~();
~&16765420033347753489&~ = ~&214625660372&~;
~&5972376&~ (timerMode) {
remainMs = totalMs;
} ~&6503784146&~ {
totalMs = 0;
}
refresh();
}
~&214604601930&~ {
~&5972374&~: _tick
~&7713147298280334&~: 100
~&7083121289162&~: ~&6504329801&~
~&495358363329399331&~: {
~&5972376&~ (_timerManager.timerMode) {
_timerManager.remainMs -= 100;
~&5972376&~ (_timerManager.remainMs <= 0) {
_timerManager.remainMs = 0;
_timerManager.~&6504295855&~();
_timerManager.~&16765420033347753489&~ = ~&6504329801&~;
}
} ~&6503784146&~ {
_timerManager.totalMs += 100;
}
_timerManager.refresh();
}
}
}
}
END TRAVERSE
END AFFECT
AFFECT [[12542166428983872557]]
TRAVERSE [[7711468349764991]] > [[6502786168]] > [[8397788359424131273]] > [[14125623155555875541]]#[[233718721544006]]
LOCATE AFTER [[14125623155555875541]]#[[471169070310690832]]
INSERT {
~&425121728314878811&~.~&15740235808997988493&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&7081629735527&~.~&254549367831075482&~: ~&254477762679831355&~.~&214603824602&~.~&7713684474795983&~.~&7713442318223278&~.~&233744706647566&~.~&214641496386&~
}
~&14125623155555875541&~ {
~&5972374&~: _timerUI
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&7081629735527&~.~&8399743405844438450&~: ~&254477762679831355&~.~&214603824602&~.~&7713684474795983&~.~&7713442318223278&~.~&233740248806464&~.~&214641496386&~
~&7081629735527&~.~&499747351624466981&~: ~&254477762679831355&~.~&214603824602&~.~&7713684474795983&~.~&7713442318223278&~.~&233740248806464&~.~&214641496386&~
~&7081629735527&~.~&254549367831075482&~: ~&254477762679831355&~.~&214603824602&~.~&7713684474795983&~.~&7713442318223278&~.~&233744706647566&~.~&214641496386&~
~&233744706647566&~: ~&254477762679831355&~.~&214603824602&~.~&7713684474795983&~.~&7713442318223278&~.~&233744706647566&~.~&7082925185962&~
/* Mode selector tabs */
~&254501558939456351&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&233744706647566&~: 0
~&7712155293725601&~ {
~&214634455770&~: [
{ ~&197101097&~: ~&"214604601930&~, isTimer: ~&6504329801&~ },
{ ~&197101097&~: "Chrono", isTimer: ~&214625660372&~ }
]
~&7712922269353028&~: ~&6502786168&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&7081629735527&~.~&17520348323745447649&~: 68
readonly property ~&6503679477&~ ~&7082453764421&~: ~&7082020628281&~.timerManager.timerMode === ~&254539508423767444&~.isTimer
~&6503165774&~ {
~&233721384511543&~.~&7712879746914881&~: ~&7083038346995&~
~&6504315758&~: ~&254539508423767444&~.~&197101097&~
~&6503823200&~.~&254543497768871654&~: 24
~&6503823200&~.~&6503679370&~: ~&7082453764421&~
~&214622605608&~: ~&7082453764421&~ ? ~&7082020628281&~.~&8399340017235344933&~ : "#888888"
}
~&254494525842443467&~ {
~&233721384511543&~.~&6503816592&~: ~&7083038346995&~
~&254542236275632405&~: {
~&7082020628281&~.timerManager.~&6504295855&~();
~&7082020628281&~.timerManager.timerMode = ~&254539508423767444&~.isTimer;
~&5972376&~ (!~&254539508423767444&~.isTimer) {
~&7082020628281&~.timerManager.totalMs = 0;
}
~&7082020628281&~.timerManager.refresh();
}
}
~&254501108490678590&~ {
~&233721384511543&~.~&7082507142622&~: ~&7083038346995&~.~&7082507142622&~
~&233721384511543&~.~&6504027668&~: ~&7083038346995&~.~&6504027668&~
~&233721384511543&~.~&214640173127&~: ~&7083038346995&~.~&214640173127&~
~&7082729686082&~: 3
~&214622605608&~: ~&7082453764421&~ ? ~&7082020628281&~.~&8399340017235344933&~ : ~&"503220030291830651&~
}
}
}
}
/* Time display (fixed width to avoid resizing) */
~&6502786168&~ {
~&7081629735527&~.~&254522510204479688&~: ~&5971598&~.~&14019785274593562237&~
~&7081629735527&~.~&7797818826744279624&~: 300
~&7081629735527&~.~&17520348323745447649&~: _display.~&2122835675838176157&~
~&6503165774&~ {
~&5972374&~: _display
~&233721384511543&~.~&7712879746914881&~: ~&7083038346995&~
~&6504315758&~: ~&7082020628281&~.timerManager.~&478322454160073828&~
~&6503823200&~.~&254543497768871654&~: 56
~&6503823200&~.~&7083316716977&~: ~&6502673216&~.ExtraLight
~&214622605608&~: ~&7082020628281&~.~&8399340017235344933&~
~&15450610953915458578&~: ~&6503165774&~.~&14019785274593562237&~
}
}
/* Preset buttons (timer mode only) */
~&254501558939456351&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&233744706647566&~: ~&254477762679831355&~.~&214603824602&~.~&7713684474795983&~.~&7713442318223278&~.~&233744706647566&~.~&214641496386&~
~&233748328658231&~: ~&7082020628281&~.timerManager.timerMode
~&7712155293725601&~ {
~&214634455770&~: [
{ ~&197101097&~: "1 m", ~&197102508&~: 60000 },
{ ~&197101097&~: "5 m", ~&197102508&~: 300000 },
{ ~&197101097&~: "10 m", ~&197102508&~: 600000 },
{ ~&197101097&~: "30 m", ~&197102508&~: 1800000 },
{ ~&197101097&~: "1 h", ~&197102508&~: 3600000 }
]
~&7712922269353028&~: ~&6502786168&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&7081629735527&~.~&17520348323745447649&~: 50
~&254501108490678590&~ {
~&233721384511543&~.~&6503816592&~: ~&7083038346995&~
~&7083116119249&~: 8
~&214622605608&~: "#EEEEEE"
}
~&6503165774&~ {
~&233721384511543&~.~&7712879746914881&~: ~&7083038346995&~
~&6504315758&~: ~&254539508423767444&~.~&197101097&~
~&6503823200&~.~&254543497768871654&~: 20
~&6503823200&~.~&6503679370&~: ~&6504329801&~
~&214622605608&~: ~&7082020628281&~.~&8399340017235344933&~
}
~&254494525842443467&~ {
~&233721384511543&~.~&6503816592&~: ~&7083038346995&~
~&254542236275632405&~: {
~&7082020628281&~.timerManager.~&6504295855&~();
~&7082020628281&~.timerManager.presetMs = ~&254539508423767444&~.~&197102508&~;
~&5972376&~ (~&7082020628281&~.timerManager.addMode) {
~&7082020628281&~.timerManager.totalMs += ~&254539508423767444&~.~&197102508&~;
~&7082020628281&~.timerManager.remainMs += ~&254539508423767444&~.~&197102508&~;
} ~&6503784146&~ {
~&7082020628281&~.timerManager.totalMs = ~&254539508423767444&~.~&197102508&~;
~&7082020628281&~.timerManager.remainMs = ~&254539508423767444&~.~&197102508&~;
}
~&7082020628281&~.timerManager.refresh();
}
}
}
}
}
/* Control buttons */
~&254501558939456351&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&233744706647566&~: ~&254477762679831355&~.~&214603824602&~.~&7713684474795983&~.~&7713442318223278&~.~&233744706647566&~.~&214641496386&~
/* Add/Set toggle (timer only) */
~&6502786168&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&7081629735527&~.~&17520348323745447649&~: 70
~&233748328658231&~: ~&7082020628281&~.timerManager.timerMode
~&254501108490678590&~ {
~&233721384511543&~.~&6503816592&~: ~&7083038346995&~
~&7083116119249&~: 8
~&7082507052999&~.~&214622605608&~: "#888888"
~&7082507052999&~.~&214646099849&~: 1
~&214622605608&~: ~&"503220030291830651&~
}
~&425121728314878811&~.~&6502767986&~ {
~&233721384511543&~.~&7712879746914881&~: ~&7083038346995&~
~&6504284228&~: ~&425121728314878811&~.~&7082020628281&~.~&7713132906001613&~.~&214641496386&~
~&7083172477658&~: ~&7082020628281&~.timerManager.addMode ? ~&"15094524446772001204&~ : ~&"5724976033632521381&~
}
~&254494525842443467&~ {
~&233721384511543&~.~&6503816592&~: ~&7083038346995&~
~&254542236275632405&~: {
~&7082020628281&~.timerManager.addMode = !~&7082020628281&~.timerManager.addMode;
}
}
}
/* Reset */
~&6502786168&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&7081629735527&~.~&17520348323745447649&~: 70
~&254501108490678590&~ {
~&233721384511543&~.~&6503816592&~: ~&7083038346995&~
~&7083116119249&~: 8
~&7082507052999&~.~&214622605608&~: "#888888"
~&7082507052999&~.~&214646099849&~: 1
~&214622605608&~: ~&"503220030291830651&~
}
~&425121728314878811&~.~&6502767986&~ {
~&233721384511543&~.~&7712879746914881&~: ~&7083038346995&~
~&6504284228&~: ~&425121728314878811&~.~&7082020628281&~.~&7713132906001613&~.~&214641496386&~
~&7083172477658&~: ~&"6968812144639225076&~
}
~&254494525842443467&~ {
~&233721384511543&~.~&6503816592&~: ~&7083038346995&~
~&254542236275632405&~: ~&7082020628281&~.timerManager.doReset()
}
}
/* Start / Stop */
~&6502786168&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&7081629735527&~.~&17520348323745447649&~: 70
~&254501108490678590&~ {
~&233721384511543&~.~&6503816592&~: ~&7083038346995&~
~&7083116119249&~: 8
~&214622605608&~: ~&7082020628281&~.timerManager.isRunning ? "#EEEEEE" : ~&7082020628281&~.~&8399340017235344933&~
}
~&6503165774&~ {
~&233721384511543&~.~&7712879746914881&~: ~&7083038346995&~
~&6504315758&~: ~&7082020628281&~.timerManager.isRunning ? "Stop" : "Start"
~&6503823200&~.~&254543497768871654&~: 20
~&6503823200&~.~&6503679370&~: ~&6504329801&~
~&214622605608&~: ~&7082020628281&~.timerManager.isRunning ? ~&7082020628281&~.~&8399340017235344933&~ : ~&7082020628281&~.~&8399340017260114793&~
}
~&254494525842443467&~ {
~&233721384511543&~.~&6503816592&~: ~&7083038346995&~
~&254542236275632405&~: {
~&7082020628281&~.timerManager.isRunning ? ~&7082020628281&~.timerManager.~&6504295855&~() : ~&7082020628281&~.timerManager.go();
}
}
}
}
}
~&425121728314878811&~.~&15740235808997988493&~ {
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&7081629735527&~.~&254549367831075482&~: ~&254477762679831355&~.~&214603824602&~.~&7713684474795983&~.~&7713442318223278&~.~&233744706647566&~.~&214641496386&~
}
}
END TRAVERSE
END AFFECT
; Notification bar when timer finishes - visible in all modes
AFFECT [[2328484894988065446]]
IMPORT [[233700934949963.233693781272506]] [[180922.180921]]
TRAVERSE [[8397788359424131273]]#[[6504254477]] > [[8397993708429497603]]#[[7713531976371484]]
LOCATE AFTER ALL
INSERT {
~&425121728314878811&~.~&11119534664549952261&~ {
~&233721384511543&~.~&6504027668&~: ~&7083038346995&~.~&6504027668&~
~&233721384511543&~.~&214640173127&~: ~&7083038346995&~.~&214640173127&~
~&233721384511543&~.~&7082507142622&~: ~&7083038346995&~.~&7082507142622&~
~&233748328658231&~: ~&7082020628281&~.timerManager.~&16765420033347753489&~
~&6504337259&~: ~&254477762679831355&~.~&11119534664549952261&~.~&233740920352621&~
~&425121728314878811&~.~&11119534664549952261&~.~&233695222288046&~ {
~&6504315758&~: "Time's up! (" + ~&7082020628281&~.timerManager.fmt(~&7082020628281&~.timerManager.totalMs) + ~&"180914&~
~&7081629735527&~.~&254529418434902000&~: ~&6504329801&~
~&7081629735527&~.~&8399743405844438450&~: ~&425121728314878811&~.~&7082020628281&~.~&233740248806464&~.~&214641496386&~
~&7081629735527&~.~&499747351624466981&~: ~&425121728314878811&~.~&7082020628281&~.~&233740248806464&~.~&214641496386&~
}
~&425121728314878811&~.~&11119534664549952261&~.~&7081261925573&~ {
~&6504315758&~: ~&"233701679664206&~
~&254542236275632405&~: {
~&7082020628281&~.timerManager.doReset();
~&7082020628281&~.timerManager.go();
}
}
~&425121728314878811&~.~&11119534664549952261&~.~&233683758819504&~ { }
~&425121728314878811&~.~&11119534664549952261&~.~&7081261925573&~ {
~&6504315758&~: "+1min"
~&254542236275632405&~: {
~&7082020628281&~.timerManager.totalMs += 60000;
~&7082020628281&~.timerManager.remainMs += 60000;
~&7082020628281&~.timerManager.~&16765420033347753489&~ = ~&214625660372&~;
~&7082020628281&~.timerManager.go();
}
}
~&425121728314878811&~.~&11119534664549952261&~.~&233683758819504&~ { }
~&425121728314878811&~.~&11119534664549952261&~.~&7081261925573&~ {
~&6504315758&~: "+5min"
~&254542236275632405&~: {
~&7082020628281&~.timerManager.totalMs += 300000;
~&7082020628281&~.timerManager.remainMs += 300000;
~&7082020628281&~.timerManager.~&16765420033347753489&~ = ~&214625660372&~;
~&7082020628281&~.timerManager.go();
}
}
~&425121728314878811&~.~&11119534664549952261&~.~&233683758819504&~ { }
~&425121728314878811&~.~&11119534664549952261&~.~&7081261925573&~ {
~&6504315758&~: ~&"214584551711&~
~&254542236275632405&~: {
~&7082020628281&~.timerManager.~&16765420033347753489&~ = ~&214625660372&~;
}
}
}
}
END TRAVERSE
END AFFECT

View File

@@ -34,12 +34,21 @@ Beta releases are not tested nor supported.
<img src="images/batteryPercentage.png" width="400"> <img src="images/batteryPercentage.png" width="400">
#### `quickSettingsTimer.qmd`
<!-- [![vellum](https://img.shields.io/badge/vellum-quick--settings--timer-purple)](https://vellum.delivery/#/package/quick-settings-timer/) -->
- Adds a countdown timer and stopwatch to the Quick Settings panel, under the light slider.
- Switch between Timer (presets: 1min, 5min, 10min, 30min, 1h) and Chrono (start/stop) modes.
- Preset buttons respect the add/set mode toggle : <img src="images/plus.svg" width="20" height="20"> increments, <img src="images/plus_circle.svg" width="20" height="20"> replaces.
- Notification bar shows "Time's up! (duration)" when the timer finishes.
<img src="images/quickSettingsTimer_1.png" width="300"> <img src="images/quickSettingsTimer_2.png" width="300">
<img src="images/quickSettingsTimer_3.png" width="600">
#### `clock.qmd` #### `clock.qmd`
[![vellum](https://img.shields.io/badge/vellum-sidebar--clock-purple)](https://vellum.delivery/#/package/sidebar-clock/) [![vellum](https://img.shields.io/badge/vellum-sidebar--clock-purple)](https://vellum.delivery/#/package/sidebar-clock/)
- Adds a live clock to the library sidebar; tap the entry to toggle seconds display. - Adds a live clock to the library sidebar; tap the entry to toggle seconds display.
<img src="images/clock_1.png" width="400"> <img src="images/clock_1.png" width="300"><img src="images/clock_2.png" width="300">
<img src="images/clock_2.png" width="400">
Note: You have to set the right timezone on the tablet (you can use [reManager](https://github.com/rmitchellscott/reManager) to set it) Note: You have to set the right timezone on the tablet (you can use [reManager](https://github.com/rmitchellscott/reManager) to set it)
#### `convertToText_remover.qmd` #### `convertToText_remover.qmd`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

4
images/plus.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2" y="2" width="44" height="44" rx="8" fill="white"/>
<path d="M18.0074 22.5C20.4893 22.496 22.5 20.4828 22.5 18V6H25.5V18C25.5 20.4828 27.5106 22.4959 29.9924 22.5L42 22.5V25.5L29.9913 25.5C27.51 25.5047 25.5 27.5176 25.5 30V42H22.5V30C22.5 27.5149 20.485 25.5 18 25.5L6 25.5V22.5H18.0074Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 419 B

5
images/plus_circle.svg Normal file
View File

@@ -0,0 +1,5 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2" y="2" width="44" height="44" rx="8" fill="white"/>
<path d="M15 22.5H19.5C21.1569 22.5 22.5 21.1569 22.5 19.5V15H25.5V19.5C25.5 21.1569 26.8431 22.5 28.5 22.5L33 22.5V25.5L28.4932 25.5C26.8395 25.5037 25.5 26.8454 25.5 28.5V33H22.5V28.5C22.5 26.8454 21.1605 25.5037 19.5068 25.5L15 25.5V22.5Z" fill="black"/>
<path d="M24 4.5C34.7696 4.5 43.5 13.2304 43.5 24C43.5 34.7696 34.7696 43.5 24 43.5C13.2304 43.5 4.5 34.7696 4.5 24C4.5 13.2304 13.2304 4.5 24 4.5ZM40.5 24C40.5 14.8873 33.1127 7.5 24 7.5C14.8873 7.5 7.5 14.8873 7.5 24C7.5 33.1127 14.8873 40.5 24 40.5C33.1127 40.5 40.5 33.1127 40.5 24Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB