1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-26 22:42:50 -05:00

Add NetworkManager VPN integration: VpnService + Control Center detail; move to TopBar VPN widget with popout; fix logs and parsing; default top bar item 'vpn' added; minor layout fixes

This commit is contained in:
Jon Rogers
2025-08-30 13:57:47 -04:00
parent e55c97185a
commit 952e5604d9
8 changed files with 595 additions and 1 deletions

View File

@@ -339,6 +339,8 @@ PanelWindow {
return DgopService.dgopAvailable
case "keyboard_layout_name":
return true
case "vpn":
return true
default:
return false
}
@@ -390,6 +392,8 @@ PanelWindow {
return networkComponent
case "keyboard_layout_name":
return keyboardLayoutNameComponent
case "vpn":
return vpnComponent
default:
return null
}
@@ -1022,6 +1026,35 @@ PanelWindow {
}
}
Component {
id: vpnComponent
Vpn {
widgetHeight: root.widgetHeight
barHeight: root.effectiveBarHeight
section: {
if (parent && parent.parent === leftSection)
return "left"
if (parent && parent.parent === rightSection)
return "right"
if (parent && parent.parent === centerSection)
return "center"
return "right"
}
popupTarget: {
vpnPopoutLoader.active = true
return vpnPopoutLoader.item
}
parentScreen: root.screen
onToggleVpnPopup: {
vpnPopoutLoader.active = true
if (vpnPopoutLoader.item) {
vpnPopoutLoader.item.toggle()
}
}
}
}
Component {
id: controlCenterButtonComponent

106
Modules/TopBar/Vpn.qml Normal file
View File

@@ -0,0 +1,106 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
// Passed in by TopBar
property int widgetHeight: 28
property int barHeight: 32
property string section: "right"
property var popupTarget: null
property var parentScreen: null
signal toggleVpnPopup()
width: Math.max(24, contentRow.implicitWidth + Theme.spacingXS * 2)
height: widgetHeight
Row {
id: contentRow
anchors.fill: parent
anchors.margins: 0
spacing: Theme.spacingXS
Rectangle {
anchors.fill: parent
radius: 6
color: "transparent"
}
DankIcon {
id: icon
name: VpnService.isBusy ? "sync" : (VpnService.connected ? "vpn_lock" : "vpn_key_off")
size: Theme.iconSize - 6
color: VpnService.connected ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
RotationAnimation on rotation {
running: VpnService.isBusy
loops: Animation.Infinite
from: 0
to: 360
duration: 900
}
}
Text {
id: label
text: VpnService.connected ? (VpnService.activeName || "VPN") : "VPN"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: VpnService.connected ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
visible: true
elide: Text.ElideRight
}
}
MouseArea {
id: clickArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: {
if (popupTarget && popupTarget.setTriggerPosition) {
var globalPos = mapToGlobal(0, 0)
var currentScreen = parentScreen || Screen
var screenX = currentScreen.x || 0
var relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen)
}
root.toggleVpnPopup()
}
}
Rectangle {
id: tooltip
width: Math.max(120, tooltipText.contentWidth + Theme.spacingM * 2)
height: tooltipText.contentHeight + Theme.spacingS * 2
radius: Theme.cornerRadius
color: Theme.surfaceContainer
border.color: Theme.surfaceVariantAlpha
border.width: 1
visible: clickArea.containsMouse && !(popupTarget && popupTarget.shouldBeVisible)
anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingS
anchors.horizontalCenter: parent.horizontalCenter
opacity: clickArea.containsMouse ? 1 : 0
Text {
id: tooltipText
anchors.centerIn: parent
text: VpnService.connected ? ("VPN Connected • " + (VpnService.activeName || "")) : "VPN Disconnected"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
}
Behavior on opacity {
NumberAnimation { duration: Theme.shortDuration; easing.type: Theme.standardEasing }
}
}
}

View File

@@ -0,0 +1,81 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Widgets
import qs.Widgets
import qs.Common
import qs.Services
import qs.Modules.ControlCenter.Details 1.0 as Details
DankPopout {
id: root
property string triggerSection: "right"
property var triggerScreen: null
function setTriggerPosition(x, y, width, section, screen) {
triggerX = x
triggerY = y
triggerWidth = width
triggerSection = section
triggerScreen = screen
}
popupWidth: 420
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 260
triggerX: Screen.width - 400 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingS
triggerWidth: 70
positioning: "center"
WlrLayershell.namespace: "quickshell-vpn"
screen: triggerScreen
shouldBeVisible: false
visible: shouldBeVisible
content: Component {
Rectangle {
id: content
implicitHeight: contentColumn.height + Theme.spacingL * 2
color: Theme.popupBackground()
radius: Theme.cornerRadius
border.color: Theme.outlineMedium
border.width: 1
antialiasing: true
smooth: true
focus: true
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Escape) {
root.close()
event.accepted = true
}
}
Column {
id: contentColumn
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Item {
width: parent.width
height: 28
StyledText {
text: "VPN"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Details.VpnDetail {
width: parent.width
}
}
}
}
}