aboutsummaryrefslogtreecommitdiffstats
AgeCommit message (Collapse)AuthorFilesLines
5 daysmail: open accounts and messages in qtmaildir from the drawer and notificationsDanilo M.7-55/+153
qtmaildir now takes --account, --thread and --message, and hands them to a running window over its socket, so the drawer and the notifications can open the exact thing they show instead of just launching the client. mail-open.sh is the one place that turns an account and a thread into selectors, shared by both callers. It looks up the thread's newest unread message at click time rather than when the row or notification was built: by then it may have been read, and an empty lookup falls back to the whole thread instead of a miss in qtmaildir's status bar. The notification never had a working click: dunstify is not installed, so mail-notify.sh always took its notify-send fallback, which carried no action. It now uses notify-send -A NAME=Text, one action per listed thread (keyed by thread id, which is hex and so never holds the "=" separator) plus the account as default. The round trip through notifyd was checked: notifyctl action makes notify-send print the picked name. On the page, the account header opens the account and a thread row its newest unread message. Rows use TapHandler and HoverHandler because a MouseArea cannot fill a Column. Launches are detached: a first launch is the client itself, and the old reused Process would have killed it on the next click. Opening anything now closes the drawer rather than going back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 daysperf: open btop in kitty from the page headerDanilo M.1-0/+10
The page shows a summary; btop is the full picture when the summary is not enough. The button sits in the header's actions slot, so it stays put while the panel scrolls, and closes the drawer on launch since the terminal takes over from there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 daysName the project Keystone, and move its paths and namespacesDanilo M.29-43/+44
The repository had no name of its own, only the framework's. It is now Keystone, in the README, AGENTS.md, the settings window, notes commit messages, calctl's PRODID and the user page's User-Agent. Its files move off quickshell's name too: ~/.config/quickshell/greetings -> ~/.config/keystone/ ~/.config/quickshell/obs-scene-icons.json -> ~/.config/keystone/ $XDG_STATE_HOME/quickshell/desktop.json -> $XDG_STATE_HOME/keystone/ ~/.config/quickshell is Quickshell's own default config directory (a bare qs loads its shell.qml), so sharing it was a collision rather than a home. There is no fallback to the old paths: the files are moved once. The layer namespaces become keystone-*, and the Hyprland blur rules in hypr-theme are renamed to match in the same change. A running shell keeps its old namespaces until restarted. Left alone: the retired standalone mail and vm shells' namespaces, which their READMEs keep as history; Quickshell's own app id, binary and process name; and the repository directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5 dayssettings: system card on the landing pageDanilo M.2-36/+230
The landing page was a paragraph of About text. It now carries the project's name, Keystone, a short About, and a system card: the Slackware facts of conky-theme-udt's card (version, package count, kernel, install age, and the slackpkg ChangeLog age, green under a day, yellow under a week, red past it), the machine, and base library and development tool versions, in two columns. The page scrolls once it outgrows the window. Everything comes from one sh process per open of the window, so there is no cache file and no dependency on conky's sampler. Library and tool versions are read from the installed package names in /var/log/packages: the version must start with a digit, so gcc does not also match gcc-g++, and stops at an underscore, which drops qt6's snapshot suffix. A package that is not installed shows a dash. The shortcut walkthrough left the About text: the drawer, island and assistant are described in their own READMEs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysisland: open the window source's properties from the pillDanilo M.3-6/+30
A Wayland window capture is chosen in the portal picker, which only OBS's source dialog can open. In a scene whose only source is a PipeWire capture, the panel gets a Window button that opens that dialog. A window scene with more than one source needs a per-scene designation the pill does not have yet.
6 daysisland: let record events own the OBS stateDanilo M.1-4/+13
6 daysisland: keep a paused OBS take as recordingDanilo M.1-2/+6
6 dayssettings: OBS scenes icon pageDanilo M.5-2/+264
6 daysisland: icon buttons, audio and corner controls, scene gridDanilo M.3-36/+92
6 daysisland: OBS desktop audio and webcam corner controlDanilo M.1-1/+41
6 daysisland: corner position helper for the OBS webcamDanilo M.2-1/+15
6 daysisland: watched scene icon map singletonDanilo M.1-0/+46
6 daysisland: scene icon map logic and its testsDanilo M.2-0/+139
6 daysdocs: OBS pill enhancements planDanilo M.1-0/+343
6 daysdocs: the OBS pillDanilo M.2-1/+20
6 daysisland: place the OBS pill and pulse the sliver while recordingDanilo M.1-2/+43
6 daysdocs: OBS pill enhancements designDanilo M.1-0/+279
6 daysisland: OBS pill and its controls panelDanilo M.1-0/+125
6 daysisland: Obs singleton, obs-websocket v5 clientDanilo M.1-0/+217
6 daysisland: obs-websocket auth helperDanilo M.1-0/+22
6 daysisland: elapsed-time helper for the OBS pillDanilo M.2-1/+17
6 daysdocs: the OBS pill opens a controls panelDanilo M.2-114/+137
At rest the pill is a record dot with the elapsed time; a click morphs it into a panel, as the status pill does for sound, with Record/Stop, Pause/Resume, Show/Hide webcam and the scene list. The user preferred it to every control inline: the pill stays small, and scenes are picked by name rather than stepped through, so obsStep is gone. OBS quitting with the panel open clears it, or the island would stay held open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdocs: OBS pill implementation planDanilo M.1-0/+528
Six tasks: logic helpers with their check, the openssl auth helper, the Obs singleton, the pill, island wiring with the sliver pulse, docs. Records two deviations from the spec found while planning: QML's WebSocket hides the close code, so a wrong password is logged as 'closed before Identified'; responses route on the echoed requestType. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdocs: OBS pill designDanilo M.1-0/+125
A pill on the island that exists while OBS runs: record, pause, scene, webcam visibility, and a pulsing sliver while recording. Talks to obs-websocket directly from QML (QtWebSockets is installed), reading the password from OBS's own config so no copy exists. Auth stays on because obs-websocket listens on every interface. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysvm: the tile is labelled VMsDanilo M.1-1/+1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysperf: sample everything always, not only while the page is openDanilo M.3-42/+19
Per-core load, the network rate, VRAM and the fan used to run only while a PerfPanel existed, and closing the page cleared them. Opening the drawer therefore always showed a fresh first sample and an empty network graph, which made the page not very useful as a glance at what just happened. Everything now samples for the whole session, so the graph opens on the last minute of history. The cost is the VRAM fdinfo scan, ~14ms every 2s, now unconditional; a ponytail note beside it says to gate it on the panel again if that shows up. The LAN address and the public IP check run once at startup instead of on each page open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 dayssettings: every page commits from the headerDanilo M.16-66/+96
The Mail, Assistant and Ask presets pages got a Save and Discard pair in the page header; the rest still had their own buttons wherever their page put them: User's Save at the bottom, Wallpaper's Apply and Reset beside the mock screens, Icons' Apply and Reset under the cursor cards, HyprSunset's and HyprIdle's Save + Restart in the page. They now all sit in the header SaveBar, which takes the page's own verbs (Apply and Reset, Save + Restart) and a busy state. HyprSunset and HyprIdle had no notion of an unsaved change, so their button was always live. They now count as changed when what save() would write differs from what was read, which enables Save only then, gives Discard (a reload) something to drop, and marks them in the sidebar; a window open no longer reloads them over unsaved edits. The staged cursor moved from IconsTab into the Icons singleton so the header and the sidebar can see it. Git and autostart act a row at a time, and a theme applies on click, so those have no bar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 dayssettings: pages edit a draft, and Save writes itDanilo M.19-161/+429
The qtmaildir, Assistant and Ask presets pages wrote a field on Enter, and a switch or chip the moment it was clicked, so a half-finished change reached the file and a slip could not be taken back. They now edit a draft as fields are typed, and a Save and Discard pair in the page header (SaveBar, through Page.actions) writes or drops it. Save waits while a field holds a value that cannot be written, and a draft over a file that changed on disk meanwhile is refused at Save rather than written over it. A dot in the sidebar marks a page with unsaved edits; drafts survive moving between pages. The four Mail pages share one draft, since they are one file. Tool switches are staged too and renamed on Save; model Load, Prefer and Restart stay immediate, being actions rather than settings. Live editing needed two rules. A field is no longer bound to its value, which would reset the cursor and eat a typed trailing space; it follows the value only when the draft moves under it. And a Repeater's model is now the set of row keys (or a count), assigned only when that set changes: an array rebuilt from the draft on each keystroke recreates every row, including the one being typed in, which loses its focus. Git, autostart's rows, HyprSunset, HyprIdle and User keep their own buttons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdocs: Quick dialogs open light here, labs.platform ones follow kvantumDanilo M.1-0/+7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysqtmaildir settings: the colour dialog follows the desktop's dark styleDanilo M.1-6/+13
QtQuick.Dialogs' ColorDialog opened light on the dark desktop. It paints from the Qt Quick palette, which qt6ct leaves at Qt's default here: its custom_palette is off and the dark comes from the kvantum-dark widget style, which Qt Quick does not use. Qt.labs.platform's ColorDialog falls back to the widget QColorDialog in a QApplication, which this process already is for the tray menus, and widgets take the kvantum style like every other application. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysqtmaildir settings: a colour picker for colour fieldsDanilo M.5-12/+86
An account's chip colour and each tag colour were #rrggbb typed by hand. A swatch beside each now shows the colour and opens Qt's own ColorDialog, which writes the choice back as #rrggbb; typing still works. The add-tag row has one too, filling its field. Setting.qml gains a colour flag rather than a second component, since a colour key is an ordinary text key with a swatch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 dayssettings: qtmaildir's config, in four Mail pagesDanilo M.21-1/+1236
qtmaildir is configured through qtmaildir.conf alone, which it reads at startup and never writes. Four settings pages under a new Mail group edit it: Mail ([general], [sync], [completion]), Compose, Accounts (a card per account, add and remove) and Tags & shortcuts ([tagcolors] and [keys]). Fields save on Enter and unset when emptied, with qtmaildir's defaults as placeholders and numbers range-checked; the pages say when qtmaildir is running and a change waits for its restart. Ini.js edits the file line by line so its comments survive. Headers are only whole [name] lines: a section is never cut at the next "[", since values such as [Gmail]/Bozze hold brackets, the trap AGENTS.md records. The shortcut actions are copied from qtmaildir's KeyMap::knownActions() rather than exported by it, since a CLI flag there would have meant translations and a changelog entry; the field also takes free text, and the copy is marked as a ponytail ceiling. The settings sidebar now clips, which a list long enough to scroll showed it did not: entries drew over the search box. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysassistant: Load no longer changes the preferred modelDanilo M.4-15/+27
Load set the preference as well as swapping the model in, so loading a model from the settings page for any reason made it the assistant's model too: after loading Qwen there, the canvas kept Qwen instead of bringing the preferred Gemma back. Load and Prefer are now separate buttons: Load swaps a model in now and leaves the preference alone, and Prefer only records which model the canvas loads when it opens. The canvas header also showed a stale model name after a swap; it now takes the model from the daemon's ctx event, which carries it from desktop-assistant f9d4644 on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysassistant: opening the canvas loads the preferred modelDanilo M.5-2/+33
A preferred model that only took effect from the settings page did nothing the next time another client had swapped it out. On this desktop one model and one client run at a time, so opening the canvas is when the assistant's model should come back: if the preferred one is neither loaded nor loading, it is loaded, and the canvas header says so until the router reports it in. The daemon still never asks for a model; with no preference set nothing changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysassistant: pick the preferred model, loaded on demandDanilo M.5-1/+151
The daemon answers with whichever model llama-server has loaded and never asks for one, so it never evicts a model another client is using. The Assistant settings page now lists the router's models with their state. Load saves one as the preferred model, in Prefs, and asks the router to load it now, polling /v1/models until it reports loaded; Prefer marks the loaded model as preferred without swapping. The swap happens only on that click, so the daemon's rule holds. AGENTS.md records the router's load endpoint and its two refusals, both measured: it lives on the server root, not under /v1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 dayssettings: the sidebar is groupedDanilo M.13-33/+74
Ten pages in one flat list had stopped reading as a list. A module now names its group, and the sidebar sorts by it and draws a small heading where it changes: Account (user, git), Appearance (wallpaper, theme, icons), Desktop (HyprSunset, HyprIdle, autostart) and Assistant (the daemon, Ask presets). Groups keep the order their first page is declared in, so shell.qml's module order still decides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 dayssettings: the assistant's daemon config, tools, and Ask presetsDanilo M.12-3/+1117
Two settings pages for desktop-assistant. Assistant edits the daemon's config.toml: server, temperature, tool rounds, thinking, the system prompt, and the [env] values its tools read; a switch per tool renames tools/<name>.toml to .toml.off, which the daemon's glob skips. The daemon reads all of it at startup only, so the page says when a change is pending and Restart runs assistant.sh restart, showing its status when the daemon does not come back. The file is edited line by line, like autostart.lua, so the comments the example ships with survive: unset keys stay commented out in place. Every write parses the whole new file with tomllib first and replaces the old one atomically, so no edit can leave a config the daemon will not start with. Defaults are read from assistant.py --defaults rather than copied into QML. Ask presets edits the canvas's canned questions, which Prefs already stored for exactly this page: label, question, and the kinds each is offered for. They apply live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysicons: cursor previews load againDanilo M.1-1/+0
Moving the appearance files into the desktop added import "../.." after the last line of each file that began with "import". In Icons.qml that line is inside the embedded Python cursor script, so the import landed there: python3 died on a SyntaxError, printed nothing, and every cursor card stayed empty with nothing in the log. Icons.qml uses no Theme, so the line goes. Every other moved file has it above its root object. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 dayswallpaper: the preview above the listDanilo M.2-111/+108
The mock screens took a third of the width beside the list, which left both cramped in the settings window. They now sit on top, sized to half the width and capped so the upright screen stays under 200px, with the notes and the actions beside them; the folder list takes the full width and the rest of the height below. The actions are a Flow, so they wrap instead of clipping in a narrow window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysuser: the details page moves to the settings windowDanilo M.2-5/+9
The drawer's greeting row stays, and clicking it now closes the drawer and opens the user page in the settings window: Drawer.show already hands a settings module to the window, so the row's handler is unchanged. "More git settings" switches the window to the git page through the same go() it used in the drawer. The page is searchable by the fields it edits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdrawer: the settings gear moves from the grid to the user headerDanilo M.3-14/+33
The grid is for quick settings, and the window it opened is the opposite, so a tile for it sat wrong. The gear now sits at the right of the user header, a round button that closes the drawer and opens the settings window on its landing page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdocs: Ctrl+Q in the settings windowDanilo M.1-1/+1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 dayssettings: Ctrl+Q closes the windowDanilo M.1-0/+7
A window-wide Shortcut rather than a Keys handler, so it works with the focus in a field, where Escape is taken first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 dayssettings: HyprSunset and HyprIdle, named after what they configureDanilo M.3-6/+6
The labels and page titles only; the module names, and so the IPC verbs and search keys, stay sunset and idle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysappearance moves into the settings windowDanilo M.31-780/+783
The appearance shell existed because a wallpaper picker needed more room than the 600px drawer, so it ran as its own process with a full-screen overlay. The settings window now gives it that room, and its five tabs become five settings pages in the desktop process: Wallpaper, Theme, Icons & cursor, Sunset and Idle. appearance/ is gone, and with it a process, a keepalive window and a layer blur rule. The files move to desktop/modules/appearance/ unchanged in what they do. Each tab gets a small *Module.qml; the window's refresh-on-open calls the singletons' refresh(), which the panel's show() used to. The two tabs that were inline Components in AppearancePanel become ThemeTab and WallpaperTab, owning the notices the panel printed. Sunset, Idle and Icons drop their own Flickable so the page scrolls them and search can reveal a row; the wallpaper list virtualises its rows and scrolls itself, so it takes the page's new viewHeight instead. Search finds a colour scheme and an icon or cursor theme by name. The appearance IPC target moves to desktop/shell.qml with the same verbs, so udt-steps and any keybind change only the path. Git now follows the appearance pages and autostart in the sidebar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdesktop: centred About, and a resizable settings sidebarDanilo M.3-35/+88
The About text sat in the top-left corner of an otherwise empty page; it is now centred both ways in the space beside the sidebar. The sidebar's edge, the rule between it and the page, drags to resize it between 160 and 420px, lit in the accent while hovered. The width lives in Prefs, written once on release rather than on every pixel of the drag, so it survives a restart without a file to edit by hand. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdesktop: a clear button in the settings searchDanilo M.1-1/+19
A small x at the right of the field while something is typed. Clearing puts the focus back in the field, ready for the next search. Escape still clears from the keyboard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdesktop: settings search finds rows, and a hit reveals its rowDanilo M.9-29/+161
Search used to stop at the page: clicking a result opened it at the top and left the setting to be found by eye. Now each settings module keeps its rows as searchItems, {text, key}, reread on every window open since the page itself is not loaded until shown: git runs gitcfg list, and autostart watches its file. A row hit opens the page, and Page.reveal() finds the row whose objectName is the key, waiting up to 3s for the page's own data, scrolls to it and flashes it in the accent. The reveal lives in Page, so a page only names its rows. Git's long keyword list was a stand-in for exactly this and is cut to "gitconfig". The autostart page takes its path from the module now that both read the file. Also corrects the AGENTS note on missed hot reloads: it blamed sed -i replacing the file, but the Edit tool writes a new inode too and usually reloads. The cause is unknown; the note now says how to detect it and that a process that stops watching needs a restart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdesktop: settings search, and an About landing pageDanilo M.5-38/+134
The landing page's tiles repeated the sidebar. It now says what the shell is and where things live, which is what a landing page is for. The sidebar gains a search. A page is a Component loaded only when opened, so its contents cannot be indexed without loading every page; instead a module lists keywords for the settings buried in its page, and the search matches those and the label. An entry matched by a keyword shows which one, Enter opens the first match, Escape clears and then steps out as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 daysdesktop: the settings window gets a landing pageDanilo M.2-8/+51
The page header's back arrow closed the whole window, which reads wrong for a back button. The window now opens on a landing page, a tile per settings page in the drawer's own Tile, and back and Escape step out to it; Escape there closes the window, as on the drawer's grid. An empty or unknown name opens it, so the gear tile and ipc toggle land there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>