From 714b660cab3fd3f7a840024a6fd2522cd6b303cc Mon Sep 17 00:00:00 2001 From: Rico Date: Sun, 1 Feb 2026 13:25:53 +0100 Subject: [PATCH 01/23] input UI --- timer@KopfdesDaemons/README.md | 3 + .../files/timer@KopfdesDaemons/desklet.js | 58 ++++++++++++++++++ .../files/timer@KopfdesDaemons/icon.png | Bin 0 -> 4318 bytes .../files/timer@KopfdesDaemons/metadata.json | 8 +++ .../files/timer@KopfdesDaemons/stylesheet.css | 20 ++++++ timer@KopfdesDaemons/info.json | 3 + 6 files changed, 92 insertions(+) create mode 100644 timer@KopfdesDaemons/README.md create mode 100644 timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js create mode 100644 timer@KopfdesDaemons/files/timer@KopfdesDaemons/icon.png create mode 100644 timer@KopfdesDaemons/files/timer@KopfdesDaemons/metadata.json create mode 100644 timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css create mode 100644 timer@KopfdesDaemons/info.json diff --git a/timer@KopfdesDaemons/README.md b/timer@KopfdesDaemons/README.md new file mode 100644 index 000000000..1684aefb9 --- /dev/null +++ b/timer@KopfdesDaemons/README.md @@ -0,0 +1,3 @@ +# Icons + +- [Desklet Icon](https://github.com/googlefonts/noto-emoji/blob/main/png/128/emoji_u231b.png) [OFL-1.1](https://github.com/googlefonts/noto-emoji?tab=OFL-1.1-1-ov-file) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js new file mode 100644 index 000000000..f419ddd74 --- /dev/null +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -0,0 +1,58 @@ +const Desklet = imports.ui.desklet; +const St = imports.gi.St; + +class MyDesklet extends Desklet.Desklet { + constructor(metadata, deskletId) { + super(metadata, deskletId); + + this.setHeader("Timer"); + this._setupInputLayout(); + } + + _setupInputLayout() { + const box = new St.BoxLayout({ vertical: true }); + + const labelRow = new St.BoxLayout(); + const timeLabel = new St.Label({ text: "00h 00m 00s", style_class: "timer-time-label", x_expand: true }); + labelRow.add_child(timeLabel); + box.add_child(labelRow); + + // Input buttons 1-9 + for (let i = 0; i < 3; i++) { + const row = new St.BoxLayout(); + for (let j = 1; j <= 3; j++) { + const num = i * 3 + j; + const button = new St.Button({ label: num.toString(), style_class: "timer-input-button" }); + row.add_child(button); + } + box.add_child(row); + } + + const lastRow = new St.BoxLayout(); + lastRow.add_child(new St.Button({ label: "0", style_class: "timer-input-button" })); + + const playIcon = new St.Icon({ + icon_name: "media-playback-start-symbolic", + icon_type: St.IconType.SYMBOLIC, + icon_size: 16, + }); + const playBtn = new St.Button({ child: playIcon, style_class: "timer-input-button" }); + lastRow.add_child(playBtn); + + const editIcon = new St.Icon({ + icon_name: "edit-clear-symbolic", + icon_type: St.IconType.SYMBOLIC, + icon_size: 16, + }); + const editBtn = new St.Button({ child: editIcon, style_class: "timer-input-button" }); + lastRow.add_child(editBtn); + + box.add_child(lastRow); + + this.setContent(box); + } +} + +function main(metadata, deskletId) { + return new MyDesklet(metadata, deskletId); +} diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/icon.png b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9db0475f0ebc1c8f11f5d4d33613540b3870295d GIT binary patch literal 4318 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 M07*qoM6N<$f=+PvU;qFB literal 0 HcmV?d00001 diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/metadata.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/metadata.json new file mode 100644 index 000000000..89a2cc947 --- /dev/null +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/metadata.json @@ -0,0 +1,8 @@ +{ + "uuid": "timer@KopfdesDaemons", + "name": "Timer", + "description": "Set a timer for a user-defined time.", + "version": "1.0.0", + "max-instances": "50", + "author": "KopfdesDaemons" +} diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css new file mode 100644 index 000000000..79c03a7e6 --- /dev/null +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css @@ -0,0 +1,20 @@ +.timer-input-button { + font-size: 1.8em; + /* padding: 0.5em 0.8em; */ + margin: 0.1em; + background-color: rgba(24, 23, 23, 0.527); + border-radius: 1em; + height: 2em; + width: 2em; +} + +.timer-input-button-action:hover, +.timer-input-button:hover { + background-color: rgba(65, 61, 61, 0.527); +} + +.timer-time-label { + width: 100%; + text-align: center; + font-size: 1.5em; +} diff --git a/timer@KopfdesDaemons/info.json b/timer@KopfdesDaemons/info.json new file mode 100644 index 000000000..e776b90bd --- /dev/null +++ b/timer@KopfdesDaemons/info.json @@ -0,0 +1,3 @@ +{ + "author": "KopfdesDaemons" +} From 053d69ef9af52804c061f5690be5fbe1cdac488b Mon Sep 17 00:00:00 2001 From: Rico Date: Sun, 1 Feb 2026 13:38:01 +0100 Subject: [PATCH 02/23] input label --- .../files/timer@KopfdesDaemons/desklet.js | 28 +++++++++++++++++-- .../files/timer@KopfdesDaemons/stylesheet.css | 3 +- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index f419ddd74..dcdc09137 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -6,6 +6,7 @@ class MyDesklet extends Desklet.Desklet { super(metadata, deskletId); this.setHeader("Timer"); + this._inputDigits = ""; this._setupInputLayout(); } @@ -13,8 +14,8 @@ class MyDesklet extends Desklet.Desklet { const box = new St.BoxLayout({ vertical: true }); const labelRow = new St.BoxLayout(); - const timeLabel = new St.Label({ text: "00h 00m 00s", style_class: "timer-time-label", x_expand: true }); - labelRow.add_child(timeLabel); + this._inputLabel = new St.Label({ text: "00h 00m 00s", style_class: "timer-input-label", x_expand: true }); + labelRow.add_child(this._inputLabel); box.add_child(labelRow); // Input buttons 1-9 @@ -23,13 +24,16 @@ class MyDesklet extends Desklet.Desklet { for (let j = 1; j <= 3; j++) { const num = i * 3 + j; const button = new St.Button({ label: num.toString(), style_class: "timer-input-button" }); + button.connect("clicked", () => this._onDigitPressed(num)); row.add_child(button); } box.add_child(row); } const lastRow = new St.BoxLayout(); - lastRow.add_child(new St.Button({ label: "0", style_class: "timer-input-button" })); + const zeroBtn = new St.Button({ label: "0", style_class: "timer-input-button" }); + zeroBtn.connect("clicked", () => this._onDigitPressed(0)); + lastRow.add_child(zeroBtn); const playIcon = new St.Icon({ icon_name: "media-playback-start-symbolic", @@ -45,12 +49,30 @@ class MyDesklet extends Desklet.Desklet { icon_size: 16, }); const editBtn = new St.Button({ child: editIcon, style_class: "timer-input-button" }); + editBtn.connect("clicked", () => this._onEditPressed()); lastRow.add_child(editBtn); box.add_child(lastRow); this.setContent(box); } + + _onDigitPressed(num) { + if (this._inputDigits.length < 6) { + this._inputDigits += num.toString(); + this._updateInputLabel(); + } + } + + _onEditPressed() { + this._inputDigits = this._inputDigits.slice(0, -1); + this._updateInputLabel(); + } + + _updateInputLabel() { + const padded = this._inputDigits.padStart(6, "0"); + this._inputLabel.set_text(`${padded.slice(0, 2)}h ${padded.slice(2, 4)}m ${padded.slice(4, 6)}s`); + } } function main(metadata, deskletId) { diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css index 79c03a7e6..6cb7ed86b 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css @@ -1,6 +1,5 @@ .timer-input-button { font-size: 1.8em; - /* padding: 0.5em 0.8em; */ margin: 0.1em; background-color: rgba(24, 23, 23, 0.527); border-radius: 1em; @@ -13,7 +12,7 @@ background-color: rgba(65, 61, 61, 0.527); } -.timer-time-label { +.timer-input-label { width: 100%; text-align: center; font-size: 1.5em; From 1147f6da7919f5cdd61e881182686faf31fa402b Mon Sep 17 00:00:00 2001 From: Rico Date: Sun, 1 Feb 2026 14:29:37 +0100 Subject: [PATCH 03/23] timer UI --- .../files/timer@KopfdesDaemons/desklet.js | 154 +++++++++++++++++- 1 file changed, 151 insertions(+), 3 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index dcdc09137..e4fea396c 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -1,16 +1,38 @@ const Desklet = imports.ui.desklet; const St = imports.gi.St; +const Cogl = imports.gi.Cogl; +const Cairo = imports.cairo; +const Clutter = imports.gi.Clutter; class MyDesklet extends Desklet.Desklet { constructor(metadata, deskletId) { super(metadata, deskletId); + this.default_size = 180; + this.isRunning = false; + + // Use default values if settings are not yet set + this.labelColor = "rgb(51, 209, 122)"; + this.scaleSize = 1; + this.indicatorColor = "rgb(51, 209, 122)"; + this.rotationSpeed = 2; + this.circleWidth = 0.03; + this.indicatorLength = 10; + this.circleColor = "rgb(255, 255, 255)"; + this.setHeader("Timer"); this._inputDigits = ""; + + this.mainContainer = new St.Widget({ + layout_manager: new Clutter.BinLayout(), + }); + this.setContent(this.mainContainer); this._setupInputLayout(); } _setupInputLayout() { + this.mainContainer.destroy_all_children(); + const box = new St.BoxLayout({ vertical: true }); const labelRow = new St.BoxLayout(); @@ -40,8 +62,9 @@ class MyDesklet extends Desklet.Desklet { icon_type: St.IconType.SYMBOLIC, icon_size: 16, }); - const playBtn = new St.Button({ child: playIcon, style_class: "timer-input-button" }); - lastRow.add_child(playBtn); + const startBtn = new St.Button({ child: playIcon, style_class: "timer-input-button" }); + lastRow.add_child(startBtn); + startBtn.connect("clicked", () => this._onStartPressed()); const editIcon = new St.Icon({ icon_name: "edit-clear-symbolic", @@ -54,7 +77,7 @@ class MyDesklet extends Desklet.Desklet { box.add_child(lastRow); - this.setContent(box); + this.mainContainer.add_child(box); } _onDigitPressed(num) { @@ -73,6 +96,131 @@ class MyDesklet extends Desklet.Desklet { const padded = this._inputDigits.padStart(6, "0"); this._inputLabel.set_text(`${padded.slice(0, 2)}h ${padded.slice(2, 4)}m ${padded.slice(4, 6)}s`); } + + _onStartPressed() { + this._setupTimerUI(); + } + + _setupTimerUI() { + this.mainContainer.destroy_all_children(); + + const absoluteSize = this.default_size * this.scaleSize; + + // Create the circle actor for the canvas + this.circleActor = new Clutter.Actor({ + width: absoluteSize, + height: absoluteSize, + }); + this.mainContainer.add_child(this.circleActor); + this._drawCircle(); + + // Create a vertical box layout for the time and buttons + const centerContent = new St.BoxLayout({ vertical: true }); + this.mainContainer.add_child(centerContent); + + // Create and style the time label + this.timeLabel = new St.Label({ + text: "00h 00m 00s", + style: `font-size: ${20 * this.scaleSize}px; color: ${this.labelColor};`, + }); + centerContent.add_child(new St.Bin({ child: this.timeLabel, x_align: St.Align.MIDDLE })); + + // Create a horizontal box for the buttons + const buttonRow = new St.BoxLayout({ style: "spacing: 10px;" }); + + const playIcon = new St.Icon({ + icon_name: "media-playback-start-symbolic", + icon_type: St.IconType.SYMBOLIC, + icon_size: 16, + }); + this.playBtn = new St.Button({ child: playIcon, style_class: "timer-input-button" }); + this.playBtn.hide(); + this.playBtn.connect("clicked", () => this._onPlayPressed()); + buttonRow.add_child(this.playBtn); + + const pauseIcon = new St.Icon({ + icon_name: "media-playback-pause-symbolic", + icon_type: St.IconType.SYMBOLIC, + icon_size: 16, + }); + this.pauseBtn = new St.Button({ child: pauseIcon, style_class: "timer-input-button" }); + this.pauseBtn.connect("clicked", () => this._onPausePressed()); + buttonRow.add_child(this.pauseBtn); + + const stopIcon = new St.Icon({ + icon_name: "media-playback-stop-symbolic", + icon_type: St.IconType.SYMBOLIC, + icon_size: 16, + }); + this.stopBtn = new St.Button({ child: stopIcon, style_class: "timer-input-button" }); + this.stopBtn.connect("clicked", () => this._onStopPressed()); + buttonRow.add_child(this.stopBtn); + + centerContent.add_child(new St.Bin({ child: buttonRow, x_align: St.Align.MIDDLE })); + } + + _onPausePressed() { + this.isRunning = false; + this.pauseBtn.hide(); + this.playBtn.show(); + } + + _onStopPressed() { + this._inputDigits = ""; + this._setupInputLayout(); + } + + _onPlayPressed() { + this.isRunning = true; + this.playBtn.hide(); + this.pauseBtn.show(); + } + + _drawCircle() { + const canvas = new Clutter.Canvas(); + const absoluteSize = this.default_size * this.scaleSize; + canvas.set_size(absoluteSize * global.ui_scale, absoluteSize * global.ui_scale); + + canvas.connect("draw", (canvas, cr, width, height) => { + cr.save(); + cr.setOperator(Cairo.Operator.CLEAR); + cr.paint(); + cr.restore(); + cr.setOperator(Cairo.Operator.OVER); + cr.scale(width, height); + cr.translate(0.5, 0.5); + + // Draw the background circle + const rgbaCircle = this._rgbToRgba(this.circleColor); + cr.setSourceRGBA(rgbaCircle[0], rgbaCircle[1], rgbaCircle[2], 0.2); + cr.setLineWidth(this.circleWidth); + cr.arc(0, 0, 0.4, 0, Math.PI * 2); + cr.stroke(); + + // Draw the indicator arc + const rgbaIndicator = this._rgbToRgba(this.indicatorColor); + cr.setSourceRGBA(rgbaIndicator[0], rgbaIndicator[1], rgbaIndicator[2], 1); + cr.setLineWidth(this.circleWidth); + const arcEnd = (this.indicatorLength * (Math.PI * 2)) / 100 - Math.PI * 0.5; + cr.arc(0, 0, 0.4, 0 - Math.PI * 0.5, arcEnd); + cr.stroke(); + + return true; + }); + + canvas.invalidate(); + this.circleActor.set_content(canvas); + this.circleActor.set_pivot_point(0.5, 0.5); + } + + // Parses an RGB string to a RGBA array for Cairo + _rgbToRgba(colorString) { + const match = colorString.match(/\d+/g); + if (match && match.length === 3) { + return match.map(Number).map(c => c / 255); + } + return [0.3, 0.8, 0.5]; // Default color if parsing fails + } } function main(metadata, deskletId) { From 9e5cde41841b9e4d67b12088ca0bf10e8ece87cb Mon Sep 17 00:00:00 2001 From: Rico Date: Sun, 1 Feb 2026 15:01:28 +0100 Subject: [PATCH 04/23] timer logic --- .../files/timer@KopfdesDaemons/desklet.js | 104 +++++++++++++++++- 1 file changed, 101 insertions(+), 3 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index e4fea396c..733298201 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -3,6 +3,7 @@ const St = imports.gi.St; const Cogl = imports.gi.Cogl; const Cairo = imports.cairo; const Clutter = imports.gi.Clutter; +const Mainloop = imports.mainloop; class MyDesklet extends Desklet.Desklet { constructor(metadata, deskletId) { @@ -10,6 +11,9 @@ class MyDesklet extends Desklet.Desklet { this.default_size = 180; this.isRunning = false; + this._timeout = null; + this._totalSeconds = 0; + this._remainingMs = 0; // Use default values if settings are not yet set this.labelColor = "rgb(51, 209, 122)"; @@ -98,7 +102,18 @@ class MyDesklet extends Desklet.Desklet { } _onStartPressed() { - this._setupTimerUI(); + const padded = this._inputDigits.padStart(6, "0"); + const h = parseInt(padded.slice(0, 2)); + const m = parseInt(padded.slice(2, 4)); + const s = parseInt(padded.slice(4, 6)); + this._totalSeconds = h * 3600 + m * 60 + s; + + if (this._totalSeconds > 0) { + this._remainingMs = this._totalSeconds * 1000; + this.indicatorLength = 100; + this._setupTimerUI(); + this._startTimer(); + } } _setupTimerUI() { @@ -138,6 +153,16 @@ class MyDesklet extends Desklet.Desklet { this.playBtn.connect("clicked", () => this._onPlayPressed()); buttonRow.add_child(this.playBtn); + const refreshIcon = new St.Icon({ + icon_name: "view-refresh-symbolic", + icon_type: St.IconType.SYMBOLIC, + icon_size: 16, + }); + this.restartBtn = new St.Button({ child: refreshIcon, style_class: "timer-input-button" }); + this.restartBtn.hide(); + this.restartBtn.connect("clicked", () => this._onRestartPressed()); + buttonRow.add_child(this.restartBtn); + const pauseIcon = new St.Icon({ icon_name: "media-playback-pause-symbolic", icon_type: St.IconType.SYMBOLIC, @@ -160,20 +185,86 @@ class MyDesklet extends Desklet.Desklet { } _onPausePressed() { + if (this._timeout) { + Mainloop.source_remove(this._timeout); + this._timeout = null; + } this.isRunning = false; this.pauseBtn.hide(); this.playBtn.show(); } _onStopPressed() { + if (this._timeout) { + Mainloop.source_remove(this._timeout); + this._timeout = null; + } + this.isRunning = false; this._inputDigits = ""; this._setupInputLayout(); } _onPlayPressed() { - this.isRunning = true; - this.playBtn.hide(); + if (this._remainingMs > 0) { + this._startTimer(); + this.playBtn.hide(); + this.pauseBtn.show(); + } + } + + _onRestartPressed() { + this._remainingMs = this._totalSeconds * 1000; + this.restartBtn.hide(); this.pauseBtn.show(); + this._startTimer(); + } + + _startTimer() { + this.isRunning = true; + this._endTime = Date.now() + this._remainingMs; + this._updateTimerVisuals(); + + if (this._timeout) Mainloop.source_remove(this._timeout); + this._timeout = Mainloop.timeout_add(10, this._updateTimer.bind(this)); + } + + _updateTimer() { + const now = Date.now(); + this._remainingMs = this._endTime - now; + + if (this._remainingMs <= 0) { + this._remainingMs = 0; + this._updateTimerVisuals(); + this.isRunning = false; + this._timeout = null; + this.playBtn.hide(); + this.pauseBtn.hide(); + this.restartBtn.show(); + return false; + } + + this._updateTimerVisuals(); + return true; + } + + _updateTimerVisuals() { + const totalSecondsLeft = Math.ceil(this._remainingMs / 1000); + const h = Math.floor(totalSecondsLeft / 3600); + const m = Math.floor((totalSecondsLeft % 3600) / 60); + const s = totalSecondsLeft % 60; + + const text = `${h.toString().padStart(2, "0")}h ${m.toString().padStart(2, "0")}m ${s.toString().padStart(2, "0")}s`; + if (this.timeLabel) this.timeLabel.set_text(text); + + if (this._totalSeconds > 0) { + this.indicatorLength = (this._remainingMs / (this._totalSeconds * 1000)) * 100; + } else { + this.indicatorLength = 0; + } + + if (this.circleActor && this.circleActor.get_content()) { + this.circleActor.get_content().invalidate(); + } } _drawCircle() { @@ -221,6 +312,13 @@ class MyDesklet extends Desklet.Desklet { } return [0.3, 0.8, 0.5]; // Default color if parsing fails } + + on_desklet_removed() { + if (this._timeout) { + Mainloop.source_remove(this._timeout); + this._timeout = null; + } + } } function main(metadata, deskletId) { From 1178c0a00b9e382d3ab432af2fe559df590be671 Mon Sep 17 00:00:00 2001 From: Rico Date: Sun, 1 Feb 2026 22:40:38 +0100 Subject: [PATCH 05/23] desklet scaling --- .../files/timer@KopfdesDaemons/desklet.js | 79 +++++++++++++------ .../timer@KopfdesDaemons/settings-schema.json | 41 ++++++++++ .../files/timer@KopfdesDaemons/stylesheet.css | 6 +- 3 files changed, 99 insertions(+), 27 deletions(-) create mode 100644 timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 733298201..767499f4b 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -4,6 +4,7 @@ const Cogl = imports.gi.Cogl; const Cairo = imports.cairo; const Clutter = imports.gi.Clutter; const Mainloop = imports.mainloop; +const Settings = imports.ui.settings; class MyDesklet extends Desklet.Desklet { constructor(metadata, deskletId) { @@ -19,11 +20,16 @@ class MyDesklet extends Desklet.Desklet { this.labelColor = "rgb(51, 209, 122)"; this.scaleSize = 1; this.indicatorColor = "rgb(51, 209, 122)"; - this.rotationSpeed = 2; this.circleWidth = 0.03; - this.indicatorLength = 10; this.circleColor = "rgb(255, 255, 255)"; + const settings = new Settings.DeskletSettings(this, metadata["uuid"], deskletId); + settings.bindProperty(Settings.BindingDirection.IN, "label-color", "labelColor", this._onSettingsChanged.bind(this)); + settings.bindProperty(Settings.BindingDirection.IN, "scale-size", "scaleSize", this._onSettingsChanged.bind(this)); + settings.bindProperty(Settings.BindingDirection.IN, "indicator-color", "indicatorColor", this._onSettingsChanged.bind(this)); + settings.bindProperty(Settings.BindingDirection.IN, "circle-width", "circleWidth", this._onSettingsChanged.bind(this)); + settings.bindProperty(Settings.BindingDirection.IN, "circle-color", "circleColor", this._onSettingsChanged.bind(this)); + this.setHeader("Timer"); this._inputDigits = ""; @@ -31,16 +37,28 @@ class MyDesklet extends Desklet.Desklet { layout_manager: new Clutter.BinLayout(), }); this.setContent(this.mainContainer); + this._setButtonStyles(); this._setupInputLayout(); } + _onSettingsChanged() { + this._setButtonStyles(); + if (this._totalSeconds > 0) this._setupTimerUI(); + else this._setupInputLayout(); + } + + _setButtonStyles() { + this.buttonStyle = `font-size: ${1.8 * this.scaleSize}em;`; + } + _setupInputLayout() { this.mainContainer.destroy_all_children(); const box = new St.BoxLayout({ vertical: true }); const labelRow = new St.BoxLayout(); - this._inputLabel = new St.Label({ text: "00h 00m 00s", style_class: "timer-input-label", x_expand: true }); + const labelStyle = `font-size: ${1.5 * this.scaleSize}em; color: ${this.labelColor};`; + this._inputLabel = new St.Label({ text: "00h 00m 00s", style_class: "timer-input-label", x_expand: true, style: labelStyle }); labelRow.add_child(this._inputLabel); box.add_child(labelRow); @@ -49,7 +67,11 @@ class MyDesklet extends Desklet.Desklet { const row = new St.BoxLayout(); for (let j = 1; j <= 3; j++) { const num = i * 3 + j; - const button = new St.Button({ label: num.toString(), style_class: "timer-input-button" }); + const button = new St.Button({ + label: num.toString(), + style_class: "timer-input-button", + style: this.buttonStyle, + }); button.connect("clicked", () => this._onDigitPressed(num)); row.add_child(button); } @@ -57,25 +79,37 @@ class MyDesklet extends Desklet.Desklet { } const lastRow = new St.BoxLayout(); - const zeroBtn = new St.Button({ label: "0", style_class: "timer-input-button" }); + const zeroBtn = new St.Button({ + label: "0", + style_class: "timer-input-button", + style: this.buttonStyle, + }); zeroBtn.connect("clicked", () => this._onDigitPressed(0)); lastRow.add_child(zeroBtn); const playIcon = new St.Icon({ icon_name: "media-playback-start-symbolic", icon_type: St.IconType.SYMBOLIC, - icon_size: 16, + icon_size: 16 * this.scaleSize, + }); + const startBtn = new St.Button({ + child: playIcon, + style_class: "timer-input-button", + style: this.buttonStyle, }); - const startBtn = new St.Button({ child: playIcon, style_class: "timer-input-button" }); lastRow.add_child(startBtn); startBtn.connect("clicked", () => this._onStartPressed()); const editIcon = new St.Icon({ icon_name: "edit-clear-symbolic", icon_type: St.IconType.SYMBOLIC, - icon_size: 16, + icon_size: 16 * this.scaleSize, + }); + const editBtn = new St.Button({ + child: editIcon, + style_class: "timer-input-button", + style: this.buttonStyle, }); - const editBtn = new St.Button({ child: editIcon, style_class: "timer-input-button" }); editBtn.connect("clicked", () => this._onEditPressed()); lastRow.add_child(editBtn); @@ -111,8 +145,8 @@ class MyDesklet extends Desklet.Desklet { if (this._totalSeconds > 0) { this._remainingMs = this._totalSeconds * 1000; this.indicatorLength = 100; - this._setupTimerUI(); this._startTimer(); + this._setupTimerUI(); } } @@ -121,7 +155,6 @@ class MyDesklet extends Desklet.Desklet { const absoluteSize = this.default_size * this.scaleSize; - // Create the circle actor for the canvas this.circleActor = new Clutter.Actor({ width: absoluteSize, height: absoluteSize, @@ -129,26 +162,23 @@ class MyDesklet extends Desklet.Desklet { this.mainContainer.add_child(this.circleActor); this._drawCircle(); - // Create a vertical box layout for the time and buttons const centerContent = new St.BoxLayout({ vertical: true }); this.mainContainer.add_child(centerContent); - // Create and style the time label this.timeLabel = new St.Label({ text: "00h 00m 00s", style: `font-size: ${20 * this.scaleSize}px; color: ${this.labelColor};`, }); centerContent.add_child(new St.Bin({ child: this.timeLabel, x_align: St.Align.MIDDLE })); - // Create a horizontal box for the buttons const buttonRow = new St.BoxLayout({ style: "spacing: 10px;" }); const playIcon = new St.Icon({ icon_name: "media-playback-start-symbolic", icon_type: St.IconType.SYMBOLIC, - icon_size: 16, + icon_size: 16 * this.scaleSize, }); - this.playBtn = new St.Button({ child: playIcon, style_class: "timer-input-button" }); + this.playBtn = new St.Button({ child: playIcon, style_class: "timer-input-button", style: this.buttonStyle }); this.playBtn.hide(); this.playBtn.connect("clicked", () => this._onPlayPressed()); buttonRow.add_child(this.playBtn); @@ -156,32 +186,34 @@ class MyDesklet extends Desklet.Desklet { const refreshIcon = new St.Icon({ icon_name: "view-refresh-symbolic", icon_type: St.IconType.SYMBOLIC, - icon_size: 16, + icon_size: 16 * this.scaleSize, }); - this.restartBtn = new St.Button({ child: refreshIcon, style_class: "timer-input-button" }); - this.restartBtn.hide(); + this.restartBtn = new St.Button({ child: refreshIcon, style_class: "timer-input-button", style: this.buttonStyle }); + if (this.isRunning) this.restartBtn.hide(); this.restartBtn.connect("clicked", () => this._onRestartPressed()); buttonRow.add_child(this.restartBtn); const pauseIcon = new St.Icon({ icon_name: "media-playback-pause-symbolic", icon_type: St.IconType.SYMBOLIC, - icon_size: 16, + icon_size: 16 * this.scaleSize, }); - this.pauseBtn = new St.Button({ child: pauseIcon, style_class: "timer-input-button" }); + this.pauseBtn = new St.Button({ child: pauseIcon, style_class: "timer-input-button", style: this.buttonStyle }); this.pauseBtn.connect("clicked", () => this._onPausePressed()); + if (!this.isRunning) this.pauseBtn.hide(); buttonRow.add_child(this.pauseBtn); const stopIcon = new St.Icon({ icon_name: "media-playback-stop-symbolic", icon_type: St.IconType.SYMBOLIC, - icon_size: 16, + icon_size: 16 * this.scaleSize, }); - this.stopBtn = new St.Button({ child: stopIcon, style_class: "timer-input-button" }); + this.stopBtn = new St.Button({ child: stopIcon, style_class: "timer-input-button", style: this.buttonStyle }); this.stopBtn.connect("clicked", () => this._onStopPressed()); buttonRow.add_child(this.stopBtn); centerContent.add_child(new St.Bin({ child: buttonRow, x_align: St.Align.MIDDLE })); + this._updateTimerVisuals(); } _onPausePressed() { @@ -200,6 +232,7 @@ class MyDesklet extends Desklet.Desklet { this._timeout = null; } this.isRunning = false; + this._totalSeconds = 0; this._inputDigits = ""; this._setupInputLayout(); } diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json new file mode 100644 index 000000000..a922de176 --- /dev/null +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json @@ -0,0 +1,41 @@ +{ + "head0": { + "type": "header", + "description": "Style" + }, + "label-color": { + "type": "colorchooser", + "default": "rgb(51, 209, 122)", + "description": "Label color" + }, + "scale-size": { + "type": "scale", + "default": 1, + "min": 0.7, + "max": 2, + "step": 0.05, + "description": "Desklet size" + }, + "head1": { + "type": "header", + "description": "Circle" + }, + "indicator-color": { + "type": "colorchooser", + "default": "rgb(51, 209, 122)", + "description": "Indicator color" + }, + "circle-color": { + "type": "colorchooser", + "default": "rgb(255, 255, 255)", + "description": "Circle color" + }, + "circle-width": { + "type": "scale", + "default": 0.03, + "min": 0.01, + "max": 0.2, + "step": 0.01, + "description": "Circle width" + } +} diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css index 6cb7ed86b..88ad7fea5 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css @@ -1,10 +1,9 @@ .timer-input-button { - font-size: 1.8em; margin: 0.1em; background-color: rgba(24, 23, 23, 0.527); - border-radius: 1em; - height: 2em; width: 2em; + height: 2em; + border-radius: 0.5em; } .timer-input-button-action:hover, @@ -15,5 +14,4 @@ .timer-input-label { width: 100%; text-align: center; - font-size: 1.5em; } From 600c70f8f0af20b5a6d7b0474d4ab341a17878b4 Mon Sep 17 00:00:00 2001 From: Rico Date: Mon, 2 Feb 2026 00:39:19 +0100 Subject: [PATCH 06/23] addTimeBtn, color settings --- .../files/timer@KopfdesDaemons/desklet.js | 53 +++++++++++++++---- .../timer@KopfdesDaemons/settings-schema.json | 13 ++++- .../files/timer@KopfdesDaemons/stylesheet.css | 10 +++- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 767499f4b..131bd473a 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -10,7 +10,7 @@ class MyDesklet extends Desklet.Desklet { constructor(metadata, deskletId) { super(metadata, deskletId); - this.default_size = 180; + this.default_size = 200; this.isRunning = false; this._timeout = null; this._totalSeconds = 0; @@ -22,6 +22,8 @@ class MyDesklet extends Desklet.Desklet { this.indicatorColor = "rgb(51, 209, 122)"; this.circleWidth = 0.03; this.circleColor = "rgb(255, 255, 255)"; + this.fillInnerCircle = false; + this.innerCircleColor = "rgba(255, 255, 255, 0.3)"; const settings = new Settings.DeskletSettings(this, metadata["uuid"], deskletId); settings.bindProperty(Settings.BindingDirection.IN, "label-color", "labelColor", this._onSettingsChanged.bind(this)); @@ -29,6 +31,8 @@ class MyDesklet extends Desklet.Desklet { settings.bindProperty(Settings.BindingDirection.IN, "indicator-color", "indicatorColor", this._onSettingsChanged.bind(this)); settings.bindProperty(Settings.BindingDirection.IN, "circle-width", "circleWidth", this._onSettingsChanged.bind(this)); settings.bindProperty(Settings.BindingDirection.IN, "circle-color", "circleColor", this._onSettingsChanged.bind(this)); + settings.bindProperty(Settings.BindingDirection.IN, "inner-circle-color", "innerCircleColor", this._onSettingsChanged.bind(this)); + settings.bindProperty(Settings.BindingDirection.IN, "fill-inner-circle", "fillInnerCircle", this._onSettingsChanged.bind(this)); this.setHeader("Timer"); this._inputDigits = ""; @@ -49,6 +53,7 @@ class MyDesklet extends Desklet.Desklet { _setButtonStyles() { this.buttonStyle = `font-size: ${1.8 * this.scaleSize}em;`; + this.addTimeButtonStyle = `font-size: ${1.2 * this.scaleSize}em;`; } _setupInputLayout() { @@ -167,7 +172,7 @@ class MyDesklet extends Desklet.Desklet { this.timeLabel = new St.Label({ text: "00h 00m 00s", - style: `font-size: ${20 * this.scaleSize}px; color: ${this.labelColor};`, + style: `font-size: ${1.5 * this.scaleSize}em; color: ${this.labelColor}; margin-top: ${0.5 * this.scaleSize}em;`, }); centerContent.add_child(new St.Bin({ child: this.timeLabel, x_align: St.Align.MIDDLE })); @@ -179,7 +184,7 @@ class MyDesklet extends Desklet.Desklet { icon_size: 16 * this.scaleSize, }); this.playBtn = new St.Button({ child: playIcon, style_class: "timer-input-button", style: this.buttonStyle }); - this.playBtn.hide(); + if (this.isRunning || this._remainingMs <= 0) this.playBtn.hide(); this.playBtn.connect("clicked", () => this._onPlayPressed()); buttonRow.add_child(this.playBtn); @@ -189,7 +194,7 @@ class MyDesklet extends Desklet.Desklet { icon_size: 16 * this.scaleSize, }); this.restartBtn = new St.Button({ child: refreshIcon, style_class: "timer-input-button", style: this.buttonStyle }); - if (this.isRunning) this.restartBtn.hide(); + if (this.isRunning || this._remainingMs > 0) this.restartBtn.hide(); this.restartBtn.connect("clicked", () => this._onRestartPressed()); buttonRow.add_child(this.restartBtn); @@ -213,6 +218,22 @@ class MyDesklet extends Desklet.Desklet { buttonRow.add_child(this.stopBtn); centerContent.add_child(new St.Bin({ child: buttonRow, x_align: St.Align.MIDDLE })); + + const addTimeBtn = new St.Button({ + label: "+1", + style_class: "timer-add-time-button", + style: this.addTimeButtonStyle, + }); + addTimeBtn.connect("clicked", () => { + this._remainingMs += 60 * 1000; + this._totalSeconds += 60; + if (this.isRunning) { + this._endTime += 60 * 1000; + } + this._updateTimerVisuals(); + }); + centerContent.add_child(new St.Bin({ child: addTimeBtn, x_align: St.Align.MIDDLE })); + this._updateTimerVisuals(); } @@ -314,16 +335,24 @@ class MyDesklet extends Desklet.Desklet { cr.scale(width, height); cr.translate(0.5, 0.5); + // Draw the inner circle + if (this.fillInnerCircle) { + const rgbaInner = this._rgbToRgba(this.innerCircleColor); + cr.setSourceRGBA(rgbaInner[0], rgbaInner[1], rgbaInner[2], rgbaInner[3]); + cr.arc(0, 0, 0.4 - this.circleWidth / 2, 0, Math.PI * 2); + cr.fill(); + } + // Draw the background circle const rgbaCircle = this._rgbToRgba(this.circleColor); - cr.setSourceRGBA(rgbaCircle[0], rgbaCircle[1], rgbaCircle[2], 0.2); + cr.setSourceRGBA(rgbaCircle[0], rgbaCircle[1], rgbaCircle[2], rgbaCircle[3]); cr.setLineWidth(this.circleWidth); cr.arc(0, 0, 0.4, 0, Math.PI * 2); cr.stroke(); // Draw the indicator arc const rgbaIndicator = this._rgbToRgba(this.indicatorColor); - cr.setSourceRGBA(rgbaIndicator[0], rgbaIndicator[1], rgbaIndicator[2], 1); + cr.setSourceRGBA(rgbaIndicator[0], rgbaIndicator[1], rgbaIndicator[2], rgbaIndicator[3]); cr.setLineWidth(this.circleWidth); const arcEnd = (this.indicatorLength * (Math.PI * 2)) / 100 - Math.PI * 0.5; cr.arc(0, 0, 0.4, 0 - Math.PI * 0.5, arcEnd); @@ -339,11 +368,15 @@ class MyDesklet extends Desklet.Desklet { // Parses an RGB string to a RGBA array for Cairo _rgbToRgba(colorString) { - const match = colorString.match(/\d+/g); - if (match && match.length === 3) { - return match.map(Number).map(c => c / 255); + const match = colorString.match(/\((.*?)\)/); + if (match && match[1]) { + const c = match[1].split(","); + if (c.length >= 3) { + const a = c.length >= 4 ? parseFloat(c[3]) : 1; + return [parseInt(c[0]) / 255, parseInt(c[1]) / 255, parseInt(c[2]) / 255, a]; + } } - return [0.3, 0.8, 0.5]; // Default color if parsing fails + return [0.3, 0.8, 0.5, 1]; // Default color if parsing fails } on_desklet_removed() { diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json index a922de176..b34ffbc97 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json @@ -27,9 +27,20 @@ }, "circle-color": { "type": "colorchooser", - "default": "rgb(255, 255, 255)", + "default": "rgba(255, 255, 255, 0.2)", "description": "Circle color" }, + "fill-inner-circle": { + "type": "checkbox", + "default": false, + "description": "Fill inner circle" + }, + "inner-circle-color": { + "type": "colorchooser", + "default": "rgba(255, 255, 255, 0.3)", + "description": "Inner circle color", + "dependency": "fill-inner-circle" + }, "circle-width": { "type": "scale", "default": 0.03, diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css index 88ad7fea5..dcd3d7fef 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/stylesheet.css @@ -7,7 +7,8 @@ } .timer-input-button-action:hover, -.timer-input-button:hover { +.timer-input-button:hover, +.timer-add-time-button:hover { background-color: rgba(65, 61, 61, 0.527); } @@ -15,3 +16,10 @@ width: 100%; text-align: center; } + +.timer-add-time-button { + border-radius: 0.5em; + width: 1.5em; + height: 1.5em; + padding: 0.2em; +} From 44700df02f0e609735a2f9add7e388865d5e9280 Mon Sep 17 00:00:00 2001 From: Rico Date: Mon, 2 Feb 2026 01:07:31 +0100 Subject: [PATCH 07/23] add screenshot, change default settings --- .../files/timer@KopfdesDaemons/desklet.js | 2 +- .../timer@KopfdesDaemons/settings-schema.json | 4 ++-- timer@KopfdesDaemons/screenshot.png | Bin 0 -> 41243 bytes 3 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 timer@KopfdesDaemons/screenshot.png diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 131bd473a..d105164da 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -22,7 +22,7 @@ class MyDesklet extends Desklet.Desklet { this.indicatorColor = "rgb(51, 209, 122)"; this.circleWidth = 0.03; this.circleColor = "rgb(255, 255, 255)"; - this.fillInnerCircle = false; + this.fillInnerCircle = true; this.innerCircleColor = "rgba(255, 255, 255, 0.3)"; const settings = new Settings.DeskletSettings(this, metadata["uuid"], deskletId); diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json index b34ffbc97..dacec38ea 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json @@ -32,7 +32,7 @@ }, "fill-inner-circle": { "type": "checkbox", - "default": false, + "default": true, "description": "Fill inner circle" }, "inner-circle-color": { @@ -45,7 +45,7 @@ "type": "scale", "default": 0.03, "min": 0.01, - "max": 0.2, + "max": 0.1, "step": 0.01, "description": "Circle width" } diff --git a/timer@KopfdesDaemons/screenshot.png b/timer@KopfdesDaemons/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..126b248d2459024930b76e60b772bc6795a441b0 GIT binary patch literal 41243 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 Date: Mon, 2 Feb 2026 19:55:38 +0100 Subject: [PATCH 08/23] decorations toggle --- .../files/timer@KopfdesDaemons/desklet.js | 8 ++++++++ .../files/timer@KopfdesDaemons/settings-schema.json | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index d105164da..154066745 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -24,6 +24,7 @@ class MyDesklet extends Desklet.Desklet { this.circleColor = "rgb(255, 255, 255)"; this.fillInnerCircle = true; this.innerCircleColor = "rgba(255, 255, 255, 0.3)"; + this.hideDecorations = false; const settings = new Settings.DeskletSettings(this, metadata["uuid"], deskletId); settings.bindProperty(Settings.BindingDirection.IN, "label-color", "labelColor", this._onSettingsChanged.bind(this)); @@ -33,6 +34,7 @@ class MyDesklet extends Desklet.Desklet { settings.bindProperty(Settings.BindingDirection.IN, "circle-color", "circleColor", this._onSettingsChanged.bind(this)); settings.bindProperty(Settings.BindingDirection.IN, "inner-circle-color", "innerCircleColor", this._onSettingsChanged.bind(this)); settings.bindProperty(Settings.BindingDirection.IN, "fill-inner-circle", "fillInnerCircle", this._onSettingsChanged.bind(this)); + settings.bindProperty(Settings.BindingDirection.IN, "hideDecorations", "hideDecorations", this.updateDecoration.bind(this)); this.setHeader("Timer"); this._inputDigits = ""; @@ -42,6 +44,7 @@ class MyDesklet extends Desklet.Desklet { }); this.setContent(this.mainContainer); this._setButtonStyles(); + this.updateDecoration(); this._setupInputLayout(); } @@ -51,6 +54,11 @@ class MyDesklet extends Desklet.Desklet { else this._setupInputLayout(); } + updateDecoration() { + this.metadata["prevent-decorations"] = this.hideDecorations; + this._updateDecoration(); + } + _setButtonStyles() { this.buttonStyle = `font-size: ${1.8 * this.scaleSize}em;`; this.addTimeButtonStyle = `font-size: ${1.2 * this.scaleSize}em;`; diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json index dacec38ea..cb773a9d4 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json @@ -16,6 +16,11 @@ "step": 0.05, "description": "Desklet size" }, + "hideDecorations": { + "type": "checkbox", + "description": "Hide decorations", + "default": false + }, "head1": { "type": "header", "description": "Circle" From fa2f3fd6f316c682771f8680fe13153101c40714 Mon Sep 17 00:00:00 2001 From: Rico Date: Mon, 2 Feb 2026 20:48:31 +0100 Subject: [PATCH 09/23] sound --- .../files/timer@KopfdesDaemons/desklet.js | 11 +++++++++++ .../timer@KopfdesDaemons/settings-schema.json | 18 +++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 154066745..4b9641c0f 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -5,6 +5,7 @@ const Cairo = imports.cairo; const Clutter = imports.gi.Clutter; const Mainloop = imports.mainloop; const Settings = imports.ui.settings; +const Util = imports.misc.util; class MyDesklet extends Desklet.Desklet { constructor(metadata, deskletId) { @@ -25,6 +26,7 @@ class MyDesklet extends Desklet.Desklet { this.fillInnerCircle = true; this.innerCircleColor = "rgba(255, 255, 255, 0.3)"; this.hideDecorations = false; + this.soundFile = "complete.oga"; const settings = new Settings.DeskletSettings(this, metadata["uuid"], deskletId); settings.bindProperty(Settings.BindingDirection.IN, "label-color", "labelColor", this._onSettingsChanged.bind(this)); @@ -35,6 +37,7 @@ class MyDesklet extends Desklet.Desklet { settings.bindProperty(Settings.BindingDirection.IN, "inner-circle-color", "innerCircleColor", this._onSettingsChanged.bind(this)); settings.bindProperty(Settings.BindingDirection.IN, "fill-inner-circle", "fillInnerCircle", this._onSettingsChanged.bind(this)); settings.bindProperty(Settings.BindingDirection.IN, "hideDecorations", "hideDecorations", this.updateDecoration.bind(this)); + settings.bindProperty(Settings.BindingDirection.IN, "sound-file", "soundFile", null); this.setHeader("Timer"); this._inputDigits = ""; @@ -302,6 +305,7 @@ class MyDesklet extends Desklet.Desklet { this.playBtn.hide(); this.pauseBtn.hide(); this.restartBtn.show(); + this._playSound(); return false; } @@ -374,6 +378,13 @@ class MyDesklet extends Desklet.Desklet { this.circleActor.set_pivot_point(0.5, 0.5); } + _playSound() { + if (this.soundFile && this.soundFile !== "none") { + const path = "/usr/share/sounds/freedesktop/stereo/" + this.soundFile; + Util.spawnCommandLine("paplay " + path); + } + } + // Parses an RGB string to a RGBA array for Cairo _rgbToRgba(colorString) { const match = colorString.match(/\((.*?)\)/); diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json index cb773a9d4..2e9ff603e 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json @@ -1,5 +1,21 @@ { "head0": { + "type": "header", + "description": "Sound" + }, + "sound-file": { + "type": "combobox", + "default": "service-login.oga", + "description": "Sound when the timer expires", + "options": { + "No Sound": "none", + "Alarm Clock": "alarm-clock-elapsed.oga", + "Complete": "complete.oga", + "Service login": "service-login.oga", + "Service logout": "service-logout.oga" + } + }, + "head1": { "type": "header", "description": "Style" }, @@ -21,7 +37,7 @@ "description": "Hide decorations", "default": false }, - "head1": { + "head2": { "type": "header", "description": "Circle" }, From 6f984858bd30077358f2a216600aa26b7c4faf15 Mon Sep 17 00:00:00 2001 From: Rico Date: Mon, 2 Feb 2026 21:10:30 +0100 Subject: [PATCH 10/23] german translation --- .../files/timer@KopfdesDaemons/po/de.po | 95 +++++++++++++++++++ .../po/timer@KopfdesDaemons.pot | 94 ++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po create mode 100644 timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po new file mode 100644 index 000000000..7b251c5f7 --- /dev/null +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po @@ -0,0 +1,95 @@ +# TIMER +# This file is put in the public domain. +# KopfdesDaemons, 2026 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: timer@KopfdesDaemons 1.0.0\n" +"Report-Msgid-Bugs-To: https://github.com/linuxmint/cinnamon-spices-desklets/" +"issues\n" +"POT-Creation-Date: 2026-02-02 20:49+0100\n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.4.2\n" + +#. metadata.json->name +msgid "Timer" +msgstr "Timer" + +#. metadata.json->description +msgid "Set a timer for a user-defined time." +msgstr "Stelle einen Timer für eine benutzerdefinierte Zeit." + +#. settings-schema.json->head0->description +msgid "Sound" +msgstr "Klang" + +#. settings-schema.json->sound-file->description +msgid "Sound when the timer expires" +msgstr "Ton, wenn der Timer abläuft" + +#. settings-schema.json->sound-file->options +msgid "No Sound" +msgstr "Kein Ton" + +#. settings-schema.json->sound-file->options +msgid "Alarm Clock" +msgstr "Wecker" + +#. settings-schema.json->sound-file->options +msgid "Complete" +msgstr "Complete" + +#. settings-schema.json->sound-file->options +msgid "Service login" +msgstr "Service login" + +#. settings-schema.json->sound-file->options +msgid "Service logout" +msgstr "Service logout" + +#. settings-schema.json->head1->description +msgid "Style" +msgstr "Stil" + +#. settings-schema.json->label-color->description +msgid "Label color" +msgstr "Labelfarbe" + +#. settings-schema.json->scale-size->description +msgid "Desklet size" +msgstr "Desklet Größe" + +#. settings-schema.json->hideDecorations->description +msgid "Hide decorations" +msgstr "Dekorationen verstecken" + +#. settings-schema.json->head2->description +msgid "Circle" +msgstr "Kreis" + +#. settings-schema.json->indicator-color->description +msgid "Indicator color" +msgstr "Indikatorfarbe" + +#. settings-schema.json->circle-color->description +msgid "Circle color" +msgstr "Kreisfarbe" + +#. settings-schema.json->fill-inner-circle->description +msgid "Fill inner circle" +msgstr "Fülle inneren Kreis" + +#. settings-schema.json->inner-circle-color->description +msgid "Inner circle color" +msgstr "Farbe des inneren Kreises" + +#. settings-schema.json->circle-width->description +msgid "Circle width" +msgstr "Kreisbreite" diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot new file mode 100644 index 000000000..ba391964f --- /dev/null +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot @@ -0,0 +1,94 @@ +# TIMER +# This file is put in the public domain. +# KopfdesDaemons, 2026 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: timer@KopfdesDaemons 1.0.0\n" +"Report-Msgid-Bugs-To: https://github.com/linuxmint/cinnamon-spices-desklets/" +"issues\n" +"POT-Creation-Date: 2026-02-02 20:49+0100\n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. metadata.json->name +msgid "Timer" +msgstr "" + +#. metadata.json->description +msgid "Set a timer for a user-defined time." +msgstr "" + +#. settings-schema.json->head0->description +msgid "Sound" +msgstr "" + +#. settings-schema.json->sound-file->description +msgid "Sound when the timer expires" +msgstr "" + +#. settings-schema.json->sound-file->options +msgid "No Sound" +msgstr "" + +#. settings-schema.json->sound-file->options +msgid "Alarm Clock" +msgstr "" + +#. settings-schema.json->sound-file->options +msgid "Complete" +msgstr "" + +#. settings-schema.json->sound-file->options +msgid "Service login" +msgstr "" + +#. settings-schema.json->sound-file->options +msgid "Service logout" +msgstr "" + +#. settings-schema.json->head1->description +msgid "Style" +msgstr "" + +#. settings-schema.json->label-color->description +msgid "Label color" +msgstr "" + +#. settings-schema.json->scale-size->description +msgid "Desklet size" +msgstr "" + +#. settings-schema.json->hideDecorations->description +msgid "Hide decorations" +msgstr "" + +#. settings-schema.json->head2->description +msgid "Circle" +msgstr "" + +#. settings-schema.json->indicator-color->description +msgid "Indicator color" +msgstr "" + +#. settings-schema.json->circle-color->description +msgid "Circle color" +msgstr "" + +#. settings-schema.json->fill-inner-circle->description +msgid "Fill inner circle" +msgstr "" + +#. settings-schema.json->inner-circle-color->description +msgid "Inner circle color" +msgstr "" + +#. settings-schema.json->circle-width->description +msgid "Circle width" +msgstr "" From 5bf387bfa0c85214f2c644511fdcb93e135ad069 Mon Sep 17 00:00:00 2001 From: Rico Date: Mon, 2 Feb 2026 21:59:54 +0100 Subject: [PATCH 11/23] change startup layout --- .../files/timer@KopfdesDaemons/desklet.js | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 4b9641c0f..18262ab98 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -13,6 +13,7 @@ class MyDesklet extends Desklet.Desklet { this.default_size = 200; this.isRunning = false; + this._isInputView = false; this._timeout = null; this._totalSeconds = 0; this._remainingMs = 0; @@ -48,13 +49,13 @@ class MyDesklet extends Desklet.Desklet { this.setContent(this.mainContainer); this._setButtonStyles(); this.updateDecoration(); - this._setupInputLayout(); + this._setupTimerUI(); } _onSettingsChanged() { this._setButtonStyles(); - if (this._totalSeconds > 0) this._setupTimerUI(); - else this._setupInputLayout(); + if (this._isInputView) this._setupInputLayout(); + else this._setupTimerUI(); } updateDecoration() { @@ -68,6 +69,7 @@ class MyDesklet extends Desklet.Desklet { } _setupInputLayout() { + this._isInputView = true; this.mainContainer.destroy_all_children(); const box = new St.BoxLayout({ vertical: true }); @@ -167,6 +169,7 @@ class MyDesklet extends Desklet.Desklet { } _setupTimerUI() { + this._isInputView = false; this.mainContainer.destroy_all_children(); const absoluteSize = this.default_size * this.scaleSize; @@ -189,13 +192,26 @@ class MyDesklet extends Desklet.Desklet { const buttonRow = new St.BoxLayout({ style: "spacing: 10px;" }); + const newTimerIcon = new St.Icon({ + icon_name: "list-add-symbolic", + icon_type: St.IconType.SYMBOLIC, + icon_size: 16 * this.scaleSize, + }); + this.newTimerBtn = new St.Button({ child: newTimerIcon, style_class: "timer-input-button", style: this.buttonStyle }); + this.newTimerBtn.connect("clicked", () => { + this._inputDigits = ""; + this._setupInputLayout(); + }); + if (this._totalSeconds > 0) this.newTimerBtn.hide(); + buttonRow.add_child(this.newTimerBtn); + const playIcon = new St.Icon({ icon_name: "media-playback-start-symbolic", icon_type: St.IconType.SYMBOLIC, icon_size: 16 * this.scaleSize, }); this.playBtn = new St.Button({ child: playIcon, style_class: "timer-input-button", style: this.buttonStyle }); - if (this.isRunning || this._remainingMs <= 0) this.playBtn.hide(); + if (this._totalSeconds === 0 || this.isRunning || this._remainingMs <= 0) this.playBtn.hide(); this.playBtn.connect("clicked", () => this._onPlayPressed()); buttonRow.add_child(this.playBtn); @@ -205,7 +221,7 @@ class MyDesklet extends Desklet.Desklet { icon_size: 16 * this.scaleSize, }); this.restartBtn = new St.Button({ child: refreshIcon, style_class: "timer-input-button", style: this.buttonStyle }); - if (this.isRunning || this._remainingMs > 0) this.restartBtn.hide(); + if (this._totalSeconds === 0 || this.isRunning || this._remainingMs > 0) this.restartBtn.hide(); this.restartBtn.connect("clicked", () => this._onRestartPressed()); buttonRow.add_child(this.restartBtn); @@ -226,6 +242,7 @@ class MyDesklet extends Desklet.Desklet { }); this.stopBtn = new St.Button({ child: stopIcon, style_class: "timer-input-button", style: this.buttonStyle }); this.stopBtn.connect("clicked", () => this._onStopPressed()); + if (this._totalSeconds === 0) this.stopBtn.hide(); buttonRow.add_child(this.stopBtn); centerContent.add_child(new St.Bin({ child: buttonRow, x_align: St.Align.MIDDLE })); @@ -236,12 +253,24 @@ class MyDesklet extends Desklet.Desklet { style: this.addTimeButtonStyle, }); addTimeBtn.connect("clicked", () => { + const wasZero = this._totalSeconds === 0; + if (!this.isRunning && this._remainingMs === 0) { + this._totalSeconds = 0; + } this._remainingMs += 60 * 1000; this._totalSeconds += 60; if (this.isRunning) { this._endTime += 60 * 1000; } this._updateTimerVisuals(); + if (wasZero) { + this.newTimerBtn.hide(); + this.playBtn.show(); + this.stopBtn.show(); + } else if (!this.isRunning && this._remainingMs > 0) { + this.playBtn.show(); + this.restartBtn.hide(); + } }); centerContent.add_child(new St.Bin({ child: addTimeBtn, x_align: St.Align.MIDDLE })); @@ -265,8 +294,9 @@ class MyDesklet extends Desklet.Desklet { } this.isRunning = false; this._totalSeconds = 0; + this._remainingMs = 0; this._inputDigits = ""; - this._setupInputLayout(); + this._setupTimerUI(); } _onPlayPressed() { From c16d94675a3a83eee998bf28b694db6eb6923d2c Mon Sep 17 00:00:00 2001 From: Rico Date: Mon, 2 Feb 2026 22:33:41 +0100 Subject: [PATCH 12/23] align input layout --- timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 18262ab98..2aa1fa275 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -73,6 +73,7 @@ class MyDesklet extends Desklet.Desklet { this.mainContainer.destroy_all_children(); const box = new St.BoxLayout({ vertical: true }); + box.style = "width: " + this.default_size * this.scaleSize + "px;"; const labelRow = new St.BoxLayout(); const labelStyle = `font-size: ${1.5 * this.scaleSize}em; color: ${this.labelColor};`; @@ -83,6 +84,8 @@ class MyDesklet extends Desklet.Desklet { // Input buttons 1-9 for (let i = 0; i < 3; i++) { const row = new St.BoxLayout(); + row.add_child(new St.Bin({ x_expand: true })); + for (let j = 1; j <= 3; j++) { const num = i * 3 + j; const button = new St.Button({ @@ -93,10 +96,12 @@ class MyDesklet extends Desklet.Desklet { button.connect("clicked", () => this._onDigitPressed(num)); row.add_child(button); } + row.add_child(new St.Bin({ x_expand: true })); box.add_child(row); } const lastRow = new St.BoxLayout(); + lastRow.add_child(new St.Bin({ x_expand: true })); const zeroBtn = new St.Button({ label: "0", style_class: "timer-input-button", @@ -130,6 +135,7 @@ class MyDesklet extends Desklet.Desklet { }); editBtn.connect("clicked", () => this._onEditPressed()); lastRow.add_child(editBtn); + lastRow.add_child(new St.Bin({ x_expand: true })); box.add_child(lastRow); From e011f1e19d48ca1880dfd42191bf3c04b91c34c4 Mon Sep 17 00:00:00 2001 From: Rico Date: Mon, 2 Feb 2026 23:12:41 +0100 Subject: [PATCH 13/23] time label caching, animation speed --- .../files/timer@KopfdesDaemons/desklet.js | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 2aa1fa275..5ae2258c6 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -6,6 +6,8 @@ const Clutter = imports.gi.Clutter; const Mainloop = imports.mainloop; const Settings = imports.ui.settings; const Util = imports.misc.util; +const Gio = imports.gi.Gio; +const GLib = imports.gi.GLib; class MyDesklet extends Desklet.Desklet { constructor(metadata, deskletId) { @@ -17,6 +19,7 @@ class MyDesklet extends Desklet.Desklet { this._timeout = null; this._totalSeconds = 0; this._remainingMs = 0; + this._lastTimeText = ""; // Use default values if settings are not yet set this.labelColor = "rgb(51, 209, 122)"; @@ -194,6 +197,7 @@ class MyDesklet extends Desklet.Desklet { text: "00h 00m 00s", style: `font-size: ${1.5 * this.scaleSize}em; color: ${this.labelColor}; margin-top: ${0.5 * this.scaleSize}em;`, }); + this._lastTimeText = ""; centerContent.add_child(new St.Bin({ child: this.timeLabel, x_align: St.Align.MIDDLE })); const buttonRow = new St.BoxLayout({ style: "spacing: 10px;" }); @@ -326,7 +330,7 @@ class MyDesklet extends Desklet.Desklet { this._updateTimerVisuals(); if (this._timeout) Mainloop.source_remove(this._timeout); - this._timeout = Mainloop.timeout_add(10, this._updateTimer.bind(this)); + this._timeout = Mainloop.timeout_add(20, this._updateTimer.bind(this)); } _updateTimer() { @@ -356,7 +360,10 @@ class MyDesklet extends Desklet.Desklet { const s = totalSecondsLeft % 60; const text = `${h.toString().padStart(2, "0")}h ${m.toString().padStart(2, "0")}m ${s.toString().padStart(2, "0")}s`; - if (this.timeLabel) this.timeLabel.set_text(text); + if (this.timeLabel && text !== this._lastTimeText) { + this.timeLabel.set_text(text); + this._lastTimeText = text; + } if (this._totalSeconds > 0) { this.indicatorLength = (this._remainingMs / (this._totalSeconds * 1000)) * 100; @@ -417,7 +424,15 @@ class MyDesklet extends Desklet.Desklet { _playSound() { if (this.soundFile && this.soundFile !== "none") { const path = "/usr/share/sounds/freedesktop/stereo/" + this.soundFile; - Util.spawnCommandLine("paplay " + path); + try { + let proc = new Gio.Subprocess({ + argv: ["paplay", path], + flags: Gio.SubprocessFlags.NONE, + }); + proc.init(null); + } catch (e) { + global.logError("timer@KopfdesDaemons: Error playing sound: " + e.message); + } } } From ee7ce53b31ee3fa14e2a16e2fb38109ce100a749 Mon Sep 17 00:00:00 2001 From: Rico Date: Fri, 6 Feb 2026 15:56:31 +0100 Subject: [PATCH 14/23] custom sound file setting --- .../files/timer@KopfdesDaemons/desklet.js | 37 +++++++++++++++++-- .../files/timer@KopfdesDaemons/po/de.po | 10 ++++- .../po/timer@KopfdesDaemons.pot | 10 ++++- .../timer@KopfdesDaemons/settings-schema.json | 15 +++++++- 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 5ae2258c6..4c84b7ca7 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -20,6 +20,7 @@ class MyDesklet extends Desklet.Desklet { this._totalSeconds = 0; this._remainingMs = 0; this._lastTimeText = ""; + this._soundProc = null; // Use default values if settings are not yet set this.labelColor = "rgb(51, 209, 122)"; @@ -31,6 +32,8 @@ class MyDesklet extends Desklet.Desklet { this.innerCircleColor = "rgba(255, 255, 255, 0.3)"; this.hideDecorations = false; this.soundFile = "complete.oga"; + this.useCustomSound = false; + this.customSoundFile = ""; const settings = new Settings.DeskletSettings(this, metadata["uuid"], deskletId); settings.bindProperty(Settings.BindingDirection.IN, "label-color", "labelColor", this._onSettingsChanged.bind(this)); @@ -42,6 +45,8 @@ class MyDesklet extends Desklet.Desklet { settings.bindProperty(Settings.BindingDirection.IN, "fill-inner-circle", "fillInnerCircle", this._onSettingsChanged.bind(this)); settings.bindProperty(Settings.BindingDirection.IN, "hideDecorations", "hideDecorations", this.updateDecoration.bind(this)); settings.bindProperty(Settings.BindingDirection.IN, "sound-file", "soundFile", null); + settings.bindProperty(Settings.BindingDirection.IN, "use-custom-sound", "useCustomSound", null); + settings.bindProperty(Settings.BindingDirection.IN, "custom-sound-file", "customSoundFile", null); this.setHeader("Timer"); this._inputDigits = ""; @@ -302,6 +307,8 @@ class MyDesklet extends Desklet.Desklet { Mainloop.source_remove(this._timeout); this._timeout = null; } + this._stopRunningSound(); + this.isRunning = false; this._totalSeconds = 0; this._remainingMs = 0; @@ -318,6 +325,7 @@ class MyDesklet extends Desklet.Desklet { } _onRestartPressed() { + this._stopRunningSound(); this._remainingMs = this._totalSeconds * 1000; this.restartBtn.hide(); this.pauseBtn.show(); @@ -353,6 +361,13 @@ class MyDesklet extends Desklet.Desklet { return true; } + _stopRunningSound() { + if (this._soundProc) { + this._soundProc.force_exit(); + this._soundProc = null; + } + } + _updateTimerVisuals() { const totalSecondsLeft = Math.ceil(this._remainingMs / 1000); const h = Math.floor(totalSecondsLeft / 3600); @@ -422,14 +437,27 @@ class MyDesklet extends Desklet.Desklet { } _playSound() { - if (this.soundFile && this.soundFile !== "none") { - const path = "/usr/share/sounds/freedesktop/stereo/" + this.soundFile; + let path = null; + if (this.useCustomSound) { + if (this.customSoundFile) { + path = this.customSoundFile; + if (path.startsWith("file://")) { + path = decodeURIComponent(path.replace("file://", "")); + } + } + } else if (this.soundFile && this.soundFile !== "none") { + path = "/usr/share/sounds/freedesktop/stereo/" + this.soundFile; + } + + if (path) { try { - let proc = new Gio.Subprocess({ + this._stopRunningSound(); + + this._soundProc = new Gio.Subprocess({ argv: ["paplay", path], flags: Gio.SubprocessFlags.NONE, }); - proc.init(null); + this._soundProc.init(null); } catch (e) { global.logError("timer@KopfdesDaemons: Error playing sound: " + e.message); } @@ -454,6 +482,7 @@ class MyDesklet extends Desklet.Desklet { Mainloop.source_remove(this._timeout); this._timeout = null; } + this._stopRunningSound(); } } diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po index 7b251c5f7..15ee28e15 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: timer@KopfdesDaemons 1.0.0\n" "Report-Msgid-Bugs-To: https://github.com/linuxmint/cinnamon-spices-desklets/" "issues\n" -"POT-Creation-Date: 2026-02-02 20:49+0100\n" +"POT-Creation-Date: 2026-02-06 15:41+0100\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -54,6 +54,14 @@ msgstr "Service login" msgid "Service logout" msgstr "Service logout" +#. settings-schema.json->use-custom-sound->description +msgid "Use custom sound" +msgstr "Benutze benutzerdefinierten Sound" + +#. settings-schema.json->custom-sound-file->description +msgid "Custom sound file" +msgstr "Benutzerdefinierte Audiodatei" + #. settings-schema.json->head1->description msgid "Style" msgstr "Stil" diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot index ba391964f..2e3ac508f 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: timer@KopfdesDaemons 1.0.0\n" "Report-Msgid-Bugs-To: https://github.com/linuxmint/cinnamon-spices-desklets/" "issues\n" -"POT-Creation-Date: 2026-02-02 20:49+0100\n" +"POT-Creation-Date: 2026-02-06 15:41+0100\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -53,6 +53,14 @@ msgstr "" msgid "Service logout" msgstr "" +#. settings-schema.json->use-custom-sound->description +msgid "Use custom sound" +msgstr "" + +#. settings-schema.json->custom-sound-file->description +msgid "Custom sound file" +msgstr "" + #. settings-schema.json->head1->description msgid "Style" msgstr "" diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json index 2e9ff603e..da81d62b3 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json @@ -13,7 +13,20 @@ "Complete": "complete.oga", "Service login": "service-login.oga", "Service logout": "service-logout.oga" - } + }, + "dependency": "!use-custom-sound" + }, + "use-custom-sound": { + "type": "checkbox", + "default": false, + "description": "Use custom sound" + }, + "custom-sound-file": { + "type": "filechooser", + "default": "", + "description": "Custom sound file", + "filters": ["*.ogg", "*.oga", "*.wav", "*.mp3"], + "dependency": "use-custom-sound" }, "head1": { "type": "header", From 5ae308e67967751d0af6fd3c1034477b4e198103 Mon Sep 17 00:00:00 2001 From: Rico Date: Fri, 6 Feb 2026 17:10:12 +0100 Subject: [PATCH 15/23] notification + timer name setting --- .../files/timer@KopfdesDaemons/desklet.js | 47 +++++++++++++++++- .../files/timer@KopfdesDaemons/po/de.po | 20 +++++++- .../po/timer@KopfdesDaemons.pot | 20 +++++++- .../timer@KopfdesDaemons/settings-schema.json | 16 +++++- timer@KopfdesDaemons/screenshot.png | Bin 41243 -> 60432 bytes 5 files changed, 97 insertions(+), 6 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 4c84b7ca7..0a42c47e0 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -8,6 +8,16 @@ const Settings = imports.ui.settings; const Util = imports.misc.util; const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; +const Main = imports.ui.main; +const MessageTray = imports.ui.messageTray; +const Gettext = imports.gettext; + +const UUID = "timer@KopfdesDaemons"; +Gettext.bindtextdomain(UUID, GLib.get_home_dir() + "/.local/share/locale"); + +function _(str) { + return Gettext.dgettext(UUID, str); +} class MyDesklet extends Desklet.Desklet { constructor(metadata, deskletId) { @@ -34,6 +44,8 @@ class MyDesklet extends Desklet.Desklet { this.soundFile = "complete.oga"; this.useCustomSound = false; this.customSoundFile = ""; + this.timerName = ""; + this.showNotification = false; const settings = new Settings.DeskletSettings(this, metadata["uuid"], deskletId); settings.bindProperty(Settings.BindingDirection.IN, "label-color", "labelColor", this._onSettingsChanged.bind(this)); @@ -47,6 +59,8 @@ class MyDesklet extends Desklet.Desklet { settings.bindProperty(Settings.BindingDirection.IN, "sound-file", "soundFile", null); settings.bindProperty(Settings.BindingDirection.IN, "use-custom-sound", "useCustomSound", null); settings.bindProperty(Settings.BindingDirection.IN, "custom-sound-file", "customSoundFile", null); + settings.bindProperty(Settings.BindingDirection.IN, "timer-name", "timerName", this._onSettingsChanged.bind(this)); + settings.bindProperty(Settings.BindingDirection.IN, "show-notification", "showNotification", null); this.setHeader("Timer"); this._inputDigits = ""; @@ -198,9 +212,17 @@ class MyDesklet extends Desklet.Desklet { const centerContent = new St.BoxLayout({ vertical: true }); this.mainContainer.add_child(centerContent); + if (this.timerName) { + const titleLabel = new St.Label({ + text: this.timerName, + style: `font-size: ${0.9 * this.scaleSize}em; background-color: rgba(0,0,0,0.5); padding: 2px 6px; border-radius: 4px;`, + }); + centerContent.add_child(new St.Bin({ child: titleLabel, x_align: St.Align.MIDDLE })); + } + this.timeLabel = new St.Label({ text: "00h 00m 00s", - style: `font-size: ${1.5 * this.scaleSize}em; color: ${this.labelColor}; margin-top: ${0.5 * this.scaleSize}em;`, + style: `font-size: ${1.5 * this.scaleSize}em; color: ${this.labelColor}; margin-top: ${!this.timerName ? 0.5 * this.scaleSize : 0}em;`, }); this._lastTimeText = ""; centerContent.add_child(new St.Bin({ child: this.timeLabel, x_align: St.Align.MIDDLE })); @@ -354,6 +376,9 @@ class MyDesklet extends Desklet.Desklet { this.pauseBtn.hide(); this.restartBtn.show(); this._playSound(); + if (this.showNotification) { + this._sendNotification(); + } return false; } @@ -368,6 +393,23 @@ class MyDesklet extends Desklet.Desklet { } } + _sendNotification() { + const title = this.timerName || "Timer"; + const message = _("Timer expired!"); + if (!this._notificationSource) { + this._notificationSource = new MessageTray.SystemNotificationSource(); + } + Main.messageTray.add(this._notificationSource); + const icon = new St.Icon({ + icon_name: "alarm-symbolic", + icon_type: St.IconType.SYMBOLIC, + }); + const notification = new MessageTray.Notification(this._notificationSource, title, message, { icon: icon }); + notification.setTransient(false); + notification.connect("destroy", () => this._stopRunningSound()); + this._notificationSource.notify(notification); + } + _updateTimerVisuals() { const totalSecondsLeft = Math.ceil(this._remainingMs / 1000); const h = Math.floor(totalSecondsLeft / 3600); @@ -483,6 +525,9 @@ class MyDesklet extends Desklet.Desklet { this._timeout = null; } this._stopRunningSound(); + if (this._notificationSource) { + this._notificationSource.destroy(); + } } } diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po index 15ee28e15..e35d8f26f 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/de.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: timer@KopfdesDaemons 1.0.0\n" "Report-Msgid-Bugs-To: https://github.com/linuxmint/cinnamon-spices-desklets/" "issues\n" -"POT-Creation-Date: 2026-02-06 15:41+0100\n" +"POT-Creation-Date: 2026-02-06 16:17+0100\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -18,6 +18,10 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.4.2\n" +#. desklet.js:389 +msgid "Timer expired!" +msgstr "Timer abgelaufen!" + #. metadata.json->name msgid "Timer" msgstr "Timer" @@ -63,6 +67,18 @@ msgid "Custom sound file" msgstr "Benutzerdefinierte Audiodatei" #. settings-schema.json->head1->description +msgid "General" +msgstr "Allgemein" + +#. settings-schema.json->timer-name->description +msgid "Timer name" +msgstr "Timer" + +#. settings-schema.json->show-notification->description +msgid "Show notification when timer expires" +msgstr "Benachrichtigung anzeigen, wenn der Timer abläuft" + +#. settings-schema.json->head2->description msgid "Style" msgstr "Stil" @@ -78,7 +94,7 @@ msgstr "Desklet Größe" msgid "Hide decorations" msgstr "Dekorationen verstecken" -#. settings-schema.json->head2->description +#. settings-schema.json->head3->description msgid "Circle" msgstr "Kreis" diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot index 2e3ac508f..c89c7d9c0 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/po/timer@KopfdesDaemons.pot @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: timer@KopfdesDaemons 1.0.0\n" "Report-Msgid-Bugs-To: https://github.com/linuxmint/cinnamon-spices-desklets/" "issues\n" -"POT-Creation-Date: 2026-02-06 15:41+0100\n" +"POT-Creation-Date: 2026-02-06 16:17+0100\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -17,6 +17,10 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +#. desklet.js:389 +msgid "Timer expired!" +msgstr "" + #. metadata.json->name msgid "Timer" msgstr "" @@ -62,6 +66,18 @@ msgid "Custom sound file" msgstr "" #. settings-schema.json->head1->description +msgid "General" +msgstr "" + +#. settings-schema.json->timer-name->description +msgid "Timer name" +msgstr "" + +#. settings-schema.json->show-notification->description +msgid "Show notification when timer expires" +msgstr "" + +#. settings-schema.json->head2->description msgid "Style" msgstr "" @@ -77,7 +93,7 @@ msgstr "" msgid "Hide decorations" msgstr "" -#. settings-schema.json->head2->description +#. settings-schema.json->head3->description msgid "Circle" msgstr "" diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json index da81d62b3..54e504351 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json @@ -29,6 +29,20 @@ "dependency": "use-custom-sound" }, "head1": { + "type": "header", + "description": "General" + }, + "timer-name": { + "type": "entry", + "default": "", + "description": "Timer name" + }, + "show-notification": { + "type": "checkbox", + "description": "Show notification when timer expires", + "default": true + }, + "head2": { "type": "header", "description": "Style" }, @@ -50,7 +64,7 @@ "description": "Hide decorations", "default": false }, - "head2": { + "head3": { "type": "header", "description": "Circle" }, diff --git a/timer@KopfdesDaemons/screenshot.png b/timer@KopfdesDaemons/screenshot.png index 126b248d2459024930b76e60b772bc6795a441b0..9f187cdbf0483b36d36500602805939fbfc1d15b 100644 GIT binary patch literal 60432 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 z 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 Date: Fri, 6 Feb 2026 20:59:07 +0100 Subject: [PATCH 16/23] stop sound when "Add Time" button is clicked --- .../files/timer@KopfdesDaemons/desklet.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 0a42c47e0..b4704a0b0 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -290,6 +290,7 @@ class MyDesklet extends Desklet.Desklet { style: this.addTimeButtonStyle, }); addTimeBtn.connect("clicked", () => { + this._stopSound(); const wasZero = this._totalSeconds === 0; if (!this.isRunning && this._remainingMs === 0) { this._totalSeconds = 0; @@ -329,7 +330,7 @@ class MyDesklet extends Desklet.Desklet { Mainloop.source_remove(this._timeout); this._timeout = null; } - this._stopRunningSound(); + this._stopSound(); this.isRunning = false; this._totalSeconds = 0; @@ -347,7 +348,7 @@ class MyDesklet extends Desklet.Desklet { } _onRestartPressed() { - this._stopRunningSound(); + this._stopSound(); this._remainingMs = this._totalSeconds * 1000; this.restartBtn.hide(); this.pauseBtn.show(); @@ -386,7 +387,7 @@ class MyDesklet extends Desklet.Desklet { return true; } - _stopRunningSound() { + _stopSound() { if (this._soundProc) { this._soundProc.force_exit(); this._soundProc = null; @@ -406,7 +407,7 @@ class MyDesklet extends Desklet.Desklet { }); const notification = new MessageTray.Notification(this._notificationSource, title, message, { icon: icon }); notification.setTransient(false); - notification.connect("destroy", () => this._stopRunningSound()); + notification.connect("destroy", () => this._stopSound()); this._notificationSource.notify(notification); } @@ -493,7 +494,7 @@ class MyDesklet extends Desklet.Desklet { if (path) { try { - this._stopRunningSound(); + this._stopSound(); this._soundProc = new Gio.Subprocess({ argv: ["paplay", path], @@ -524,7 +525,7 @@ class MyDesklet extends Desklet.Desklet { Mainloop.source_remove(this._timeout); this._timeout = null; } - this._stopRunningSound(); + this._stopSound(); if (this._notificationSource) { this._notificationSource.destroy(); } From be5fce7c9fe4477305a81ef31ea1e28314b601d4 Mon Sep 17 00:00:00 2001 From: Rico Date: Sat, 7 Feb 2026 01:40:41 +0100 Subject: [PATCH 17/23] use St.DrawingArea, remove clutter --- .../files/timer@KopfdesDaemons/CHANGELOG.md | 5 + .../files/timer@KopfdesDaemons/desklet.js | 118 ++++++++---------- 2 files changed, 59 insertions(+), 64 deletions(-) create mode 100644 timer@KopfdesDaemons/files/timer@KopfdesDaemons/CHANGELOG.md diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/CHANGELOG.md b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/CHANGELOG.md new file mode 100644 index 000000000..0b673d1ff --- /dev/null +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/CHANGELOG.md @@ -0,0 +1,5 @@ +#changelog + +## [1.0.0] - 07.02.2026 + +- Initial release diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index b4704a0b0..b35fd2d55 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -1,8 +1,6 @@ const Desklet = imports.ui.desklet; const St = imports.gi.St; -const Cogl = imports.gi.Cogl; const Cairo = imports.cairo; -const Clutter = imports.gi.Clutter; const Mainloop = imports.mainloop; const Settings = imports.ui.settings; const Util = imports.misc.util; @@ -65,10 +63,6 @@ class MyDesklet extends Desklet.Desklet { this.setHeader("Timer"); this._inputDigits = ""; - this.mainContainer = new St.Widget({ - layout_manager: new Clutter.BinLayout(), - }); - this.setContent(this.mainContainer); this._setButtonStyles(); this.updateDecoration(); this._setupTimerUI(); @@ -92,7 +86,6 @@ class MyDesklet extends Desklet.Desklet { _setupInputLayout() { this._isInputView = true; - this.mainContainer.destroy_all_children(); const box = new St.BoxLayout({ vertical: true }); box.style = "width: " + this.default_size * this.scaleSize + "px;"; @@ -161,7 +154,7 @@ class MyDesklet extends Desklet.Desklet { box.add_child(lastRow); - this.mainContainer.add_child(box); + this.setContent(box); } _onDigitPressed(num) { @@ -198,19 +191,26 @@ class MyDesklet extends Desklet.Desklet { _setupTimerUI() { this._isInputView = false; - this.mainContainer.destroy_all_children(); const absoluteSize = this.default_size * this.scaleSize; - this.circleActor = new Clutter.Actor({ + const container = new St.Widget({ width: absoluteSize, height: absoluteSize }); + + this.circleDrawingArea = new St.DrawingArea({ width: absoluteSize, height: absoluteSize }); + this.circleDrawingArea.set_pivot_point(0.5, 0.5); + this.circleDrawingArea.connect("repaint", this._onRepaint.bind(this)); + container.add_child(this.circleDrawingArea); + this.circleDrawingArea.queue_repaint(); + + const centerContent = new St.BoxLayout({ vertical: true }); + const bin = new St.Bin({ width: absoluteSize, height: absoluteSize, + child: centerContent, + x_align: St.Align.MIDDLE, + y_align: St.Align.MIDDLE, }); - this.mainContainer.add_child(this.circleActor); - this._drawCircle(); - - const centerContent = new St.BoxLayout({ vertical: true }); - this.mainContainer.add_child(centerContent); + container.add_child(bin); if (this.timerName) { const titleLabel = new St.Label({ @@ -313,6 +313,8 @@ class MyDesklet extends Desklet.Desklet { centerContent.add_child(new St.Bin({ child: addTimeBtn, x_align: St.Align.MIDDLE })); this._updateTimerVisuals(); + + this.setContent(container); } _onPausePressed() { @@ -429,54 +431,45 @@ class MyDesklet extends Desklet.Desklet { this.indicatorLength = 0; } - if (this.circleActor && this.circleActor.get_content()) { - this.circleActor.get_content().invalidate(); + if (this.circleDrawingArea) { + this.circleDrawingArea.queue_repaint(); } } - _drawCircle() { - const canvas = new Clutter.Canvas(); - const absoluteSize = this.default_size * this.scaleSize; - canvas.set_size(absoluteSize * global.ui_scale, absoluteSize * global.ui_scale); - - canvas.connect("draw", (canvas, cr, width, height) => { - cr.save(); - cr.setOperator(Cairo.Operator.CLEAR); - cr.paint(); - cr.restore(); - cr.setOperator(Cairo.Operator.OVER); - cr.scale(width, height); - cr.translate(0.5, 0.5); - - // Draw the inner circle - if (this.fillInnerCircle) { - const rgbaInner = this._rgbToRgba(this.innerCircleColor); - cr.setSourceRGBA(rgbaInner[0], rgbaInner[1], rgbaInner[2], rgbaInner[3]); - cr.arc(0, 0, 0.4 - this.circleWidth / 2, 0, Math.PI * 2); - cr.fill(); - } - - // Draw the background circle - const rgbaCircle = this._rgbToRgba(this.circleColor); - cr.setSourceRGBA(rgbaCircle[0], rgbaCircle[1], rgbaCircle[2], rgbaCircle[3]); - cr.setLineWidth(this.circleWidth); - cr.arc(0, 0, 0.4, 0, Math.PI * 2); - cr.stroke(); - - // Draw the indicator arc - const rgbaIndicator = this._rgbToRgba(this.indicatorColor); - cr.setSourceRGBA(rgbaIndicator[0], rgbaIndicator[1], rgbaIndicator[2], rgbaIndicator[3]); - cr.setLineWidth(this.circleWidth); - const arcEnd = (this.indicatorLength * (Math.PI * 2)) / 100 - Math.PI * 0.5; - cr.arc(0, 0, 0.4, 0 - Math.PI * 0.5, arcEnd); - cr.stroke(); - - return true; - }); + _onRepaint(area) { + const cr = area.get_context(); + const [width, height] = area.get_surface_size(); + + cr.save(); + cr.setOperator(Cairo.Operator.CLEAR); + cr.paint(); + cr.restore(); + cr.setOperator(Cairo.Operator.OVER); + cr.scale(width, height); + cr.translate(0.5, 0.5); + + // Draw the inner circle + if (this.fillInnerCircle) { + const rgbaInner = this._rgbToRgba(this.innerCircleColor); + cr.setSourceRGBA(rgbaInner[0], rgbaInner[1], rgbaInner[2], rgbaInner[3]); + cr.arc(0, 0, 0.4 - this.circleWidth / 2, 0, Math.PI * 2); + cr.fill(); + } - canvas.invalidate(); - this.circleActor.set_content(canvas); - this.circleActor.set_pivot_point(0.5, 0.5); + // Draw the background circle + const rgbaCircle = this._rgbToRgba(this.circleColor); + cr.setSourceRGBA(rgbaCircle[0], rgbaCircle[1], rgbaCircle[2], rgbaCircle[3]); + cr.setLineWidth(this.circleWidth); + cr.arc(0, 0, 0.4, 0, Math.PI * 2); + cr.stroke(); + + // Draw the indicator arc + const rgbaIndicator = this._rgbToRgba(this.indicatorColor); + cr.setSourceRGBA(rgbaIndicator[0], rgbaIndicator[1], rgbaIndicator[2], rgbaIndicator[3]); + cr.setLineWidth(this.circleWidth); + const arcEnd = (this.indicatorLength * (Math.PI * 2)) / 100 - Math.PI * 0.5; + cr.arc(0, 0, 0.4, 0 - Math.PI * 0.5, arcEnd); + cr.stroke(); } _playSound() { @@ -511,11 +504,8 @@ class MyDesklet extends Desklet.Desklet { _rgbToRgba(colorString) { const match = colorString.match(/\((.*?)\)/); if (match && match[1]) { - const c = match[1].split(","); - if (c.length >= 3) { - const a = c.length >= 4 ? parseFloat(c[3]) : 1; - return [parseInt(c[0]) / 255, parseInt(c[1]) / 255, parseInt(c[2]) / 255, a]; - } + const [r, g, b, a = 1] = match[1].split(",").map(parseFloat); + return [r / 255, g / 255, b / 255, a]; } return [0.3, 0.8, 0.5, 1]; // Default color if parsing fails } From 46e02de1d2b5360b2d4e525c6c0c59bf4062bc40 Mon Sep 17 00:00:00 2001 From: Rico Date: Sat, 7 Feb 2026 02:01:11 +0100 Subject: [PATCH 18/23] remove notification on button click --- .../files/timer@KopfdesDaemons/desklet.js | 120 ++++++++---------- 1 file changed, 55 insertions(+), 65 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index b35fd2d55..e9a5658f9 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -29,6 +29,7 @@ class MyDesklet extends Desklet.Desklet { this._remainingMs = 0; this._lastTimeText = ""; this._soundProc = null; + this._currentNotification = null; // Use default values if settings are not yet set this.labelColor = "rgb(51, 209, 122)"; @@ -117,11 +118,7 @@ class MyDesklet extends Desklet.Desklet { const lastRow = new St.BoxLayout(); lastRow.add_child(new St.Bin({ x_expand: true })); - const zeroBtn = new St.Button({ - label: "0", - style_class: "timer-input-button", - style: this.buttonStyle, - }); + const zeroBtn = new St.Button({ label: "0", style_class: "timer-input-button", style: this.buttonStyle }); zeroBtn.connect("clicked", () => this._onDigitPressed(0)); lastRow.add_child(zeroBtn); @@ -130,24 +127,12 @@ class MyDesklet extends Desklet.Desklet { icon_type: St.IconType.SYMBOLIC, icon_size: 16 * this.scaleSize, }); - const startBtn = new St.Button({ - child: playIcon, - style_class: "timer-input-button", - style: this.buttonStyle, - }); + const startBtn = new St.Button({ child: playIcon, style_class: "timer-input-button", style: this.buttonStyle }); lastRow.add_child(startBtn); startBtn.connect("clicked", () => this._onStartPressed()); - const editIcon = new St.Icon({ - icon_name: "edit-clear-symbolic", - icon_type: St.IconType.SYMBOLIC, - icon_size: 16 * this.scaleSize, - }); - const editBtn = new St.Button({ - child: editIcon, - style_class: "timer-input-button", - style: this.buttonStyle, - }); + const editIcon = new St.Icon({ icon_name: "edit-clear-symbolic", icon_type: St.IconType.SYMBOLIC, icon_size: 16 * this.scaleSize }); + const editBtn = new St.Button({ child: editIcon, style_class: "timer-input-button", style: this.buttonStyle }); editBtn.connect("clicked", () => this._onEditPressed()); lastRow.add_child(editBtn); lastRow.add_child(new St.Bin({ x_expand: true })); @@ -229,19 +214,17 @@ class MyDesklet extends Desklet.Desklet { const buttonRow = new St.BoxLayout({ style: "spacing: 10px;" }); - const newTimerIcon = new St.Icon({ - icon_name: "list-add-symbolic", - icon_type: St.IconType.SYMBOLIC, - icon_size: 16 * this.scaleSize, - }); + const newTimerIcon = new St.Icon({ icon_name: "list-add-symbolic", icon_type: St.IconType.SYMBOLIC, icon_size: 16 * this.scaleSize }); this.newTimerBtn = new St.Button({ child: newTimerIcon, style_class: "timer-input-button", style: this.buttonStyle }); this.newTimerBtn.connect("clicked", () => { + this._removeNotification(); this._inputDigits = ""; this._setupInputLayout(); }); if (this._totalSeconds > 0) this.newTimerBtn.hide(); buttonRow.add_child(this.newTimerBtn); + // Play button const playIcon = new St.Icon({ icon_name: "media-playback-start-symbolic", icon_type: St.IconType.SYMBOLIC, @@ -252,11 +235,8 @@ class MyDesklet extends Desklet.Desklet { this.playBtn.connect("clicked", () => this._onPlayPressed()); buttonRow.add_child(this.playBtn); - const refreshIcon = new St.Icon({ - icon_name: "view-refresh-symbolic", - icon_type: St.IconType.SYMBOLIC, - icon_size: 16 * this.scaleSize, - }); + // Restart button + const refreshIcon = new St.Icon({ icon_name: "view-refresh-symbolic", icon_type: St.IconType.SYMBOLIC, icon_size: 16 * this.scaleSize }); this.restartBtn = new St.Button({ child: refreshIcon, style_class: "timer-input-button", style: this.buttonStyle }); if (this._totalSeconds === 0 || this.isRunning || this._remainingMs > 0) this.restartBtn.hide(); this.restartBtn.connect("clicked", () => this._onRestartPressed()); @@ -272,11 +252,8 @@ class MyDesklet extends Desklet.Desklet { if (!this.isRunning) this.pauseBtn.hide(); buttonRow.add_child(this.pauseBtn); - const stopIcon = new St.Icon({ - icon_name: "media-playback-stop-symbolic", - icon_type: St.IconType.SYMBOLIC, - icon_size: 16 * this.scaleSize, - }); + // Stop button + const stopIcon = new St.Icon({ icon_name: "media-playback-stop-symbolic", icon_type: St.IconType.SYMBOLIC, icon_size: 16 * this.scaleSize }); this.stopBtn = new St.Button({ child: stopIcon, style_class: "timer-input-button", style: this.buttonStyle }); this.stopBtn.connect("clicked", () => this._onStopPressed()); if (this._totalSeconds === 0) this.stopBtn.hide(); @@ -284,32 +261,9 @@ class MyDesklet extends Desklet.Desklet { centerContent.add_child(new St.Bin({ child: buttonRow, x_align: St.Align.MIDDLE })); - const addTimeBtn = new St.Button({ - label: "+1", - style_class: "timer-add-time-button", - style: this.addTimeButtonStyle, - }); - addTimeBtn.connect("clicked", () => { - this._stopSound(); - const wasZero = this._totalSeconds === 0; - if (!this.isRunning && this._remainingMs === 0) { - this._totalSeconds = 0; - } - this._remainingMs += 60 * 1000; - this._totalSeconds += 60; - if (this.isRunning) { - this._endTime += 60 * 1000; - } - this._updateTimerVisuals(); - if (wasZero) { - this.newTimerBtn.hide(); - this.playBtn.show(); - this.stopBtn.show(); - } else if (!this.isRunning && this._remainingMs > 0) { - this.playBtn.show(); - this.restartBtn.hide(); - } - }); + // Add +1 minute button + const addTimeBtn = new St.Button({ label: "+1", style_class: "timer-add-time-button", style: this.addTimeButtonStyle }); + addTimeBtn.connect("clicked", () => this._onAddTimePressed()); centerContent.add_child(new St.Bin({ child: addTimeBtn, x_align: St.Align.MIDDLE })); this._updateTimerVisuals(); @@ -317,6 +271,29 @@ class MyDesklet extends Desklet.Desklet { this.setContent(container); } + _onAddTimePressed() { + this._stopSound(); + this._removeNotification(); + const wasZero = this._totalSeconds === 0; + if (!this.isRunning && this._remainingMs === 0) { + this._totalSeconds = 0; + } + this._remainingMs += 60 * 1000; + this._totalSeconds += 60; + if (this.isRunning) { + this._endTime += 60 * 1000; + } + this._updateTimerVisuals(); + if (wasZero) { + this.newTimerBtn.hide(); + this.playBtn.show(); + this.stopBtn.show(); + } else if (!this.isRunning && this._remainingMs > 0) { + this.playBtn.show(); + this.restartBtn.hide(); + } + } + _onPausePressed() { if (this._timeout) { Mainloop.source_remove(this._timeout); @@ -333,6 +310,7 @@ class MyDesklet extends Desklet.Desklet { this._timeout = null; } this._stopSound(); + this._removeNotification(); this.isRunning = false; this._totalSeconds = 0; @@ -343,6 +321,7 @@ class MyDesklet extends Desklet.Desklet { _onPlayPressed() { if (this._remainingMs > 0) { + this._removeNotification(); this._startTimer(); this.playBtn.hide(); this.pauseBtn.show(); @@ -351,6 +330,7 @@ class MyDesklet extends Desklet.Desklet { _onRestartPressed() { this._stopSound(); + this._removeNotification(); this._remainingMs = this._totalSeconds * 1000; this.restartBtn.hide(); this.pauseBtn.show(); @@ -407,10 +387,20 @@ class MyDesklet extends Desklet.Desklet { icon_name: "alarm-symbolic", icon_type: St.IconType.SYMBOLIC, }); - const notification = new MessageTray.Notification(this._notificationSource, title, message, { icon: icon }); - notification.setTransient(false); - notification.connect("destroy", () => this._stopSound()); - this._notificationSource.notify(notification); + this._currentNotification = new MessageTray.Notification(this._notificationSource, title, message, { icon: icon }); + this._currentNotification.setTransient(false); + this._currentNotification.connect("destroy", () => { + this._stopSound(); + this._currentNotification = null; + }); + this._notificationSource.notify(this._currentNotification); + } + + _removeNotification() { + if (this._currentNotification) { + this._currentNotification.destroy(); + this._currentNotification = null; + } } _updateTimerVisuals() { From 7e1f6f860c528dcb314b94cafedbab04fd178e5f Mon Sep 17 00:00:00 2001 From: Rico Date: Sat, 21 Feb 2026 09:58:07 +0100 Subject: [PATCH 19/23] add missing translation, init nullish properties, cleanup settings, set animation fps to 60 --- .../files/timer@KopfdesDaemons/desklet.js | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index e9a5658f9..46cf5d8da 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -20,6 +20,7 @@ function _(str) { class MyDesklet extends Desklet.Desklet { constructor(metadata, deskletId) { super(metadata, deskletId); + this.setHeader(_("Timer")); this.default_size = 200; this.isRunning = false; @@ -30,6 +31,9 @@ class MyDesklet extends Desklet.Desklet { this._lastTimeText = ""; this._soundProc = null; this._currentNotification = null; + this._inputDigits = ""; + this._notificationSource = null; + this._endTime = 0; // Use default values if settings are not yet set this.labelColor = "rgb(51, 209, 122)"; @@ -46,29 +50,42 @@ class MyDesklet extends Desklet.Desklet { this.timerName = ""; this.showNotification = false; - const settings = new Settings.DeskletSettings(this, metadata["uuid"], deskletId); - settings.bindProperty(Settings.BindingDirection.IN, "label-color", "labelColor", this._onSettingsChanged.bind(this)); - settings.bindProperty(Settings.BindingDirection.IN, "scale-size", "scaleSize", this._onSettingsChanged.bind(this)); - settings.bindProperty(Settings.BindingDirection.IN, "indicator-color", "indicatorColor", this._onSettingsChanged.bind(this)); - settings.bindProperty(Settings.BindingDirection.IN, "circle-width", "circleWidth", this._onSettingsChanged.bind(this)); - settings.bindProperty(Settings.BindingDirection.IN, "circle-color", "circleColor", this._onSettingsChanged.bind(this)); - settings.bindProperty(Settings.BindingDirection.IN, "inner-circle-color", "innerCircleColor", this._onSettingsChanged.bind(this)); - settings.bindProperty(Settings.BindingDirection.IN, "fill-inner-circle", "fillInnerCircle", this._onSettingsChanged.bind(this)); - settings.bindProperty(Settings.BindingDirection.IN, "hideDecorations", "hideDecorations", this.updateDecoration.bind(this)); - settings.bindProperty(Settings.BindingDirection.IN, "sound-file", "soundFile", null); - settings.bindProperty(Settings.BindingDirection.IN, "use-custom-sound", "useCustomSound", null); - settings.bindProperty(Settings.BindingDirection.IN, "custom-sound-file", "customSoundFile", null); - settings.bindProperty(Settings.BindingDirection.IN, "timer-name", "timerName", this._onSettingsChanged.bind(this)); - settings.bindProperty(Settings.BindingDirection.IN, "show-notification", "showNotification", null); - - this.setHeader("Timer"); - this._inputDigits = ""; + this.settings = new Settings.DeskletSettings(this, metadata["uuid"], deskletId); + this.settings.bindProperty(Settings.BindingDirection.IN, "label-color", "labelColor", this._onSettingsChanged.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "scale-size", "scaleSize", this._onSettingsChanged.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "indicator-color", "indicatorColor", this._onSettingsChanged.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "circle-width", "circleWidth", this._onSettingsChanged.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "circle-color", "circleColor", this._onSettingsChanged.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "inner-circle-color", "innerCircleColor", this._onSettingsChanged.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "fill-inner-circle", "fillInnerCircle", this._onSettingsChanged.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "hideDecorations", "hideDecorations", this.updateDecoration.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "sound-file", "soundFile", null); + this.settings.bindProperty(Settings.BindingDirection.IN, "use-custom-sound", "useCustomSound", null); + this.settings.bindProperty(Settings.BindingDirection.IN, "custom-sound-file", "customSoundFile", null); + this.settings.bindProperty(Settings.BindingDirection.IN, "timer-name", "timerName", this._onSettingsChanged.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "show-notification", "showNotification", null); + } + on_desklet_added_to_desktop() { this._setButtonStyles(); this.updateDecoration(); this._setupTimerUI(); } + on_desklet_removed() { + this.settings.finalize(); + this._stopSound(); + this._removeNotification(); + if (this._timeout) { + Mainloop.source_remove(this._timeout); + this._timeout = null; + } + this._stopSound(); + if (this._notificationSource) { + this._notificationSource.destroy(); + } + } + _onSettingsChanged() { this._setButtonStyles(); if (this._isInputView) this._setupInputLayout(); @@ -343,7 +360,8 @@ class MyDesklet extends Desklet.Desklet { this._updateTimerVisuals(); if (this._timeout) Mainloop.source_remove(this._timeout); - this._timeout = Mainloop.timeout_add(20, this._updateTimer.bind(this)); + const fps = 60; + this._timeout = Mainloop.timeout_add(1000 / fps, this._updateTimer.bind(this)); } _updateTimer() { @@ -377,12 +395,12 @@ class MyDesklet extends Desklet.Desklet { } _sendNotification() { - const title = this.timerName || "Timer"; + const title = this.timerName || _("Timer"); const message = _("Timer expired!"); if (!this._notificationSource) { this._notificationSource = new MessageTray.SystemNotificationSource(); + Main.messageTray.add(this._notificationSource); } - Main.messageTray.add(this._notificationSource); const icon = new St.Icon({ icon_name: "alarm-symbolic", icon_type: St.IconType.SYMBOLIC, @@ -499,17 +517,6 @@ class MyDesklet extends Desklet.Desklet { } return [0.3, 0.8, 0.5, 1]; // Default color if parsing fails } - - on_desklet_removed() { - if (this._timeout) { - Mainloop.source_remove(this._timeout); - this._timeout = null; - } - this._stopSound(); - if (this._notificationSource) { - this._notificationSource.destroy(); - } - } } function main(metadata, deskletId) { From 3cbc73aeccb22c0a924ac0387c9dd4f9920e1410 Mon Sep 17 00:00:00 2001 From: Rico Date: Sat, 21 Feb 2026 10:27:04 +0100 Subject: [PATCH 20/23] scale circle size with system font size --- .../files/timer@KopfdesDaemons/desklet.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 46cf5d8da..511dad1d1 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -22,7 +22,7 @@ class MyDesklet extends Desklet.Desklet { super(metadata, deskletId); this.setHeader(_("Timer")); - this.default_size = 200; + this.default_size = 14; this.isRunning = false; this._isInputView = false; this._timeout = null; @@ -106,7 +106,7 @@ class MyDesklet extends Desklet.Desklet { this._isInputView = true; const box = new St.BoxLayout({ vertical: true }); - box.style = "width: " + this.default_size * this.scaleSize + "px;"; + box.style = "width: " + this.default_size * this.scaleSize + "em;"; const labelRow = new St.BoxLayout(); const labelStyle = `font-size: ${1.5 * this.scaleSize}em; color: ${this.labelColor};`; @@ -196,9 +196,9 @@ class MyDesklet extends Desklet.Desklet { const absoluteSize = this.default_size * this.scaleSize; - const container = new St.Widget({ width: absoluteSize, height: absoluteSize }); + const container = new St.Widget({ style: `width: ${absoluteSize}em; height: ${absoluteSize}em;` }); - this.circleDrawingArea = new St.DrawingArea({ width: absoluteSize, height: absoluteSize }); + this.circleDrawingArea = new St.DrawingArea({ style: `width: ${absoluteSize}em; height: ${absoluteSize}em;` }); this.circleDrawingArea.set_pivot_point(0.5, 0.5); this.circleDrawingArea.connect("repaint", this._onRepaint.bind(this)); container.add_child(this.circleDrawingArea); @@ -206,8 +206,7 @@ class MyDesklet extends Desklet.Desklet { const centerContent = new St.BoxLayout({ vertical: true }); const bin = new St.Bin({ - width: absoluteSize, - height: absoluteSize, + style: `width: ${absoluteSize}em; height: ${absoluteSize}em;`, child: centerContent, x_align: St.Align.MIDDLE, y_align: St.Align.MIDDLE, From e107e9a887db4d98a7d28e49f7b1a7822b4e288b Mon Sep 17 00:00:00 2001 From: Rico Date: Sat, 21 Feb 2026 10:46:45 +0100 Subject: [PATCH 21/23] organize settings with tabs --- .../files/timer@KopfdesDaemons/desklet.js | 6 +-- .../timer@KopfdesDaemons/settings-schema.json | 38 ++++++++++++++++++- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 511dad1d1..16f4e74c8 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -43,7 +43,7 @@ class MyDesklet extends Desklet.Desklet { this.circleColor = "rgb(255, 255, 255)"; this.fillInnerCircle = true; this.innerCircleColor = "rgba(255, 255, 255, 0.3)"; - this.hideDecorations = false; + this.hideDecorations = true; this.soundFile = "complete.oga"; this.useCustomSound = false; this.customSoundFile = ""; @@ -58,7 +58,7 @@ class MyDesklet extends Desklet.Desklet { this.settings.bindProperty(Settings.BindingDirection.IN, "circle-color", "circleColor", this._onSettingsChanged.bind(this)); this.settings.bindProperty(Settings.BindingDirection.IN, "inner-circle-color", "innerCircleColor", this._onSettingsChanged.bind(this)); this.settings.bindProperty(Settings.BindingDirection.IN, "fill-inner-circle", "fillInnerCircle", this._onSettingsChanged.bind(this)); - this.settings.bindProperty(Settings.BindingDirection.IN, "hideDecorations", "hideDecorations", this.updateDecoration.bind(this)); + this.settings.bindProperty(Settings.BindingDirection.IN, "hide-decorations", "hideDecorations", this.updateDecoration.bind(this)); this.settings.bindProperty(Settings.BindingDirection.IN, "sound-file", "soundFile", null); this.settings.bindProperty(Settings.BindingDirection.IN, "use-custom-sound", "useCustomSound", null); this.settings.bindProperty(Settings.BindingDirection.IN, "custom-sound-file", "customSoundFile", null); @@ -502,7 +502,7 @@ class MyDesklet extends Desklet.Desklet { }); this._soundProc.init(null); } catch (e) { - global.logError("timer@KopfdesDaemons: Error playing sound: " + e.message); + global.logError(UUID + ": Error playing sound: " + e.message); } } } diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json index 54e504351..cb4032dfc 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json @@ -1,4 +1,38 @@ { + "layout": { + "type": "layout", + "pages": ["general-page", "style-page"], + "general-page": { + "type": "page", + "title": "General", + "sections": ["general-section", "sound-section"] + }, + "style-page": { + "type": "page", + "title": "Style", + "sections": ["style-section", "circle-section"] + }, + "general-section": { + "type": "section", + "title": "General", + "keys": ["scale-size", "timer-name", "show-notification", "hide-decorations"] + }, + "sound-section": { + "type": "section", + "title": "Sound", + "keys": ["sound-file", "use-custom-sound", "custom-sound-file"] + }, + "style-section": { + "type": "section", + "title": "Style", + "keys": ["label-color"] + }, + "circle-section": { + "type": "section", + "title": "Circle", + "keys": ["indicator-color", "circle-color", "circle-width", "fill-inner-circle", "inner-circle-color"] + } + }, "head0": { "type": "header", "description": "Sound" @@ -59,10 +93,10 @@ "step": 0.05, "description": "Desklet size" }, - "hideDecorations": { + "hide-decorations": { "type": "checkbox", "description": "Hide decorations", - "default": false + "default": true }, "head3": { "type": "header", From 2a23e170f96314ed632470e98736dcd87543de9a Mon Sep 17 00:00:00 2001 From: Rico Date: Sat, 21 Feb 2026 10:49:54 +0100 Subject: [PATCH 22/23] remove old settings header --- .../timer@KopfdesDaemons/settings-schema.json | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json index cb4032dfc..1d595776f 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/settings-schema.json @@ -33,10 +33,6 @@ "keys": ["indicator-color", "circle-color", "circle-width", "fill-inner-circle", "inner-circle-color"] } }, - "head0": { - "type": "header", - "description": "Sound" - }, "sound-file": { "type": "combobox", "default": "service-login.oga", @@ -62,10 +58,6 @@ "filters": ["*.ogg", "*.oga", "*.wav", "*.mp3"], "dependency": "use-custom-sound" }, - "head1": { - "type": "header", - "description": "General" - }, "timer-name": { "type": "entry", "default": "", @@ -76,10 +68,6 @@ "description": "Show notification when timer expires", "default": true }, - "head2": { - "type": "header", - "description": "Style" - }, "label-color": { "type": "colorchooser", "default": "rgb(51, 209, 122)", @@ -98,10 +86,6 @@ "description": "Hide decorations", "default": true }, - "head3": { - "type": "header", - "description": "Circle" - }, "indicator-color": { "type": "colorchooser", "default": "rgb(51, 209, 122)", From 294298e476560986b08313bdd9e447e70cc26425 Mon Sep 17 00:00:00 2001 From: Rico Date: Sun, 22 Feb 2026 18:41:37 +0100 Subject: [PATCH 23/23] fix freezing of the settings window when reloading the desklet --- .../files/timer@KopfdesDaemons/desklet.js | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js index 16f4e74c8..f16b45748 100644 --- a/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js +++ b/timer@KopfdesDaemons/files/timer@KopfdesDaemons/desklet.js @@ -22,8 +22,8 @@ class MyDesklet extends Desklet.Desklet { super(metadata, deskletId); this.setHeader(_("Timer")); - this.default_size = 14; - this.isRunning = false; + this._default_size = 14; + this._isRunning = false; this._isInputView = false; this._timeout = null; this._totalSeconds = 0; @@ -34,6 +34,7 @@ class MyDesklet extends Desklet.Desklet { this._inputDigits = ""; this._notificationSource = null; this._endTime = 0; + this._isReloading = false; // Use default values if settings are not yet set this.labelColor = "rgb(51, 209, 122)"; @@ -73,7 +74,6 @@ class MyDesklet extends Desklet.Desklet { } on_desklet_removed() { - this.settings.finalize(); this._stopSound(); this._removeNotification(); if (this._timeout) { @@ -84,6 +84,13 @@ class MyDesklet extends Desklet.Desklet { if (this._notificationSource) { this._notificationSource.destroy(); } + if (this.settings && !this._isReloading) { + this.settings.finalize(); + } + } + + on_desklet_reloaded() { + this._isReloading = true; } _onSettingsChanged() { @@ -106,7 +113,7 @@ class MyDesklet extends Desklet.Desklet { this._isInputView = true; const box = new St.BoxLayout({ vertical: true }); - box.style = "width: " + this.default_size * this.scaleSize + "em;"; + box.style = "width: " + this._default_size * this.scaleSize + "em;"; const labelRow = new St.BoxLayout(); const labelStyle = `font-size: ${1.5 * this.scaleSize}em; color: ${this.labelColor};`; @@ -194,7 +201,7 @@ class MyDesklet extends Desklet.Desklet { _setupTimerUI() { this._isInputView = false; - const absoluteSize = this.default_size * this.scaleSize; + const absoluteSize = this._default_size * this.scaleSize; const container = new St.Widget({ style: `width: ${absoluteSize}em; height: ${absoluteSize}em;` }); @@ -247,14 +254,14 @@ class MyDesklet extends Desklet.Desklet { icon_size: 16 * this.scaleSize, }); this.playBtn = new St.Button({ child: playIcon, style_class: "timer-input-button", style: this.buttonStyle }); - if (this._totalSeconds === 0 || this.isRunning || this._remainingMs <= 0) this.playBtn.hide(); + if (this._totalSeconds === 0 || this._isRunning || this._remainingMs <= 0) this.playBtn.hide(); this.playBtn.connect("clicked", () => this._onPlayPressed()); buttonRow.add_child(this.playBtn); // Restart button const refreshIcon = new St.Icon({ icon_name: "view-refresh-symbolic", icon_type: St.IconType.SYMBOLIC, icon_size: 16 * this.scaleSize }); this.restartBtn = new St.Button({ child: refreshIcon, style_class: "timer-input-button", style: this.buttonStyle }); - if (this._totalSeconds === 0 || this.isRunning || this._remainingMs > 0) this.restartBtn.hide(); + if (this._totalSeconds === 0 || this._isRunning || this._remainingMs > 0) this.restartBtn.hide(); this.restartBtn.connect("clicked", () => this._onRestartPressed()); buttonRow.add_child(this.restartBtn); @@ -265,7 +272,7 @@ class MyDesklet extends Desklet.Desklet { }); this.pauseBtn = new St.Button({ child: pauseIcon, style_class: "timer-input-button", style: this.buttonStyle }); this.pauseBtn.connect("clicked", () => this._onPausePressed()); - if (!this.isRunning) this.pauseBtn.hide(); + if (!this._isRunning) this.pauseBtn.hide(); buttonRow.add_child(this.pauseBtn); // Stop button @@ -291,12 +298,12 @@ class MyDesklet extends Desklet.Desklet { this._stopSound(); this._removeNotification(); const wasZero = this._totalSeconds === 0; - if (!this.isRunning && this._remainingMs === 0) { + if (!this._isRunning && this._remainingMs === 0) { this._totalSeconds = 0; } this._remainingMs += 60 * 1000; this._totalSeconds += 60; - if (this.isRunning) { + if (this._isRunning) { this._endTime += 60 * 1000; } this._updateTimerVisuals(); @@ -304,7 +311,7 @@ class MyDesklet extends Desklet.Desklet { this.newTimerBtn.hide(); this.playBtn.show(); this.stopBtn.show(); - } else if (!this.isRunning && this._remainingMs > 0) { + } else if (!this._isRunning && this._remainingMs > 0) { this.playBtn.show(); this.restartBtn.hide(); } @@ -315,7 +322,7 @@ class MyDesklet extends Desklet.Desklet { Mainloop.source_remove(this._timeout); this._timeout = null; } - this.isRunning = false; + this._isRunning = false; this.pauseBtn.hide(); this.playBtn.show(); } @@ -328,7 +335,7 @@ class MyDesklet extends Desklet.Desklet { this._stopSound(); this._removeNotification(); - this.isRunning = false; + this._isRunning = false; this._totalSeconds = 0; this._remainingMs = 0; this._inputDigits = ""; @@ -354,7 +361,7 @@ class MyDesklet extends Desklet.Desklet { } _startTimer() { - this.isRunning = true; + this._isRunning = true; this._endTime = Date.now() + this._remainingMs; this._updateTimerVisuals(); @@ -370,7 +377,7 @@ class MyDesklet extends Desklet.Desklet { if (this._remainingMs <= 0) { this._remainingMs = 0; this._updateTimerVisuals(); - this.isRunning = false; + this._isRunning = false; this._timeout = null; this.playBtn.hide(); this.pauseBtn.hide();