Minimal loadable DMS widget skeleton with plugin.json manifest and TailscaleWidget.qml component. Symlinked, enabled, and loaded cleanly in Dank Material Shell. References #1, #2
4.6 KiB
Problem Statement
Users of Dank Material Shell want a lightweight, native-feeling status widget on the Dank Bar that shows Tailscale connectivity at a glance and provides quick controls (toggle connection, switch exit nodes, copy addresses) without leaving the shell or opening a separate GUI.
Solution
A DMS widget plugin (tailscale) that renders a compact pill in the Dank Bar using the standard PluginComponent + DankIcon pattern. The icon reflects connected/disconnected state. Right-click toggles Tailscale via the official CLI. Left-click opens a PopoutComponent flyout containing current IP, active exit node, and a peer list with one-click exit-node selection and copy-to-clipboard actions. All interaction is driven by tailscale status --json, tailscale up/down, and tailscale set --exit-node=....
User Stories
- As a DMS user, I want to see a Tailscale icon in my Dank Bar so that I know at a glance whether I am connected to my tailnet.
- As a DMS user, I want the icon to change when Tailscale is connected vs. disconnected so that I can visually confirm status without clicking.
- As a DMS user, I want to right-click the widget to toggle my Tailscale connection so that I can quickly go online or offline.
- As a DMS user, I want to left-click the widget to open a flyout with my current Tailscale IP and active exit node so that I have the most important information in one place.
- As a DMS user, I want the flyout to list all devices on my tailnet with their Tailscale IPs so that I can quickly find a peer.
- As a DMS user, I want to click any device name or IP in the flyout to copy it to the clipboard so that I can easily share or paste addresses.
- As a DMS user, I want any peer that offers an exit node to show a “Use as exit node” button so that I can route my traffic through that node with one click.
- As a DMS user, I want the widget to automatically refresh status every few seconds so that the displayed information stays current.
- As a DMS user, I want errors from Tailscale commands to appear as toast notifications so that I am informed when something goes wrong.
- As a DMS user, I want the plugin to work with the standard DMS plugin loading mechanism (plugin.json + QML component) so that I can enable it like any other widget.
Implementation Decisions
- The plugin will be implemented as a single
PluginComponentwidget (type: "widget"). - Iconography will reuse existing Material symbols (
vpn_key/vpn_key_off) for connected/disconnected states; no custom assets required for v1. - All Tailscale interaction will be performed via
Process+StdioCollectorcalling thetailscaleCLI (no direct Tailscale API or daemon socket). - Status polling will be driven by a
Timerinside the QML component (interval exposed only via code, not user settings). - The flyout will be implemented with
popoutContent+PopoutComponentfollowing the DMS widget-with-popout pattern. - Click-to-copy will use
Quickshell.execDetached(["sh","-c","echo -n '…' | wl-copy"])andToastService. - Exit-node selection will call
tailscale set --exit-node=<hostname>(andtailscale set --exit-node=to clear). - The plugin will request the three permissions:
settings_read,settings_write,process. - No
PluginSettingscomponent or persistent user preferences will be provided in v1. - The widget will support both horizontal and vertical bar orientations using the standard
horizontalBarPill/verticalBarPillproperties.
Testing Decisions
- Good tests exercise external behavior only: icon state changes when
tailscale statusreports Running vs. Stopped, toggle commands are issued on right-click, flyout content matches parsed JSON, copy actions invoke the expected clipboard command. - The primary testable module is the status-parsing and command-generation logic inside
TailscaleWidget.qml. - Prior art: the existing
dms-tailscaleplugin in the DMS plugin library uses the sameProcess+StdioCollector+Timerpattern; tests should mirror that style.
Out of Scope
- Custom Tailscale logo SVG or branded assets.
- Settings UI, refresh-interval configuration, or preferred-exit-node list.
- Traffic graphs, ping, or file-send/receive features (those belong in a full GUI like KTailCtl).
- Multi-user or multi-profile Tailscale support.
- Any changes to Dank Material Shell core or Quickshell itself.
Further Notes
The implementation deliberately stays close to the lightweight dms-tailscale reference while adding the exit-node and copy-to-clipboard features requested. It follows the exact DMS plugin development patterns documented at https://danklinux.com/docs/dankmaterialshell/plugin-development (v1.4).