1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-30 16:32:50 -05:00

VPN Popout: match Battery popout styling (width, shadow rings, header close button, container colors); fix detail sizing

This commit is contained in:
Jon Rogers
2025-08-30 15:07:49 -04:00
parent 04ce154d36
commit b9c4822c27
2 changed files with 221 additions and 172 deletions

View File

@@ -1,168 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Rectangle {
id: root
implicitHeight: 220
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.6)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1
Column {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
Row {
spacing: Theme.spacingS
width: parent.width
StyledText {
text: VpnService.connected ? ("Active: " + (VpnService.activeName || "VPN")) : "Active: None"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
Item { width: 10; height: 1 }
Rectangle {
height: 28
radius: 14
color: toggleMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
// Only show quick connect when not connected
visible: !VpnService.connected && VpnService.profiles.length > 0
width: 100
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon { name: "link"; size: Theme.fontSizeSmall; color: Theme.surfaceText }
StyledText { text: "Connect"; font.pixelSize: Theme.fontSizeSmall; color: Theme.surfaceText; font.weight: Font.Medium }
}
MouseArea {
id: toggleMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: VpnService.toggle()
}
}
}
Rectangle { height: 1; width: parent.width; color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) }
DankFlickable {
width: parent.width
height: 160
contentHeight: listCol.height
Column {
id: listCol
width: parent.width
spacing: Theme.spacingXS
Item {
width: parent.width
height: VpnService.profiles.length === 0 ? 120 : 0
visible: height > 0
Column {
anchors.centerIn: parent
spacing: Theme.spacingS
DankIcon { name: "playlist_remove"; size: 36; color: Theme.surfaceVariantText; anchors.horizontalCenter: parent.horizontalCenter }
StyledText { text: "No VPN profiles found"; font.pixelSize: Theme.fontSizeMedium; color: Theme.surfaceVariantText; anchors.horizontalCenter: parent.horizontalCenter }
StyledText { text: "Add a VPN in NetworkManager"; font.pixelSize: Theme.fontSizeSmall; color: Theme.surfaceVariantText; anchors.horizontalCenter: parent.horizontalCenter }
}
}
Repeater {
model: VpnService.profiles
delegate: Rectangle {
required property var modelData
width: parent ? parent.width : 300
height: 40
radius: Theme.cornerRadius
color: rowMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
border.width: 1
border.color: modelData.uuid === VpnService.activeUuid ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
DankIcon {
name: modelData.uuid === VpnService.activeUuid ? "vpn_lock" : "vpn_key_off"
size: Theme.iconSize - 4
color: modelData.uuid === VpnService.activeUuid ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: modelData.name
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
Layout.alignment: Qt.AlignVCenter
}
Item { Layout.fillWidth: true; height: 1 }
Rectangle {
height: 28
radius: 14
color: actMouse.containsMouse
? (modelData.uuid === VpnService.activeUuid
? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12))
: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
width: 100
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
StyledText {
anchors.centerIn: parent
text: modelData.uuid === VpnService.activeUuid ? "Disconnect" : "Connect"
font.pixelSize: Theme.fontSizeSmall
color: modelData.uuid === VpnService.activeUuid ? Theme.error : Theme.surfaceText
font.weight: Font.Medium
}
MouseArea {
id: actMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData.uuid === VpnService.activeUuid) {
VpnService.disconnect(modelData.uuid)
} else {
VpnService.connect(modelData.uuid)
}
}
}
}
}
MouseArea {
id: rowMouse
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
}
}
}
Item { height: 1; width: 1 }
}
}
}
}

View File

