aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/user
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/modules/user')
-rw-r--r--desktop/modules/user/README.md7
-rw-r--r--desktop/modules/user/User.js18
-rw-r--r--desktop/modules/user/UserRow.qml14
-rw-r--r--desktop/modules/user/test_user.js10
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");