mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-10 07:25:37 -05:00
plugins: add pillClickAction + PopoutService
This commit is contained in:
285
PLUGINS/POPOUT_SERVICE.md
Normal file
285
PLUGINS/POPOUT_SERVICE.md
Normal file
@@ -0,0 +1,285 @@
|
||||
# PopoutService for Plugins
|
||||
|
||||
## Overview
|
||||
|
||||
The `PopoutService` singleton provides plugins with access to all DankMaterialShell popouts and modals. It's automatically injected into plugin widgets and daemons, enabling them to control shell UI elements.
|
||||
|
||||
## Automatic Injection
|
||||
|
||||
The `popoutService` property is automatically injected into:
|
||||
- Widget plugins (loaded in DankBar)
|
||||
- Daemon plugins (background services)
|
||||
- Plugin settings components
|
||||
|
||||
**Required**: Declare the property in your plugin component:
|
||||
|
||||
```qml
|
||||
property var popoutService: null
|
||||
```
|
||||
|
||||
**Note**: Without this declaration, the service cannot be injected and you'll see errors like `Cannot assign to non-existent property "popoutService"`
|
||||
|
||||
## API Reference
|
||||
|
||||
### Popouts (DankPopout-based)
|
||||
|
||||
| Component | Open | Close | Toggle |
|
||||
|-----------|------|-------|--------|
|
||||
| Control Center | `openControlCenter()` | `closeControlCenter()` | `toggleControlCenter()` |
|
||||
| Notification Center | `openNotificationCenter()` | `closeNotificationCenter()` | `toggleNotificationCenter()` |
|
||||
| App Drawer | `openAppDrawer()` | `closeAppDrawer()` | `toggleAppDrawer()` |
|
||||
| Process List | `openProcessList()` | `closeProcessList()` | `toggleProcessList()` |
|
||||
| DankDash | `openDankDash(tab)` | `closeDankDash()` | `toggleDankDash(tab)` |
|
||||
| Battery | `openBattery()` | `closeBattery()` | `toggleBattery()` |
|
||||
| VPN | `openVpn()` | `closeVpn()` | `toggleVpn()` |
|
||||
| System Update | `openSystemUpdate()` | `closeSystemUpdate()` | `toggleSystemUpdate()` |
|
||||
|
||||
### Modals (DankModal-based)
|
||||
|
||||
| Modal | Show | Hide | Notes |
|
||||
|-------|------|------|-------|
|
||||
| Settings | `openSettings()` | `closeSettings()` | Full settings interface |
|
||||
| Clipboard History | `openClipboardHistory()` | `closeClipboardHistory()` | Cliphist integration |
|
||||
| Spotlight | `openSpotlight()` | `closeSpotlight()` | Command launcher |
|
||||
| Power Menu | `openPowerMenu()` | `closePowerMenu()` | Also has `togglePowerMenu()` |
|
||||
| Process List Modal | `showProcessListModal()` | `hideProcessListModal()` | Fullscreen version, has `toggleProcessListModal()` |
|
||||
| Color Picker | `showColorPicker()` | `hideColorPicker()` | Theme color selection |
|
||||
| Notification | `showNotificationModal()` | `hideNotificationModal()` | Notification details |
|
||||
| WiFi Password | `showWifiPasswordModal()` | `hideWifiPasswordModal()` | Network authentication |
|
||||
| Network Info | `showNetworkInfoModal()` | `hideNetworkInfoModal()` | Network details |
|
||||
|
||||
### Slideouts
|
||||
|
||||
| Component | Open | Close | Toggle |
|
||||
|-----------|------|-------|--------|
|
||||
| Notepad | `openNotepad()` | `closeNotepad()` | `toggleNotepad()` |
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Simple Widget with Popout Control
|
||||
|
||||
```qml
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property var popoutService: null
|
||||
|
||||
width: 100
|
||||
height: 30
|
||||
color: Theme.surfaceContainerHigh
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: popoutService?.toggleControlCenter()
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: "Settings"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Daemon with Event-Driven Popouts
|
||||
|
||||
```qml
|
||||
import QtQuick
|
||||
import qs.Services
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var popoutService: null
|
||||
|
||||
Connections {
|
||||
target: NotificationService
|
||||
|
||||
function onNotificationReceived(notification) {
|
||||
if (notification.urgency === "critical") {
|
||||
popoutService?.openNotificationCenter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: BatteryService
|
||||
|
||||
function onPercentageChanged() {
|
||||
if (BatteryService.percentage < 10 && !BatteryService.isCharging) {
|
||||
popoutService?.openBattery()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Widget with Multiple Popout Options
|
||||
|
||||
```qml
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Common
|
||||
|
||||
Rectangle {
|
||||
property var popoutService: null
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onClicked: (mouse) => {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
contextMenu.popup()
|
||||
} else {
|
||||
popoutService?.toggleControlCenter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: contextMenu
|
||||
|
||||
MenuItem {
|
||||
text: "Settings"
|
||||
onClicked: popoutService?.openSettings()
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Notifications"
|
||||
onClicked: popoutService?.toggleNotificationCenter()
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Power Menu"
|
||||
onClicked: popoutService?.openPowerMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Service Architecture
|
||||
|
||||
`PopoutService` is a singleton that holds references to popout instances:
|
||||
|
||||
```qml
|
||||
// Services/PopoutService.qml
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property var controlCenterPopout: null
|
||||
property var notificationCenterPopout: null
|
||||
// ... other popout references
|
||||
|
||||
function toggleControlCenter() {
|
||||
controlCenterPopout?.toggle()
|
||||
}
|
||||
// ... other control functions
|
||||
}
|
||||
```
|
||||
|
||||
### Reference Assignment
|
||||
|
||||
References are assigned in `DMSShell.qml` when popouts are loaded:
|
||||
|
||||
```qml
|
||||
LazyLoader {
|
||||
ControlCenterPopout {
|
||||
id: controlCenterPopout
|
||||
|
||||
Component.onCompleted: {
|
||||
PopoutService.controlCenterPopout = controlCenterPopout
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Plugin Injection
|
||||
|
||||
The service is injected in three locations:
|
||||
|
||||
1. **DMSShell.qml** (daemon plugins):
|
||||
```qml
|
||||
Instantiator {
|
||||
delegate: Loader {
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
item.popoutService = PopoutService
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **WidgetHost.qml** (widget plugins):
|
||||
```qml
|
||||
onLoaded: {
|
||||
if (item.popoutService !== undefined) {
|
||||
item.popoutService = PopoutService
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **CenterSection.qml** (center widgets):
|
||||
```qml
|
||||
onLoaded: {
|
||||
if (item.popoutService !== undefined) {
|
||||
item.popoutService = PopoutService
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. **PluginsTab.qml** (settings):
|
||||
```qml
|
||||
onLoaded: {
|
||||
if (item && typeof PopoutService !== "undefined") {
|
||||
item.popoutService = PopoutService
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Optional Chaining**: Always use `?.` to handle null cases
|
||||
```qml
|
||||
popoutService?.toggleControlCenter()
|
||||
```
|
||||
|
||||
2. **Check Availability**: Some popouts may not be available
|
||||
```qml
|
||||
if (popoutService && popoutService.controlCenterPopout) {
|
||||
popoutService.toggleControlCenter()
|
||||
}
|
||||
```
|
||||
|
||||
3. **Lazy Loading**: First access may activate lazy loaders - this is normal
|
||||
|
||||
4. **Feature Detection**: Some popouts require specific features
|
||||
```qml
|
||||
if (BatteryService.batteryAvailable) {
|
||||
popoutService?.openBattery()
|
||||
}
|
||||
```
|
||||
|
||||
5. **User Intent**: Only trigger popouts based on user actions or critical events
|
||||
|
||||
## Example Plugin
|
||||
|
||||
See `PLUGINS/PopoutControlExample/` for a complete working example that demonstrates:
|
||||
- Widget creation with popout controls
|
||||
- Menu-based popout selection
|
||||
- Proper service usage
|
||||
- Error handling
|
||||
|
||||
## Limitations
|
||||
|
||||
- Popouts are shared across all plugins - avoid conflicts
|
||||
- Some popouts may be compositor or feature-dependent
|
||||
- Lazy-loaded popouts need activation before use
|
||||
- Multi-monitor considerations apply to positioned popouts
|
||||
Reference in New Issue
Block a user