@@ -1,12 +1,13 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Widgets import Quickshell.Widgets
import qs.Widgets import qs.Widgets
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Modules.ControlCenter.Details 1.0 as Details // No external details import; content inlined for consistency
DankPopout { DankPopout {
id: root id: root
@@ -22,7 +23,7 @@ DankPopout {
triggerScreen = screen triggerScreen = screen
} }
popupWidth: 360 popupWidth: 400
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 260 popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 260
triggerX: Screen.width - 400 - Theme.spacingL triggerX: Screen.width - 400 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingS triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingS
@@ -52,6 +53,36 @@ DankPopout {
} }
} }
// Outer subtle shadow rings to match BatteryPopout
Rectangle {
anchors.fill: parent
anchors.margins: -3
color: "transparent"
radius: parent.radius + 3
border.color: Qt.rgba(0, 0, 0, 0.05)
border.width: 1
z: -3
}
Rectangle {
anchors.fill: parent
anchors.margins: -2
color: "transparent"
radius: parent.radius + 2
border.color: Theme.shadowMedium
border.width: 1
z: -2
}
Rectangle {
anchors.fill: parent
color: "transparent"
border.color: Theme.outlineStrong
border.width: 1
radius: parent.radius
z: -1
}
Column { Column {
id: contentColumn id: contentColumn
anchors.left: parent.left anchors.left: parent.left
@@ -62,7 +93,7 @@ DankPopout {
Item { Item {
width: parent.width width: parent.width
height: 28 height: 32
StyledText { StyledText {
text: "VPN Connections" text: "VPN Connections"
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
@@ -70,10 +101,196 @@ DankPopout {
font.weight: Font.Medium font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
// Close button (matches BatteryPopout)
Rectangle {
width: 32
height: 32
radius: 16
color: closeArea.containsMouse ? Theme.errorHover : "transparent"
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
DankIcon {
anchors.centerIn: parent
name: "close"
size: Theme.iconSize - 4
color: closeArea.containsMouse ? Theme.error : Theme.surfaceText
} }
Details.VpnDetail { MouseArea {
id: closeArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: root.close()
}
}
}
// Inlined VPN details
Rectangle {
id: vpnDetail
width: parent.width width: parent.width
implicitHeight: detailsColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.4)
border.color: Theme.outlineMedium
border.width: 1
Column {
id: detailsColumn
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
Row {
spacing: Theme.spacingS
width: parent.width
StyledText {
text: VpnService.connected ? ("Active: " + (VpnService.activeName || "VPN")) : "Active: None"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
Item { width: 10; height: 1 }
// Quick connect when not connected
Rectangle {
height: 28
radius: 14
color: quickBtnArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
visible: !VpnService.connected && VpnService.profiles.length > 0
width: 100
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
DankIcon { name: "link"; size: Theme.fontSizeSmall; color: Theme.surfaceText }
StyledText { text: "Connect"; font.pixelSize: Theme.fontSizeSmall; color: Theme.surfaceText; font.weight: Font.Medium }
}
MouseArea {
id: quickBtnArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: VpnService.toggle()
}
}
}
Rectangle { height: 1; width: parent.width; color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) }
DankFlickable {
width: parent.width
height: 160
contentHeight: listCol.height
Column {
id: listCol
width: parent.width
spacing: Theme.spacingXS
Item {
width: parent.width
height: VpnService.profiles.length === 0 ? 120 : 0
visible: height > 0
Column {
anchors.centerIn: parent
spacing: Theme.spacingS
DankIcon { name: "playlist_remove"; size: 36; color: Theme.surfaceVariantText; anchors.horizontalCenter: parent.horizontalCenter }
StyledText { text: "No VPN profiles found"; font.pixelSize: Theme.fontSizeMedium; color: Theme.surfaceVariantText; anchors.horizontalCenter: parent.horizontalCenter }
StyledText { text: "Add a VPN in NetworkManager"; font.pixelSize: Theme.fontSizeSmall; color: Theme.surfaceVariantText; anchors.horizontalCenter: parent.horizontalCenter }
}
}
Repeater {
model: VpnService.profiles
delegate: Rectangle {
required property var modelData
width: parent ? parent.width : 300
height: 40
radius: Theme.cornerRadius
color: rowMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
border.width: 1
border.color: modelData.uuid === VpnService.activeUuid ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
DankIcon {
name: modelData.uuid === VpnService.activeUuid ? "vpn_lock" : "vpn_key_off"
size: Theme.iconSize - 4
color: modelData.uuid === VpnService.activeUuid ? Theme.primary : Theme.surfaceText
Layout.alignment: Qt.AlignVCenter
}
StyledText {
text: modelData.name
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
Layout.alignment: Qt.AlignVCenter
}
Item { Layout.fillWidth: true; height: 1 }
Rectangle {
height: 28
radius: 14
color: actMouse.containsMouse
? (modelData.uuid === VpnService.activeUuid
? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12))
: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5)
width: 100
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
z: 10
StyledText {
anchors.centerIn: parent
text: modelData.uuid === VpnService.activeUuid ? "Disconnect" : "Connect"
font.pixelSize: Theme.fontSizeSmall
color: modelData.uuid === VpnService.activeUuid ? Theme.error : Theme.surfaceText
font.weight: Font.Medium
}
MouseArea {
id: actMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData.uuid === VpnService.activeUuid) {
VpnService.disconnect(modelData.uuid)
} else {
VpnService.connect(modelData.uuid)
}
}
}
}
}
MouseArea {
id: rowMouse
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
z: -1
}
}
}
Item { height: 1; width: 1 }
}
}
}
} }
} }
} }