diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-16 10:54:49 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-16 10:54:49 +0200 |
| commit | 33a20ad0b33467c6980399bb618485b74d66dc04 (patch) | |
| tree | 48d20718d9dd80619125082cec90521b107eb6cb /desktop | |
| parent | 9a2f7cce971bf2dca54794896d083fdd2f2f1110 (diff) | |
| download | quickshell-33a20ad0b33467c6980399bb618485b74d66dc04.tar.gz quickshell-33a20ad0b33467c6980399bb618485b74d66dc04.zip | |
feat(user): a random greeting on each drawer open
The greeting row picks one at random from ~/.config/quickshell/greetings,
one per line with {user} for the login name, # comments and blank lines
skipped; without the file, five built-in ones. The row is rebuilt on every
drawer open, so the file is read then with no watch, and the last pick is
kept in User.js, a shared .pragma library, so the same greeting never
shows twice running.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop')
| -rw-r--r-- | desktop/modules/user/README.md | 7 | ||||
| -rw-r--r-- | desktop/modules/user/User.js | 18 | ||||
| -rw-r--r-- | desktop/modules/user/UserRow.qml | 14 | ||||
| -rw-r--r-- | desktop/modules/user/test_user.js | 10 |
4 files changed, 45 insertions, 4 deletions
diff --git a/desktop/modules/user/README.md b/desktop/modules/user/README.md index 63670eb..692fb78 100644 --- a/desktop/modules/user/README.md +++ b/desktop/modules/user/README.md @@ -1,6 +1,6 @@ # user -The drawer's greeting row (avatar, `Hello <login>`, real name) and the page +The drawer's greeting row (avatar, a greeting, real name) and the page it opens, which edits the user's details where other programs read them. | Field | Written to | @@ -17,6 +17,11 @@ stops and from three characters, per its usage policy. Up/Down, Enter and Escape work the list. Offline, the field is plain text. The Git section shows the name and email git will get, read-only, and the signing key. +The greeting is picked at random on each drawer open, never the same one +twice running, from `~/.config/quickshell/greetings`: one per line, `{user}` +for the login name, `#` comments and blank lines skipped. Without the file, +five built-in ones. + `userctl` does all reading and writing; the page only calls it. Polkit lets a user edit their own AccountsService entry without a prompt. A new detail is one entry in `UserPage.qml`'s `fields` and one `case` in `userctl`. diff --git a/desktop/modules/user/User.js b/desktop/modules/user/User.js index 5c3d5a2..dc48209 100644 --- a/desktop/modules/user/User.js +++ b/desktop/modules/user/User.js @@ -62,3 +62,21 @@ function places(text) { } return out; } + +// The drawer's greeting, from ~/.config/quickshell/greetings: one per line, +// {user} for the login name, blank lines and # comments skipped. A missing or +// empty file is the built-in set. The row is rebuilt on every drawer open, so +// the last pick lives here, in the shared library, to never show the same one +// twice running. +const defaultGreetings = ["Hello {user}", "Hi {user}", "Welcome back, {user}", + "Hey there, {user}", "Good to see you, {user}"]; +let lastGreeting = -1; +function greeting(text, user, random) { + const lines = text.split("\n").map(l => l.trim()).filter(l => l && !l.startsWith("#")); + const all = lines.length ? lines : defaultGreetings; + const skip = all.length > 1 && lastGreeting >= 0 && lastGreeting < all.length; + let i = Math.floor((random ?? Math.random()) * (all.length - skip)); + if (skip && i >= lastGreeting) i++; + lastGreeting = i; + return all[i].replace(/\{user\}/g, user); +} diff --git a/desktop/modules/user/UserRow.qml b/desktop/modules/user/UserRow.qml index b67d591..311c6df 100644 --- a/desktop/modules/user/UserRow.qml +++ b/desktop/modules/user/UserRow.qml @@ -16,7 +16,7 @@ import QtQuick import "../.." import "User.js" as U -// The drawer's greeting: avatar, login name, real name. It re-reads each time +// The drawer's greeting: avatar, a random greeting, real name. It re-reads each time // it becomes visible, which is every drawer open and every return from a // page, so a save on the user page shows here on the way back. Rectangle { @@ -38,6 +38,16 @@ Rectangle { onVisibleChanged: if (visible) read() Component.onCompleted: read() + // Read on creation, which is every drawer open, so an edit to the file + // shows on the next one with no watch. + property string greeting: "Hello " + Quickshell.env("USER") + FileView { + path: (Quickshell.env("XDG_CONFIG_HOME") || Quickshell.env("HOME") + "/.config") + "/quickshell/greetings" + printErrors: false + onLoaded: row.greeting = U.greeting(text(), Quickshell.env("USER")) + onLoadFailed: row.greeting = U.greeting("", Quickshell.env("USER")) + } + Process { id: reader command: [Qt.resolvedUrl("userctl").toString().replace(/^file:\/\//, ""), "get"] @@ -78,7 +88,7 @@ Rectangle { verticalCenter: parent.verticalCenter } spacing: 2 Text { - text: "Hello " + Quickshell.env("USER") + text: row.greeting font { family: Theme.fontFamily; pixelSize: Theme.fontSize + 2; bold: true } color: Theme.text } diff --git a/desktop/modules/user/test_user.js b/desktop/modules/user/test_user.js index 3f1a73d..cf38609 100644 --- a/desktop/modules/user/test_user.js +++ b/desktop/modules/user/test_user.js @@ -18,7 +18,7 @@ const assert = require("assert"); const src = fs.readFileSync(__dirname + "/User.js", "utf8") .replace(/^\.pragma library$/m, ""); -const U = new Function(src + "\nreturn { parse, keys, locales, gitName, places };")(); +const U = new Function(src + "\nreturn { parse, keys, locales, gitName, places, greeting };")(); // parse: key=value lines; a value may itself hold "=". assert.deepStrictEqual(U.parse("name=Jane Doèr\nlocation=a=b\n\n"), @@ -64,4 +64,12 @@ assert.deepStrictEqual(U.places(nominatim), [ assert.deepStrictEqual(U.places(""), []); assert.deepStrictEqual(U.places("<html>rate limited</html>"), []); + +// greeting: comments and blanks skipped, {user} filled, never the same twice +// running, and the built-in set when the file has nothing. +assert.strictEqual(U.greeting("# c\n\n Yo {user} \n", "jd", 0), "Yo jd"); +assert.strictEqual(U.greeting("a\nb", "jd", 0), "b"); +assert.strictEqual(U.greeting("a\nb", "jd", 0), "a"); +assert.ok(U.greeting("", "jd", 0).endsWith("jd")); + console.log("test_user: ok"); |
