diff options
Diffstat (limited to 'raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Widgets/VpnProfileDelegate.qml')
| -rw-r--r-- | raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Widgets/VpnProfileDelegate.qml | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Widgets/VpnProfileDelegate.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Widgets/VpnProfileDelegate.qml new file mode 100644 index 0000000..e859456 --- /dev/null +++ b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Widgets/VpnProfileDelegate.qml @@ -0,0 +1,287 @@ +import QtQuick +import qs.Common +import qs.Services +import qs.Widgets + +Rectangle { + id: root + + LayoutMirroring.enabled: I18n.isRtl + LayoutMirroring.childrenInherit: true + + required property var profile + property bool isExpanded: false + + signal toggleExpand + signal deleteRequested + + readonly property bool isActive: DMSNetworkService.activeUuids?.includes(profile?.uuid) ?? false + readonly property bool isHovered: rowArea.containsMouse || expandBtn.containsMouse || deleteBtn.containsMouse + readonly property var configData: isExpanded ? VPNService.editConfig : null + readonly property var configFields: buildConfigFields() + + height: isExpanded ? 46 + expandedContent.height : 46 + radius: Theme.cornerRadius + color: isHovered ? Theme.primaryHoverLight : (isActive ? Theme.primaryPressed : Theme.surfaceLight) + border.width: isActive ? 2 : 1 + border.color: isActive ? Theme.primary : Theme.outlineLight + opacity: DMSNetworkService.isBusy ? 0.5 : 1.0 + clip: true + + function buildConfigFields() { + if (!configData) + return []; + const fields = []; + const data = configData.data || {}; + if (data.remote) + fields.push({ + "key": "server", + "label": I18n.tr("Server"), + "value": data.remote + }); + if (configData.username || data.username) + fields.push({ + "key": "user", + "label": I18n.tr("Username"), + "value": configData.username || data.username + }); + if (data.cipher) + fields.push({ + "key": "cipher", + "label": I18n.tr("Cipher"), + "value": data.cipher + }); + if (data.auth) + fields.push({ + "key": "auth", + "label": I18n.tr("Auth"), + "value": data.auth + }); + if (data["proto-tcp"] === "yes" || data["proto-tcp"] === "no") + fields.push({ + "key": "proto", + "label": I18n.tr("Protocol"), + "value": data["proto-tcp"] === "yes" ? "TCP" : "UDP" + }); + if (data["tunnel-mtu"]) + fields.push({ + "key": "mtu", + "label": I18n.tr("MTU"), + "value": data["tunnel-mtu"] + }); + if (data["connection-type"]) + fields.push({ + "key": "conntype", + "label": I18n.tr("Auth Type"), + "value": data["connection-type"] + }); + return fields; + } + + Behavior on height { + NumberAnimation { + duration: 150 + easing.type: Easing.OutQuad + } + } + + MouseArea { + id: rowArea + anchors.fill: parent + hoverEnabled: true + cursorShape: DMSNetworkService.isBusy ? Qt.BusyCursor : Qt.PointingHandCursor + enabled: !DMSNetworkService.isBusy + onClicked: DMSNetworkService.toggle(profile.uuid) + } + + Column { + anchors.fill: parent + anchors.margins: Theme.spacingS + spacing: Theme.spacingS + + Row { + width: parent.width + height: 46 - Theme.spacingS * 2 + spacing: Theme.spacingS + + DankIcon { + name: isActive ? "vpn_lock" : "vpn_key_off" + size: 20 + color: isActive ? Theme.primary : Theme.surfaceText + anchors.verticalCenter: parent.verticalCenter + } + + Column { + spacing: 1 + anchors.verticalCenter: parent.verticalCenter + width: parent.width - 20 - 28 - 28 - Theme.spacingS * 4 + + StyledText { + text: profile?.name ?? "" + font.pixelSize: Theme.fontSizeMedium + color: isActive ? Theme.primary : Theme.surfaceText + elide: Text.ElideRight + wrapMode: Text.NoWrap + width: parent.width + horizontalAlignment: Text.AlignLeft + } + + StyledText { + text: VPNService.getVpnTypeFromProfile(profile) + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + wrapMode: Text.NoWrap + width: parent.width + elide: Text.ElideRight + horizontalAlignment: Text.AlignLeft + } + } + + Item { + width: Theme.spacingXS + height: 1 + } + + Rectangle { + width: 28 + height: 28 + radius: 14 + color: expandBtn.containsMouse ? Theme.surfacePressed : "transparent" + anchors.verticalCenter: parent.verticalCenter + + DankIcon { + anchors.centerIn: parent + name: isExpanded ? "expand_less" : "expand_more" + size: 18 + color: Theme.surfaceText + } + + MouseArea { + id: expandBtn + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: root.toggleExpand() + } + } + + Rectangle { + width: 28 + height: 28 + radius: 14 + color: deleteBtn.containsMouse ? Theme.errorHover : "transparent" + anchors.verticalCenter: parent.verticalCenter + + DankIcon { + anchors.centerIn: parent + name: "delete" + size: 18 + color: deleteBtn.containsMouse ? Theme.error : Theme.surfaceVariantText + } + + MouseArea { + id: deleteBtn + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: root.deleteRequested() + } + } + } + + Column { + id: expandedContent + width: parent.width + spacing: Theme.spacingXS + visible: isExpanded + + Rectangle { + width: parent.width + height: 1 + color: Theme.outlineLight + } + + Item { + width: parent.width + height: VPNService.configLoading ? 40 : 0 + visible: VPNService.configLoading + + Row { + anchors.centerIn: parent + spacing: Theme.spacingS + + DankIcon { + name: "sync" + size: 16 + color: Theme.surfaceVariantText + } + + StyledText { + text: I18n.tr("Loading...") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + } + } + } + + Flow { + width: parent.width + spacing: Theme.spacingXS + visible: !VPNService.configLoading && configData + + Repeater { + model: configFields + + delegate: Rectangle { + required property var modelData + + width: fieldContent.width + Theme.spacingM * 2 + height: 32 + radius: Theme.cornerRadius - 2 + color: Theme.surfaceLight + border.width: 1 + border.color: Theme.outlineLight + + Row { + id: fieldContent + anchors.centerIn: parent + spacing: Theme.spacingXS + + StyledText { + text: modelData.label + ":" + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceVariantText + anchors.verticalCenter: parent.verticalCenter + } + + StyledText { + text: modelData.value + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Medium + anchors.verticalCenter: parent.verticalCenter + } + } + } + } + } + + DankToggle { + width: parent.width + text: I18n.tr("Autoconnect") + checked: configData ? (configData.autoconnect || false) : false + visible: !VPNService.configLoading && configData !== null + onToggled: checked => { + VPNService.updateConfig(profile.uuid, { + autoconnect: checked + }); + } + } + + Item { + width: 1 + height: Theme.spacingXS + } + } + } +} |