* feat: add cellular support * fix(settings): resolve cellular tab index collision * fix: address review feedback for cellular support Bump the network API version, drop the deleted term freeze file, regenerate the settings search index, and reuse existing translation terms where they already cover the new cellular UI. * fix: do not assign readonly userPreference when switching network type Assigning SettingsData.networkPreference through the readonly alias threw on click, so the Cellular segment in Control Center did nothing. * fix: make Cellular selectable and the modem row clickable The Control Center type switcher was bound only to preference, so Cellular snapped back to Ethernet. The settings modem row highlighted on hover but had no click handler. Show the modem as a connect target when no APN profiles exist. * fix: create a GSM profile when connecting cellular with none saved Clicking Mobile broadband only activated an existing profile, so a modem with no APN did nothing useful. Fall back to AddAndActivate like ethernet connect. * fix: address second round of cellular review feedback - Guard cellularDevices map with devMutex via snapshot/by-iface/set/remove helpers, mirroring the existing ethernet and wifi accessors - Regenerate mocks with mockery v3 instead of hand-editing mock_Backend.go - Reuse refreshCellularState() in SetCellularEnabled, DisconnectCellular, DisconnectCellularDevice, ActivateCellularConnection and device removal - Wrap retryErr rather than the first error when the auto-config retry fails - Use Theme.surfaceTextSecondary/primaryHover/primaryHoverLight in the cellular-off state instead of hand-rolled Qt.rgba values - Drop the duplicate "No devices found" label so it can no longer render twice with no modem and no saved config Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> * fix: address remaining cellular review comments - Toast "Failed to toggle cellular" instead of always "enable" - Remove unused enableCellularRadio() wrappers - Store Control Center network type as a value, not a list index * fix: pass nmcli connection selector as separate argument `nmcli con mod uuid:<UUID>` is not valid syntax -- nmcli expects the selector keyword as its own argument, so every priority update failed with "no such connection profile". Because practically every NM profile has a UUID, this silently disabled autoconnect-priority and route-metric updates for ethernet and WiFi as well as cellular. Also fix the Cellular settings status text, which said "Connecting..." for a flag that only tracks radio enable/disable, and add the seven cellular terms that were missing from the translation catalogs. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> * apply review comments * fix lints * update debug doc * fix style inconsistencies --------- Co-authored-by: Yechiel Worenklein <[email protected]> Co-authored-by: Claude Opus 5 (1M context) <[email protected]> Co-authored-by: bbedward <[email protected]>
DMS Quickshell Interface
QML-based desktop shell interface for DankMaterialShell providing panels, widgets, and overlays.
See root README for project overview and installation.
Architecture
Modular QML Structure
Modules/- UI components (panels, widgets, overlays)Services/- System integration singletons (audio, network, bluetooth)Widgets/- Reusable UI controlsCommon/- Shared resources and themes
Technology Stack
- Quickshell - QML-based shell framework
- Qt/QtQuick - UI rendering and controls
- Material Design 3 - Design system and theming
Development
Run the shell:
quickshell -p quickshell/
Code formatting:
qmlfmt -t 4 -i 4 -b 250 -w path/to/file.qml
make lint-qml # Run from repo root; requires quickshell/.qmlls.ini (generated by `qs -p quickshell/`)
# Uses Qt 6 qmllint. Override path with QMLLINT=/path/to/qmllint if needed.
# Auto-detects `qmllint6`, Fedora's `qmllint-qt6`, `/usr/lib/qt6/bin/qmllint`, then `qmllint`.
Components
Panels & Bars
Modules/TopBar/- Multi-monitor status bars with workspace switchingModules/DankBar/- Customizable widget bar with plugin supportModules/Dock/- Application dock with window management
System Controls
Modules/ControlCenter/- WiFi, Bluetooth, audio, display settingsModules/Notifications/- Notification center with popups
Overlays
Modules/Spotlight/- Application and file launcherModules/Overview/- Workspace overviewModules/Lock/- Screen lock system
Utilities
Modules/ProcessList/- System monitoring and process managementModules/Calendar/- Calendar widget with event syncModules/Weather/- Weather display
Services
Singletons providing system integration:
Media & Audio
AudioService- PipeWire/PulseAudio volume and device controlMprisController- Media player integration
Network
NetworkService- NetworkManager WiFi controlBluetoothService- BlueZ Bluetooth management
Display
DisplayService- Brightness control and night modeWallpaperService- Wallpaper management and effects
System
BatteryService- Battery status and power profilesIdleService- Idle detection and inhibit locksClipboardService- Clipboard history with imagesDgopService- System metrics (CPU, RAM, GPU)
Integration
NiriService- Niri workspace integrationHyprlandService- Hyprland workspace integrationPluginService- Plugin discovery and lifecycle
Widgets
Reusable Material Design 3 components in Widgets/:
DankIcon- Icon component with Material fontDankSlider- Enhanced slider with animationsDankToggle- Toggle switch componentDankTabBar- Tab bar implementationDankGridView- Grid layout with adaptive columnsDankListView- Scrollable list viewDankTextField- Text input with validationDankDropdown- Dropdown selectionDankPopout- Base for overlay componentsStateLayer- Material interaction states
Theming
Dynamic Color Schemes
Wallpaper-based theming using matugen:
import qs.Common
Rectangle {
color: Theme.container
border.color: Theme.outline
}
Theme singleton provides Material Design 3 color system, spacing, fonts, and elevation.
Application Themes
Templates in scripts/templates/ generate themes for:
- GTK 3/4
- Qt5/Qt6
- Alacritty, Kitty, Ghostty, Foot, Wezterm terminals
- Neovim
- VSCode/VSCodium
- Firefox
Multi-Monitor Support
Per-monitor panel instances using Quickshell Variants:
Variants {
model: Quickshell.screens
PanelWindow {
screen: modelData
// Per-screen configuration
}
}
Workspace switchers adapt to compositor (Niri/Hyprland).
Plugin System
External plugins in ~/.config/DankMaterialShell/plugins/:
Widget plugins - UI components in DankBar Daemon plugins - Background processes without UI
Plugin manifest (plugin.json):
{
"id": "pluginId",
"name": "Plugin Name",
"version": "1.0.0",
"type": "widget",
"component": "./Widget.qml",
"settings": "./Settings.qml",
"permissions": ["settings_read", "settings_write"]
}
Plugins access pluginService for persistent data:
pluginService.savePluginData("pluginId", "key", value)
pluginService.loadPluginData("pluginId", "key", defaultValue)
IPC Integration
Backend IPC socket communication:
import Quickshell.Io
Process {
command: ["dms", "ipc", "call", "spotlight", "toggle"]
running: true
}
Common IPC commands exposed through services for reactive property bindings.
Code Conventions
Component Structure:
import QtQuick
import Quickshell
import qs.Common
import qs.Services
Item {
id: root
property type name: value
signal customSignal(type param)
Component { /* children */ }
}
Services (Singletons):
import QtQuick
import Quickshell
pragma Singleton
pragma ComponentBehavior: Bound
Singleton {
id: root
property bool featureAvailable: false
property type currentValue: defaultValue
function performAction(param) { /* implementation */ }
}
Guidelines:
- Use
Theme.propertyNamefor consistent styling - Bind directly to service properties for reactivity
- Use
DankIconfor all icons - Implement feature detection and graceful degradation
- 4-space indentation, no unnecessary comments
Translation
Internationalization using POEditor:
export POEDITOR_API_TOKEN="token"
export POEDITOR_PROJECT_ID="id"
python3 scripts/i18nsync.py sync
Pre-commit hook checks translation sync status.
License
MIT License - See LICENSE for details.