From cb936e93be75bae93fbd5a81f39376cd31142e71 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 16 Oct 2026 09:34:51 +0200 Subject: docs(spec): user details in the drawer A drawer row greets the login user and opens a page that edits name, email, avatar, language and location, written where other programs already read them: AccountsService (and through it the passwd GECOS LibreOffice reads), KDE's emaildefaults and the global git config, with the surname shortened to an initial for git. Co-Authored-By: Claude Opus 5.5 --- .../specs/2026-10-16-user-details-design.md | 97 ++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 docs/superpowers/specs/2026-10-16-user-details-design.md (limited to 'docs/superpowers/specs/2026-10-16-user-details-design.md') diff --git a/docs/superpowers/specs/2026-10-16-user-details-design.md b/docs/superpowers/specs/2026-10-16-user-details-design.md new file mode 100644 index 0000000..2b2819b --- /dev/null +++ b/docs/superpowers/specs/2026-10-16-user-details-design.md @@ -0,0 +1,97 @@ +# User details in the drawer + +## Goal + +Edit the user's own details from the drawer and write them where other +applications already look for them, so LibreOffice, KDE apps, SDDM and git +pick them up without being told. + +## Where the details live + +Measured on this machine: + +- **AccountsService** (`org.freedesktop.Accounts`, D-Bus activated, not a + running daemon until called): `RealName`, `Email`, `IconFile`, `Language`, + `Location`. Read by KDE's Users settings, GNOME and SDDM. `SetRealName` + also rewrites the GECOS field of `/etc/passwd`. +- **GECOS** is what LibreOffice's `libdesktopbe1lo.so` reads to prefill its + user data (`givenname`). Name only, never email. +- **`~/.config/emaildefaults`** (KEMailSettings, `[PROFILE_Default]`): + `FullName`, `EmailAddress`. Read by KDE mail apps. +- **git** global config (`~/.gitconfig`): `user.name`, `user.email`. + +Polkit's `org.freedesktop.accounts.change-own-user-data` is implicit `yes` for +any, inactive and active sessions, so no write prompts for a password. + +## Drawer row + +A row at the top of the drawer's grid view, above the notification list: +the avatar in a circle, `Hello ` (the login name, `$USER`, which is +fixed and not editable), and the real name as a smaller sub-line under it. +Clicking it opens the user page; Escape and the mouse back button step out +as on every page. + +## Module: `desktop/modules/user/` + +- `UserModule.qml`: name `user`, label `User`, a `page`. It sets + `tiled: false`, a new `Module` property (default `true`) that the drawer's + tile grid filters on, so the module has a page and no tile. +- `UserRow.qml`: the drawer row. `Drawer.qml` places it above + `NotificationList` and calls `show("user")` on click. +- `UserPage.qml`: the form. Avatar (click to choose a file with + `QtQuick.Dialogs.FileDialog`, as the KDE Connect module already does; shown + cropped to a circle, no cropping tool), name, email, language (a combo from + `locale -a`, UTF-8 entries only), location (free text), and a line previewing + what git will carry: `git: Jane D. `. A Save button sends + only the fields that changed. +- `userctl`: bash, the only writer, like `statusctl`. + +The page reads values when it opens. The row reads them when the drawer +opens. + +## `userctl` + + userctl get # key=value lines: name, email, avatar, language, location + userctl set # writes one field everywhere it lives + +| Field | Writes | +| --- | --- | +| name | AccountsService `SetRealName`, emaildefaults `FullName`, git `user.name` (shortened) | +| email | AccountsService `SetEmail`, emaildefaults `EmailAddress`, git `user.email` | +| avatar | AccountsService `SetIconFile` (the daemon copies the file in) | +| language | AccountsService `SetLanguage` | +| location | AccountsService `SetLocation` | + +AccountsService is called with `busctl --system`, emaildefaults with +`kwriteconfig6 --file emaildefaults --group PROFILE_Default`, git with +`git config --global`. + +**Git name shortening.** The last whitespace-separated word becomes its first +character and a dot: `Jane Doèr` becomes `Jane D.`. A single-word name +is unchanged. The first character is taken by character, not byte, so an +accented initial survives. + +`set` exits non-zero on the first failing write and prints the failing +command's stderr. The page shows that text under the field, and leaves the +field marked changed so Save retries it. + +## Extending + +A new detail is one entry in the field list in `UserPage.qml` and one `case` +in `userctl`. No settings framework. + +## Testing + +`test-userctl.sh`: stub `busctl`, `kwriteconfig6` and `git` on `PATH` that log +their arguments. Checks the shortening (two words, three words, one word, +accented initial), that each field reaches exactly its stores, and that a +failing stub makes `set` exit non-zero. It never calls the real +AccountsService or touches the real git config. + +## Ceilings + +- Values are read on open; a change made elsewhere while the page is open is + not seen until it reopens. +- No `~/.face.icon`: SDDM reads the AccountsService icon. +- No vCard, no social links, no GPG key: nothing on the desktop reads them. + The field list is where they would go. -- cgit v1.2.3