boot-time@KopfdesDaemons: Initial release#1705
boot-time@KopfdesDaemons: Initial release#1705KopfdesDaemons wants to merge 13 commits intolinuxmint:masterfrom
Conversation
KopfdesDaemons
commented
Dec 15, 2025
There was a problem hiding this comment.
Pull request overview
This pull request introduces a new Cinnamon desklet called "Boot Time" that displays system boot time information retrieved from systemd-analyze. The desklet provides a visual breakdown of boot stages including firmware, loader, kernel, userspace, and graphical target times with customizable colors and styling options.
Changes:
- New desklet implementation with async systemd-analyze integration
- Configurable UI with color customization and loading animations
- German translation support (de.po)
Reviewed changes
Copilot reviewed 7 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
boot-time@KopfdesDaemons/info.json |
Author metadata for the desklet |
boot-time@KopfdesDaemons/screenshot.png |
Screenshot image for desklet showcase |
boot-time@KopfdesDaemons/files/boot-time@KopfdesDaemons/settings-schema.json |
Settings configuration with color and display options |
boot-time@KopfdesDaemons/files/boot-time@KopfdesDaemons/po/de.po |
German translation file |
boot-time@KopfdesDaemons/files/boot-time@KopfdesDaemons/po/boot-time@KopfdesDaemons.pot |
Translation template |
boot-time@KopfdesDaemons/files/boot-time@KopfdesDaemons/metadata.json |
Desklet metadata with UUID and version |
boot-time@KopfdesDaemons/files/boot-time@KopfdesDaemons/icon.png |
Desklet icon image |
boot-time@KopfdesDaemons/files/boot-time@KopfdesDaemons/helpers/boot-time.js |
Helper class to execute and parse systemd-analyze output |
boot-time@KopfdesDaemons/files/boot-time@KopfdesDaemons/desklet.js |
Main desklet implementation with UI and settings management |
| channel.shutdown(true); | ||
| errClosed = true; |
There was a problem hiding this comment.
Similar to the stdout channel, the stderr channel should be explicitly unreferenced after shutdown for proper resource cleanup.
| this.animationState += 0.01; | ||
| if (this.animationState > 1) this.animationState = 0; |
There was a problem hiding this comment.
The animation state increment of 0.01 per frame at 60 FPS means the animation takes 100/60 = ~1.67 seconds to complete. Consider making this a configurable constant or adjusting it to complete in a rounder number like 1 or 2 seconds (e.g., 0.0167 for 1 second at 60 FPS).
| let [status, data] = channel.read_to_end(); | ||
| if (data) outOutput += data.toString(); |
There was a problem hiding this comment.
The read_to_end method is called every time IOCondition.IN is triggered, which could read partial data multiple times. Consider using read_line or read_chars in a loop instead to properly accumulate output, as read_to_end reads all available data until EOF. The current implementation may work but is semantically incorrect - you should read incrementally on each IN event, not call read_to_end repeatedly.
| let [status, data] = channel.read_to_end(); | ||
| if (data) errOutput += data.toString(); |
There was a problem hiding this comment.
The same issue with read_to_end applies here as in the stdout handler. Consider reading incrementally rather than calling read_to_end on each IN event.
| { name: "Graphical", label: _("Graphical:"), value: graphical ? graphical[1] : null }, | ||
| ]; | ||
| } | ||
| if (String(err).includes("Bootup is not yet finished")) throw new Error("Bootup is not yet finished"); |
There was a problem hiding this comment.
The error message check is performed on the string representation of err which may not be the complete error message. It would be more reliable to check the out variable first (which is already done on line 63) before checking err, and ensure consistent error message detection.
| if (String(err).includes("Bootup is not yet finished")) throw new Error("Bootup is not yet finished"); | |
| if (err && err.includes("Bootup is not yet finished")) throw new Error("Bootup is not yet finished"); |
| this._loadingUIisLoaded = true; | ||
| this._getLoadingUI(); | ||
| } | ||
| this._loadingTimeoutId = Mainloop.timeout_add_seconds(1, () => this._setupUI()); |
There was a problem hiding this comment.
The timeout callback should return false explicitly to prevent it from being called again. While the timeout is removed with source_remove, it's better to also return false for clarity and to follow the expected pattern for timeout callbacks.
| this._loadingTimeoutId = Mainloop.timeout_add_seconds(1, () => this._setupUI()); | |
| this._loadingTimeoutId = Mainloop.timeout_add_seconds(1, () => { | |
| this._setupUI(); | |
| return false; | |
| }); |
| channel.shutdown(true); | ||
| outClosed = true; |
There was a problem hiding this comment.
The channels should be explicitly closed after shutdown to avoid potential resource leaks. While shutdown(true) is called, explicitly calling unref() after shutdown would be more defensive programming to ensure proper cleanup.