- Startseite
- Plugins
- UI-Erweiterungen
- dsh-im-workspace-buttons
dsh-im-workspace-buttons
whatcannotbesaid/dsh-im-workspace-buttons
Adds one 28x28 icon button per dsh-im channel that holds an account to the official Workspaces header row. Pressing one puts the sidebar into that channel's view, drawing only its conversations and hiding every other row; pressing it again drops back to the official list. Buttons appear only for channels with a connected account.
Installation
dsh plugin --profile web add github:whatcannotbesaid/dsh-im-workspace-buttonsREADME
Workspace Channel Buttons
English | 中文
One 28×28 icon button per @xmanrui/dsh-im channel that holds an account, placed in the official 「工作区」 (Workspaces) header row. Pressing one puts the sidebar into that channel's view: only its conversations are drawn, and the official list (every other conversation, every group header) waits behind it. Pressing the same entry again drops back to the official list, where every dsh-im conversation is hidden again.
This is the single feature extracted from eva-inspired-theme: the buttons and nothing
else. No skin, no theme replacement, no dependency on the theme's CSS, locale namespace
or build pipeline.
Install
# 1. install the package
npm install dsh-im-workspace-buttons --prefix ~/.dsh/profiles/desktop --registry=https://registry.npmjs.org
# 2. add it to the profile's bundle list (<profileDir> = ~/.dsh/profiles/desktop)
# append "dsh-im-workspace-buttons" to dsh.profile.bundles in package.json
Restart DSH afterwards. The package ships its own dsh.bundle.patch, so
cordis.patch.yml needs no hand edit — but the profile's dsh.profile.bundles must list
this package, or the loader never mounts it.
Requires @xmanrui/dsh-im and at least
one channel with a connected account; by design no buttons appear otherwise.
Migrating from the theme edition
eva-inspired-theme 1.2.0 no longer contains these buttons. Do not install both:
- The theme edition uses the
data-eva-im-*contract and theeva-im-filterlocale namespace; this package usesdata-dsh-im-*anddsh-im-workspace-buttons. Installed together they draw two sets of buttons on the same row, and neither stylesheet covers the other's. - Upgrading to
eva-inspired-theme@1.2.0and installing this package is a drop-in swap: interaction, icons, order and the visibility rule are identical.
Behaviour
| Plugin id | dsh-im-workspace-buttons (also the client module id and the locale namespace) |
| Where | The header row carrying the official sidebar.workspaces.directoryFlow marker, left of the search slot, in the plugin's own channel order |
| Visibility | An entry appears only when the channel has an account: connection.status returns a non-empty botId in bots[], or the older configured: true. An inconclusive probe (RPC not ready, request failed) draws nothing on the first pass and keeps the previous verdict after that |
| Click | Puts the sidebar into that channel's view: its conversation rows (recognised by data-dsh-im-session-channel or by the row's title belonging to the channel) stay, and every other row — other channels, official conversations, group headers, show-more controls — is hidden. A second click drops back to the official list |
| Collapsed groups | Unfolded, paged and scrolled to the channel's first conversation only on click, capped at CLICK_LIMIT = 200 steps. The controls are hidden in the view but still clickable, so the rows are drawn before they are hidden |
| dsh-im hidden by default | No dsh-im conversation shows in any of the three views — 工作区, 工作区树, single list — until its entry is pressed. Every dsh-im row carries data-eva-im-tag='off'; only the lit channel's own rows turn 'on'. A row that is not a dsh-im conversation is never tagged and is never hidden by the official list; in a lit view it is 'off' like everything else |
| Group ownership | A conversation counts as living in exactly one group, decided by home(): the workspace record whose sessionIds names it owns it, and everything else is Ungrouped (the empty workspace: suffix). That is the host's own rule (groupByWorkspace); cwd takes no part in it |
| Ungrouped bucket | Ungrouped has no header to press — only its own show-more control, keyed overflow: with nothing after the colon. The plugin clicks that control and never a header for it |
| Flat list | The host draws both lists through AnimatedRows, so the single list's rows sit inside the same [role='tree'] and need no separate container. tree() still answers with a [data-testid="session-list"] container when a host draws the rows outside that tree. The whole page is one overflow: row; the plugin records it as __ungrouped_session__ and opens that single control, so a channel view can reach conversations past the first page |
| Labels | Through the Client locale service; follows the profile language, falls back to Chinese when the registry is absent |
| Untouched | Official grouping, collapsed state, spy counts, conversation order — none of them are rewritten. A lit view hides the official rows along with everything else, and dropping back draws them exactly as the host had them |
Style contract
The runtime injects its own <style data-dsh-im-workspace-buttons-sheet>; every colour
comes from a --dsw-* token:
| Selector | Effect |
|---|---|
[data-eva-im-button] | 28×28, no border, no background, --dsw-radius-sm corners, --dsw-alias-label-secondary foreground |
[data-eva-im-button]:hover | Foreground turns --dsw-alias-label-primary |
[data-eva-im-state='on'] | The lit entry turns --dsw-alias-brand-primary |
[data-eva-im-tag='off'] | Hides that one row — the only hiding rule in the sheet. It is written on dsh-im rows while no entry is lit, and on every row that does not belong to the lit channel |
The data-eva-im-* prefix is kept verbatim from the extraction; renaming it would break
style compatibility with eva-inspired-theme. The rule is a plain attribute test, so an
"off" state must be written explicitly: a row with no tag is a row the host draws as-is.
The tag lives on its own attribute rather than on data-eva-im-row, which is in this
effect's MutationObserver filter — a per-row tag there would re-trigger every pass. The
pump hides rows after it has clicked them, which is why the sheet never hides a control
the runtime still has to click.
Dependencies
| Dependency | Kind |
|---|---|
@xmanrui/dsh-im | Required at runtime. The channel table and the status probe both read its connection.status; without it no button appears |
Host client services sessions / workspaces / locale / connection | Taken through ctx.get only, never imported |
eva-inspired-theme | Not needed. Styles, locale namespace and build are all self-contained |
Development
node tools/build-client.mjs # rewrite the runtime section of client.js from src/runtime.js
node tools/build-client.mjs --check # assert client.js and src/runtime.js agree
node --test --test-timeout=15000 test/*.test.mjs # 14 behaviour tests, fake DOM, no browser
node test/render.mjs # real browser: isolated profile + this package + dsh-im
The runtime inside client.js is a copy, not an import: the client module loader
evaluates client.js as a classic script, so the file cannot contain a module graph.
tools/build-client.mjs keeps the copy honest.
Files
| File | Purpose |
|---|---|
index.js | Host entry, ESM, export apply(ctx); one log line, no service / route / Config |
client.js | Browser entry, window.__ModuleLoader__.load({ id, factory }), carries the runtime copy |
src/runtime.js | Runtime source of truth (export function mountWorkspaceButtons(ctx)) |
cordis.patch.yml | - insert: [{ id, name }]; also the browser roster entry |
locale/zh.json · locale/en.json | meta.title / meta.description plus the 12 channel labels |
tools/build-client.mjs | Inlines src/runtime.js into client.js, --check verifies it |
test/fake-dom.mjs · test/behaviour.test.mjs | Fake DOM and 14 behaviour assertions |
Three deviations from the theme edition
- Locale namespace renamed
eva-im-filter→dsh-im-workspace-buttons. The registry keeps the first registration for a namespace, so two packages sharing one would overwrite each other's dictionary. The fallback language also moved fromDICT.entoDICT.zh, because these strings were written in Chinese — an untranslated language reading Chinese beats reading English. - Styles moved from
theme.cssinto the runtime's own<style>(data-dsh-im-workspace-buttons-sheet). The four rules are copied verbatim; selectors, sizes and colour tokens are unchanged. - The disposer also calls
removeSheet(). In the theme the styles live with the skin document, so the rules survived unloading; in a standalone package "uninstalling must stop affecting the document" is a hard rule, so the buttons and the rules leave together.
Beyond these three, behaviour, channel table, icons, probe interval, click limit and selectors are identical to the theme edition.
Licence
MIT — see LICENSE.
Ähnliche Plugins
dsh-web (dsh-task-board)
zhu1090093659/dsh-web
dsh-web (dsh-web-all)
zhu1090093659/dsh-web
dsh-web-ui (dsh-task-board)
zhu1090093659/dsh-web-ui
dsh-web-ui (dsh-web-ui-all)
zhu1090093659/dsh-web-ui