diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details')
8 files changed, 0 insertions, 3817 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/AudioInputDetail.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/AudioInputDetail.qml deleted file mode 100644 index 8fc2d46..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/AudioInputDetail.qml +++ /dev/null @@ -1,363 +0,0 @@ -import QtQuick -import Quickshell -import Quickshell.Services.Pipewire -import qs.Common -import qs.Services -import qs.Widgets - -Rectangle { - id: root - - LayoutMirroring.enabled: I18n.isRtl - LayoutMirroring.childrenInherit: true - - property bool hasInputVolumeSliderInCC: { - const widgets = SettingsData.controlCenterWidgets || []; - return widgets.some(widget => widget.id === "inputVolumeSlider"); - } - - implicitHeight: headerRow.height + (hasInputVolumeSliderInCC ? 0 : volumeSlider.height) + audioContent.height + Theme.spacingM - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) - border.width: 0 - - Row { - id: headerRow - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.leftMargin: Theme.spacingM - anchors.rightMargin: Theme.spacingM - anchors.topMargin: Theme.spacingS - height: 40 - - StyledText { - id: headerText - text: I18n.tr("Input Devices") - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium - anchors.verticalCenter: parent.verticalCenter - } - - Item { - height: 1 - width: parent.width - headerText.width - settingsButton.width - } - - DankActionButton { - id: settingsButton - anchors.verticalCenter: parent.verticalCenter - iconName: "settings" - buttonSize: 28 - iconSize: 16 - iconColor: Theme.surfaceVariantText - onClicked: { - PopoutService.closeControlCenter(); - PopoutService.openSettingsWithTab("audio"); - } - } - } - - Row { - id: volumeSlider - anchors.left: parent.left - anchors.right: parent.right - anchors.top: headerRow.bottom - anchors.leftMargin: Theme.spacingM - anchors.rightMargin: Theme.spacingM - anchors.topMargin: Theme.spacingXS - height: 35 - spacing: 0 - visible: !hasInputVolumeSliderInCC - - Rectangle { - width: Theme.iconSize + Theme.spacingS * 2 - height: Theme.iconSize + Theme.spacingS * 2 - anchors.verticalCenter: parent.verticalCenter - radius: (Theme.iconSize + Theme.spacingS * 2) / 2 - color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" - - DankRipple { - id: iconRipple - cornerRadius: parent.radius - } - - MouseArea { - id: iconArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y) - onClicked: { - if (AudioService.source && AudioService.source.audio) { - AudioService.source.audio.muted = !AudioService.source.audio.muted; - } - } - } - - DankIcon { - anchors.centerIn: parent - name: { - if (!AudioService.source || !AudioService.source.audio) - return "mic_off"; - let muted = AudioService.source.audio.muted; - return muted ? "mic_off" : "mic"; - } - size: Theme.iconSize - color: AudioService.source && AudioService.source.audio && !AudioService.source.audio.muted && AudioService.source.audio.volume > 0 ? Theme.primary : Theme.surfaceText - } - } - - DankSlider { - readonly property real actualVolumePercent: AudioService.source && AudioService.source.audio ? Math.round(AudioService.source.audio.volume * 100) : 0 - - anchors.verticalCenter: parent.verticalCenter - width: parent.width - (Theme.iconSize + Theme.spacingS * 2) - enabled: AudioService.source && AudioService.source.audio - minimum: 0 - maximum: 100 - value: AudioService.source && AudioService.source.audio ? Math.min(100, Math.round(AudioService.source.audio.volume * 100)) : 0 - showValue: true - unit: "%" - valueOverride: actualVolumePercent - thumbOutlineColor: Theme.surfaceVariant - - onSliderValueChanged: function (newValue) { - if (AudioService.source && AudioService.source.audio) { - AudioService.source.audio.volume = newValue / 100; - if (newValue > 0 && AudioService.source.audio.muted) { - AudioService.source.audio.muted = false; - } - } - } - } - } - - DankFlickable { - id: audioContent - anchors.top: hasInputVolumeSliderInCC ? headerRow.bottom : volumeSlider.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: Theme.spacingM - anchors.topMargin: hasInputVolumeSliderInCC ? Theme.spacingM : Theme.spacingS - contentHeight: audioColumn.height - clip: true - - property int maxPinnedInputs: 3 - - function normalizePinList(value) { - if (Array.isArray(value)) - return value.filter(v => v); - if (typeof value === "string" && value.length > 0) - return [value]; - return []; - } - - function getPinnedInputs() { - const pins = SettingsData.audioInputDevicePins || {}; - return normalizePinList(pins["preferredInput"]); - } - - Column { - id: audioColumn - width: parent.width - spacing: Theme.spacingS - - Repeater { - model: ScriptModel { - values: { - const hidden = SessionData.hiddenInputDeviceNames ?? []; - const nodes = Pipewire.nodes.values.filter(node => { - if (!node.audio || node.isSink || node.isStream) - return false; - return !hidden.includes(node.name); - }); - const pinnedList = audioContent.getPinnedInputs(); - - let sorted = [...nodes]; - sorted.sort((a, b) => { - // Pinned device first - const aPinnedIndex = pinnedList.indexOf(a.name); - const bPinnedIndex = pinnedList.indexOf(b.name); - if (aPinnedIndex !== -1 || bPinnedIndex !== -1) { - if (aPinnedIndex === -1) - return 1; - if (bPinnedIndex === -1) - return -1; - return aPinnedIndex - bPinnedIndex; - } - // Then active device - if (a === AudioService.source && b !== AudioService.source) - return -1; - if (b === AudioService.source && a !== AudioService.source) - return 1; - return 0; - }); - return sorted; - } - } - - delegate: Rectangle { - required property var modelData - required property int index - - width: parent.width - height: 50 - radius: Theme.cornerRadius - color: deviceMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight - border.color: modelData === AudioService.source ? Theme.primary : Theme.outlineLight - border.width: modelData === AudioService.source ? 2 : 1 - - Row { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Theme.spacingM - spacing: Theme.spacingS - - DankIcon { - name: { - if (modelData.name.includes("bluez")) - return "headset"; - else if (modelData.name.includes("usb")) - return "headset"; - else - return "mic"; - } - size: Theme.iconSize - 4 - color: modelData === AudioService.source ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - Column { - anchors.verticalCenter: parent.verticalCenter - width: { - const iconWidth = Theme.iconSize; - const pinButtonWidth = pinInputRow.width + Theme.spacingS * 4 + Theme.spacingM; - return parent.parent.width - iconWidth - parent.spacing - pinButtonWidth - Theme.spacingM * 2; - } - - StyledText { - text: AudioService.displayName(modelData) - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - font.weight: modelData === AudioService.source ? Font.Medium : Font.Normal - elide: Text.ElideRight - width: parent.width - wrapMode: Text.NoWrap - horizontalAlignment: Text.AlignLeft - } - - StyledText { - text: modelData === AudioService.source ? I18n.tr("Active") : I18n.tr("Available") - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - elide: Text.ElideRight - width: parent.width - wrapMode: Text.NoWrap - horizontalAlignment: Text.AlignLeft - } - } - } - - Rectangle { - anchors.right: parent.right - anchors.rightMargin: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - width: pinInputRow.width + Theme.spacingS * 2 - height: 28 - radius: height / 2 - color: { - const isThisDevicePinned = audioContent.getPinnedInputs().includes(modelData.name); - return isThisDevicePinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05); - } - - Row { - id: pinInputRow - anchors.centerIn: parent - spacing: 4 - - DankIcon { - name: "push_pin" - size: 16 - color: { - const isThisDevicePinned = audioContent.getPinnedInputs().includes(modelData.name); - return isThisDevicePinned ? Theme.primary : Theme.surfaceText; - } - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: { - const isThisDevicePinned = audioContent.getPinnedInputs().includes(modelData.name); - return isThisDevicePinned ? I18n.tr("Pinned") : I18n.tr("Pin"); - } - font.pixelSize: Theme.fontSizeSmall - color: { - const isThisDevicePinned = audioContent.getPinnedInputs().includes(modelData.name); - return isThisDevicePinned ? Theme.primary : Theme.surfaceText; - } - anchors.verticalCenter: parent.verticalCenter - } - } - - DankRipple { - id: pinRipple - cornerRadius: parent.radius - } - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y) - onClicked: { - const pins = JSON.parse(JSON.stringify(SettingsData.audioInputDevicePins || {})); - let pinnedList = audioContent.normalizePinList(pins["preferredInput"]); - const pinIndex = pinnedList.indexOf(modelData.name); - - if (pinIndex !== -1) { - pinnedList.splice(pinIndex, 1); - } else { - pinnedList.unshift(modelData.name); - if (pinnedList.length > audioContent.maxPinnedInputs) - pinnedList = pinnedList.slice(0, audioContent.maxPinnedInputs); - } - - if (pinnedList.length > 0) - pins["preferredInput"] = pinnedList; - else - delete pins["preferredInput"]; - - SettingsData.set("audioInputDevicePins", pins); - } - } - } - - DankRipple { - id: deviceRipple - cornerRadius: parent.radius - } - - MouseArea { - id: deviceMouseArea - anchors.fill: parent - anchors.rightMargin: pinInputRow.width + Theme.spacingS * 4 - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => { - let mapped = mapToItem(parent, mouse.x, mouse.y); - deviceRipple.trigger(mapped.x, mapped.y); - } - onClicked: { - if (modelData) { - Pipewire.preferredDefaultAudioSource = modelData; - } - } - } - } - } - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/AudioOutputDetail.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/AudioOutputDetail.qml deleted file mode 100644 index 7e86ae4..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/AudioOutputDetail.qml +++ /dev/null @@ -1,544 +0,0 @@ -import QtQuick -import Quickshell -import Quickshell.Services.Pipewire -import qs.Common -import qs.Services -import qs.Widgets - -Rectangle { - id: root - - LayoutMirroring.enabled: I18n.isRtl - LayoutMirroring.childrenInherit: true - - property bool hasVolumeSliderInCC: { - const widgets = SettingsData.controlCenterWidgets || []; - return widgets.some(widget => widget.id === "volumeSlider"); - } - - implicitHeight: headerRow.height + (!hasVolumeSliderInCC ? volumeSlider.height : 0) + audioContent.height + Theme.spacingM - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) - border.width: 0 - - Row { - id: headerRow - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.leftMargin: Theme.spacingM - anchors.rightMargin: Theme.spacingM - anchors.topMargin: Theme.spacingS - height: 40 - - StyledText { - id: headerText - text: I18n.tr("Audio Devices") - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium - anchors.verticalCenter: parent.verticalCenter - } - - Item { - height: 1 - width: parent.width - headerText.width - settingsButton.width - } - - DankActionButton { - id: settingsButton - anchors.verticalCenter: parent.verticalCenter - iconName: "settings" - buttonSize: 28 - iconSize: 16 - iconColor: Theme.surfaceVariantText - onClicked: { - PopoutService.closeControlCenter(); - PopoutService.openSettingsWithTab("audio"); - } - } - } - - Row { - id: volumeSlider - anchors.left: parent.left - anchors.right: parent.right - anchors.top: headerRow.bottom - anchors.leftMargin: Theme.spacingM - anchors.rightMargin: Theme.spacingM - anchors.topMargin: Theme.spacingXS - height: 35 - spacing: 0 - visible: !hasVolumeSliderInCC - - Rectangle { - width: Theme.iconSize + Theme.spacingS * 2 - height: Theme.iconSize + Theme.spacingS * 2 - anchors.verticalCenter: parent.verticalCenter - radius: (Theme.iconSize + Theme.spacingS * 2) / 2 - color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" - - DankRipple { - id: muteRipple - cornerRadius: parent.radius - } - - MouseArea { - id: iconArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => muteRipple.trigger(mouse.x, mouse.y) - onClicked: { - if (AudioService.sink && AudioService.sink.audio) { - AudioService.sink.audio.muted = !AudioService.sink.audio.muted; - } - } - } - - DankIcon { - anchors.centerIn: parent - name: { - if (!AudioService.sink || !AudioService.sink.audio) - return "volume_off"; - let muted = AudioService.sink.audio.muted; - let volume = AudioService.sink.audio.volume; - if (muted) - return "volume_off"; - if (volume === 0.0) - return "volume_mute"; - if (volume <= 0.33) - return "volume_down"; - if (volume <= 0.66) - return "volume_up"; - return "volume_up"; - } - size: Theme.iconSize - color: AudioService.sink && AudioService.sink.audio && !AudioService.sink.audio.muted && AudioService.sink.audio.volume > 0 ? Theme.primary : Theme.surfaceText - } - } - - DankSlider { - readonly property real actualVolumePercent: AudioService.sink && AudioService.sink.audio ? Math.round(AudioService.sink.audio.volume * 100) : 0 - - anchors.verticalCenter: parent.verticalCenter - width: parent.width - (Theme.iconSize + Theme.spacingS * 2) - enabled: AudioService.sink && AudioService.sink.audio - minimum: 0 - maximum: AudioService.sinkMaxVolume - value: AudioService.sink && AudioService.sink.audio ? Math.min(AudioService.sinkMaxVolume, Math.round(AudioService.sink.audio.volume * 100)) : 0 - showValue: true - unit: "%" - valueOverride: actualVolumePercent - thumbOutlineColor: Theme.surfaceVariant - - onSliderValueChanged: function (newValue) { - if (AudioService.sink && AudioService.sink.audio) { - AudioService.sink.audio.volume = newValue / 100; - if (newValue > 0 && AudioService.sink.audio.muted) { - AudioService.sink.audio.muted = false; - } - AudioService.volumeChanged(); - } - } - } - } - - DankFlickable { - id: audioContent - anchors.top: volumeSlider.visible ? volumeSlider.bottom : headerRow.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: Theme.spacingM - anchors.topMargin: volumeSlider.visible ? Theme.spacingS : Theme.spacingM - contentHeight: audioColumn.height - clip: true - - property int maxPinnedOutputs: 3 - - function normalizePinList(value) { - if (Array.isArray(value)) - return value.filter(v => v); - if (typeof value === "string" && value.length > 0) - return [value]; - return []; - } - - function getPinnedOutputs() { - const pins = SettingsData.audioOutputDevicePins || {}; - return normalizePinList(pins["preferredOutput"]); - } - - Column { - id: audioColumn - width: parent.width - spacing: Theme.spacingS - - Repeater { - model: ScriptModel { - values: { - const hidden = SessionData.hiddenOutputDeviceNames ?? []; - const nodes = Pipewire.nodes.values.filter(node => { - if (!node.audio || !node.isSink || node.isStream) - return false; - return !hidden.includes(node.name); - }); - const pinnedList = audioContent.getPinnedOutputs(); - - let sorted = [...nodes]; - sorted.sort((a, b) => { - // Pinned device first - const aPinnedIndex = pinnedList.indexOf(a.name); - const bPinnedIndex = pinnedList.indexOf(b.name); - if (aPinnedIndex !== -1 || bPinnedIndex !== -1) { - if (aPinnedIndex === -1) - return 1; - if (bPinnedIndex === -1) - return -1; - return aPinnedIndex - bPinnedIndex; - } - // Then active device - if (a === AudioService.sink && b !== AudioService.sink) - return -1; - if (b === AudioService.sink && a !== AudioService.sink) - return 1; - return 0; - }); - return sorted; - } - } - - delegate: Rectangle { - id: outputDelegate - required property var modelData - required property int index - - width: parent.width - height: 50 - radius: Theme.cornerRadius - color: deviceMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight - border.color: modelData === AudioService.sink ? Theme.primary : Theme.outlineLight - border.width: modelData === AudioService.sink ? 2 : 1 - - DankRipple { - id: deviceRipple - cornerRadius: outputDelegate.radius - } - - Row { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Theme.spacingM - spacing: Theme.spacingS - - DankIcon { - name: AudioService.sinkIcon(modelData) - size: Theme.iconSize - 4 - color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - Column { - anchors.verticalCenter: parent.verticalCenter - width: { - const iconWidth = Theme.iconSize; - const pinButtonWidth = pinOutputRow.width + Theme.spacingS * 4 + Theme.spacingM; - return parent.parent.width - iconWidth - parent.spacing - pinButtonWidth - Theme.spacingM * 2; - } - - StyledText { - text: AudioService.displayName(modelData) - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - font.weight: modelData === AudioService.sink ? Font.Medium : Font.Normal - elide: Text.ElideRight - width: parent.width - wrapMode: Text.NoWrap - horizontalAlignment: Text.AlignLeft - } - - StyledText { - text: modelData === AudioService.sink ? I18n.tr("Active") : I18n.tr("Available") - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - elide: Text.ElideRight - width: parent.width - wrapMode: Text.NoWrap - horizontalAlignment: Text.AlignLeft - } - } - } - - Rectangle { - anchors.right: parent.right - anchors.rightMargin: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - width: pinOutputRow.width + Theme.spacingS * 2 - height: 28 - radius: height / 2 - color: { - const isThisDevicePinned = audioContent.getPinnedOutputs().includes(modelData.name); - return isThisDevicePinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05); - } - - Row { - id: pinOutputRow - anchors.centerIn: parent - spacing: 4 - - DankIcon { - name: "push_pin" - size: 16 - color: { - const isThisDevicePinned = audioContent.getPinnedOutputs().includes(modelData.name); - return isThisDevicePinned ? Theme.primary : Theme.surfaceText; - } - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: { - const isThisDevicePinned = audioContent.getPinnedOutputs().includes(modelData.name); - return isThisDevicePinned ? I18n.tr("Pinned") : I18n.tr("Pin"); - } - font.pixelSize: Theme.fontSizeSmall - color: { - const isThisDevicePinned = audioContent.getPinnedOutputs().includes(modelData.name); - return isThisDevicePinned ? Theme.primary : Theme.surfaceText; - } - anchors.verticalCenter: parent.verticalCenter - } - } - - DankRipple { - id: pinRipple - cornerRadius: parent.radius - } - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y) - onClicked: { - const pins = JSON.parse(JSON.stringify(SettingsData.audioOutputDevicePins || {})); - let pinnedList = audioContent.normalizePinList(pins["preferredOutput"]); - const pinIndex = pinnedList.indexOf(modelData.name); - - if (pinIndex !== -1) { - pinnedList.splice(pinIndex, 1); - } else { - pinnedList.unshift(modelData.name); - if (pinnedList.length > audioContent.maxPinnedOutputs) - pinnedList = pinnedList.slice(0, audioContent.maxPinnedOutputs); - } - - if (pinnedList.length > 0) - pins["preferredOutput"] = pinnedList; - else - delete pins["preferredOutput"]; - - SettingsData.set("audioOutputDevicePins", pins); - } - } - } - - MouseArea { - id: deviceMouseArea - anchors.fill: parent - anchors.rightMargin: pinOutputRow.width + Theme.spacingS * 4 - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => { - let mapped = deviceMouseArea.mapToItem(outputDelegate, mouse.x, mouse.y); - deviceRipple.trigger(mapped.x, mapped.y); - } - onClicked: { - if (modelData) { - Pipewire.preferredDefaultAudioSink = modelData; - } - } - } - } - } - Row { - id: playbackHeaderRow - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: Theme.spacingM - anchors.rightMargin: Theme.spacingM - height: 28 - - StyledText { - id: playbackHeaderText - text: I18n.tr("Playback") - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - font.weight: Font.Medium - anchors.verticalCenter: parent.verticalCenter - } - } - - Repeater { - model: ScriptModel { - values: { - const nodes = Pipewire.nodes.values.filter(node => { - return node.audio && node.isSink && node.isStream; - }); - return nodes; - } - } - - delegate: Rectangle { - required property var modelData - required property int index - - width: parent.width - height: 50 - radius: Theme.cornerRadius - color: Theme.surfaceLight - border.color: modelData === AudioService.sink ? Theme.primary : Theme.outlineLight - border.width: modelData === AudioService.sink ? 2 : 1 - - Row { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Theme.spacingM - spacing: Theme.spacingS - - DankIcon { - name: "album" - size: Theme.iconSize - 4 - color: !modelData.audio.muted ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - Column { - anchors.verticalCenter: parent.verticalCenter - width: { - const iconWidth = Theme.iconSize; - return parent.parent.width - iconWidth - parent.spacing - Theme.spacingM * 2; - } - - StyledText { - text: { - const modelDataMediaName = modelData && modelData.properties ? (modelData.properties["media.name"] || "") : ""; - const mediaName = AudioService.displayName(modelData) + ": " + modelDataMediaName; - const max = 35; - return mediaName.length > max ? mediaName.substring(0, max) + "..." : mediaName; - } - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - font.weight: modelData === AudioService.sink ? Font.Medium : Font.Normal - elide: Text.ElideRight - width: parent.width - wrapMode: Text.NoWrap - } - } - } - Rectangle { - anchors.right: parent.right - anchors.rightMargin: 120 - anchors.verticalCenter: parent.verticalCenter - width: appVolumeRow.width - height: 28 - radius: height / 2 - - Item { - id: appVolumeRow - property color sliderTrackColor: "transparent" - anchors.centerIn: parent - - height: 40 - width: parent.width - - Rectangle { - anchors.right: parent.right - anchors.rightMargin: Theme.spacingM - width: Theme.iconSize + Theme.spacingS * 2 - height: Theme.iconSize + Theme.spacingS * 2 - anchors.verticalCenter: parent.verticalCenter - radius: Theme.cornerRadius - color: appIconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.primary, 0) - - DankRipple { - id: appMuteRipple - cornerRadius: parent.radius - } - - MouseArea { - id: appIconArea - anchors.fill: parent - visible: modelData !== null - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => appMuteRipple.trigger(mouse.x, mouse.y) - onClicked: { - if (modelData) { - SessionData.suppressOSDTemporarily(); - modelData.audio.muted = !modelData.audio.muted; - } - } - } - - DankIcon { - anchors.centerIn: parent - name: { - if (!modelData) - return "volume_off"; - - let volume = modelData.audio.volume; - let muted = modelData.audio.muted; - - if (muted) - return "volume_off"; - if (volume === 0.0) - return "volume_mute"; - if (volume <= 0.33) - return "volume_down"; - if (volume <= 0.66) - return "volume_up"; - return "volume_up"; - } - size: Theme.iconSize - color: modelData && !modelData.audio.muted && modelData.audio.volume > 0 ? Theme.primary : Theme.surfaceText - } - } - - DankSlider { - readonly property real actualVolumePercent: modelData ? Math.round(modelData.audio.volume * 100) : 0 - - anchors.verticalCenter: parent.verticalCenter - width: 100 - enabled: modelData !== null - minimum: 0 - maximum: 100 - value: modelData ? Math.min(100, Math.round(modelData.audio.volume * 100)) : 0 - showValue: true - unit: "%" - valueOverride: actualVolumePercent - thumbOutlineColor: Theme.surfaceContainer - trackColor: appVolumeRow.sliderTrackColor.a > 0 ? appVolumeRow.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) - - onSliderValueChanged: function (newValue) { - if (modelData) { - SessionData.suppressOSDTemporarily(); - modelData.audio.volume = newValue / 100.0; - if (newValue > 0 && modelData.audio.muted) { - modelData.audio.muted = false; - } - AudioService.playVolumeChangeSoundIfEnabled(); - } - } - } - } - PwObjectTracker { - objects: [modelData] - } - } - } - } - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BatteryDetail.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BatteryDetail.qml deleted file mode 100644 index 1f0206a..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BatteryDetail.qml +++ /dev/null @@ -1,267 +0,0 @@ -import QtQuick -import Quickshell.Services.UPower -import qs.Common -import qs.Services -import qs.Widgets - -Rectangle { - id: root - - LayoutMirroring.enabled: I18n.isRtl - LayoutMirroring.childrenInherit: true - - implicitHeight: contentColumn.implicitHeight + Theme.spacingL * 2 - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) - border.width: 0 - - function isActiveProfile(profile) { - if (typeof PowerProfiles === "undefined") { - return false; - } - return PowerProfiles.profile === profile; - } - - function setProfile(profile) { - if (typeof PowerProfiles === "undefined") { - ToastService.showError("power-profiles-daemon not available"); - return; - } - PowerProfiles.profile = profile; - if (PowerProfiles.profile !== profile) { - ToastService.showError("Failed to set power profile"); - } - } - - Column { - id: contentColumn - width: parent.width - Theme.spacingL * 2 - anchors.left: parent.left - anchors.top: parent.top - anchors.margins: Theme.spacingL - spacing: Theme.spacingL - - Row { - id: headerRow - width: parent.width - spacing: Theme.spacingM - - DankIcon { - name: BatteryService.getBatteryIcon() - size: Theme.iconSizeLarge - color: { - if (BatteryService.isLowBattery && !BatteryService.isCharging) - return Theme.error; - if (BatteryService.isCharging || BatteryService.isPluggedIn) - return Theme.primary; - return Theme.surfaceText; - } - anchors.verticalCenter: parent.verticalCenter - } - - Column { - spacing: Theme.spacingXS - anchors.verticalCenter: parent.verticalCenter - width: parent.width - Theme.iconSizeLarge - Theme.spacingM - - Row { - spacing: Theme.spacingS - - StyledText { - text: BatteryService.batteryAvailable ? `${BatteryService.batteryLevel}%` : I18n.tr("Power") - font.pixelSize: Theme.fontSizeXLarge - color: { - if (BatteryService.isLowBattery && !BatteryService.isCharging) { - return Theme.error; - } - if (BatteryService.isCharging) { - return Theme.primary; - } - return Theme.surfaceText; - } - font.weight: Font.Bold - } - - StyledText { - text: BatteryService.batteryAvailable ? BatteryService.batteryStatus : I18n.tr("Management") - font.pixelSize: Theme.fontSizeLarge - color: { - if (BatteryService.isLowBattery && !BatteryService.isCharging) { - return Theme.error; - } - if (BatteryService.isCharging) { - return Theme.primary; - } - return Theme.surfaceText; - } - font.weight: Font.Medium - anchors.verticalCenter: parent.verticalCenter - } - } - - StyledText { - text: { - if (!BatteryService.batteryAvailable) - return I18n.tr("Power profile management available"); - const time = BatteryService.formatTimeRemaining(); - if (time !== "Unknown") { - return BatteryService.isCharging ? I18n.tr("Time until full: %1").arg(time) : I18n.tr("Time remaining: %1").arg(time); - } - return ""; - } - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceTextMedium - visible: text.length > 0 - elide: Text.ElideRight - width: parent.width - horizontalAlignment: Text.AlignLeft - } - } - } - - Row { - width: parent.width - spacing: Theme.spacingM - visible: BatteryService.batteryAvailable - - StyledRect { - width: (parent.width - Theme.spacingM) / 2 - height: 64 - radius: Theme.cornerRadius - color: Theme.surfaceLight - border.color: Theme.outlineLight - border.width: 1 - - Column { - anchors.centerIn: parent - spacing: Theme.spacingXS - - StyledText { - text: I18n.tr("Health") - font.pixelSize: Theme.fontSizeSmall - color: Theme.primary - font.weight: Font.Medium - anchors.horizontalCenter: parent.horizontalCenter - } - - StyledText { - text: BatteryService.batteryHealth - font.pixelSize: Theme.fontSizeLarge - color: { - if (BatteryService.batteryHealth === "N/A") { - return Theme.surfaceText; - } - const healthNum = parseInt(BatteryService.batteryHealth); - return healthNum < 80 ? Theme.error : Theme.surfaceText; - } - font.weight: Font.Bold - anchors.horizontalCenter: parent.horizontalCenter - } - } - } - - StyledRect { - width: (parent.width - Theme.spacingM) / 2 - height: 64 - radius: Theme.cornerRadius - color: Theme.surfaceLight - border.color: Theme.outlineLight - border.width: 1 - - Column { - anchors.centerIn: parent - spacing: Theme.spacingXS - - StyledText { - text: I18n.tr("Capacity") - font.pixelSize: Theme.fontSizeSmall - color: Theme.primary - font.weight: Font.Medium - anchors.horizontalCenter: parent.horizontalCenter - } - - StyledText { - text: BatteryService.batteryCapacity > 0 ? `${BatteryService.batteryCapacity.toFixed(1)} Wh` : I18n.tr("Unknown") - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Bold - anchors.horizontalCenter: parent.horizontalCenter - } - } - } - } - - DankButtonGroup { - property var profileModel: (typeof PowerProfiles !== "undefined") ? [PowerProfile.PowerSaver, PowerProfile.Balanced].concat(PowerProfiles.hasPerformanceProfile ? [PowerProfile.Performance] : []) : [PowerProfile.PowerSaver, PowerProfile.Balanced, PowerProfile.Performance] - property int currentProfileIndex: { - if (typeof PowerProfiles === "undefined") - return 1; - return profileModel.findIndex(profile => isActiveProfile(profile)); - } - - model: profileModel.map(profile => Theme.getPowerProfileLabel(profile)) - currentIndex: currentProfileIndex - selectionMode: "single" - anchors.horizontalCenter: parent.horizontalCenter - onSelectionChanged: (index, selected) => { - if (!selected) - return; - setProfile(profileModel[index]); - } - } - - StyledRect { - width: parent.width - height: degradationContent.implicitHeight + Theme.spacingL * 2 - radius: Theme.cornerRadius - color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) - border.color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3) - border.width: 0 - visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None - - Column { - id: degradationContent - width: parent.width - Theme.spacingL * 2 - anchors.left: parent.left - anchors.top: parent.top - anchors.margins: Theme.spacingL - spacing: Theme.spacingS - - Row { - width: parent.width - spacing: Theme.spacingM - - DankIcon { - name: "warning" - size: Theme.iconSize - color: Theme.error - anchors.verticalCenter: parent.verticalCenter - } - - Column { - spacing: Theme.spacingXS - anchors.verticalCenter: parent.verticalCenter - width: parent.width - Theme.iconSize - Theme.spacingM - - StyledText { - text: I18n.tr("Power Profile Degradation") - font.pixelSize: Theme.fontSizeLarge - color: Theme.error - font.weight: Font.Medium - } - - StyledText { - text: (typeof PowerProfiles !== "undefined") ? PerformanceDegradationReason.toString(PowerProfiles.degradationReason) : "" - font.pixelSize: Theme.fontSizeSmall - color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.8) - wrapMode: Text.WordWrap - width: parent.width - horizontalAlignment: Text.AlignLeft - } - } - } - } - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BluetoothCodecSelector.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BluetoothCodecSelector.qml deleted file mode 100644 index 0cad08c..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BluetoothCodecSelector.qml +++ /dev/null @@ -1,332 +0,0 @@ -import QtQuick -import qs.Common -import qs.Services -import qs.Widgets - -Item { - id: root - - LayoutMirroring.enabled: I18n.isRtl - LayoutMirroring.childrenInherit: true - - property var device: null - property bool modalVisible: false - property var parentItem - property var availableCodecs: [] - property string currentCodec: "" - property bool isLoading: false - - readonly property bool deviceValid: device !== null && device.connected && BluetoothService.isAudioDevice(device) - - signal codecSelected(string deviceAddress, string codecName) - - function show(bluetoothDevice) { - if (!bluetoothDevice?.connected) - return; - if (!BluetoothService.isAudioDevice(bluetoothDevice)) - return; - device = bluetoothDevice; - isLoading = true; - availableCodecs = []; - currentCodec = ""; - visible = true; - modalVisible = true; - queryCodecs(); - Qt.callLater(() => { - focusScope.forceActiveFocus(); - }); - } - - function hide() { - modalVisible = false; - Qt.callLater(() => { - visible = false; - device = null; - }); - } - - function queryCodecs() { - if (!deviceValid) { - hide(); - return; - } - - const capturedDevice = device; - const capturedAddress = device.address; - - BluetoothService.getAvailableCodecs(capturedDevice, function (codecs, current) { - if (!root.deviceValid || root.device?.address !== capturedAddress) - return; - availableCodecs = codecs; - currentCodec = current; - isLoading = false; - }); - } - - function selectCodec(profileName) { - if (!deviceValid || isLoading) - return; - - const capturedDevice = device; - const capturedAddress = device.address; - - const selectedCodec = availableCodecs.find(c => c.profile === profileName); - if (!selectedCodec) - return; - - BluetoothService.updateDeviceCodec(capturedAddress, selectedCodec.name); - codecSelected(capturedAddress, selectedCodec.name); - - isLoading = true; - BluetoothService.switchCodec(capturedDevice, profileName, function (success, message) { - if (!root.device || root.device.address !== capturedAddress) - return; - - isLoading = false; - if (success) { - ToastService.showToast(message, ToastService.levelInfo); - Qt.callLater(root.hide); - return; - } - ToastService.showToast(message, ToastService.levelError); - }); - } - - onDeviceValidChanged: { - if (modalVisible && !deviceValid) { - hide(); - } - } - - visible: false - anchors.fill: parent - z: 2000 - - MouseArea { - id: modalBlocker - anchors.fill: parent - visible: modalVisible - enabled: modalVisible - hoverEnabled: true - preventStealing: true - propagateComposedEvents: false - - onClicked: root.hide() - onWheel: wheel => { - wheel.accepted = true; - } - onPositionChanged: mouse => { - mouse.accepted = true; - } - } - - Rectangle { - id: modalBackground - anchors.fill: parent - color: Qt.rgba(0, 0, 0, 0.5) - opacity: modalVisible ? 1 : 0 - - Behavior on opacity { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - } - - FocusScope { - id: focusScope - - anchors.fill: parent - focus: root.visible - enabled: root.visible - - Keys.onEscapePressed: { - root.hide(); - event.accepted = true; - } - } - - Rectangle { - id: modalContent - anchors.centerIn: parent - width: 320 - height: contentColumn.implicitHeight + Theme.spacingL * 2 - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency) - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) - border.width: 0 - opacity: modalVisible ? 1 : 0 - scale: modalVisible ? 1 : 0.9 - - MouseArea { - anchors.fill: parent - hoverEnabled: true - preventStealing: true - propagateComposedEvents: false - onClicked: mouse => { - mouse.accepted = true; - } - onWheel: wheel => { - wheel.accepted = true; - } - onPositionChanged: mouse => { - mouse.accepted = true; - } - } - - Column { - id: contentColumn - - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.margins: Theme.spacingL - spacing: Theme.spacingM - - Row { - width: parent.width - spacing: Theme.spacingM - - DankIcon { - name: device ? BluetoothService.getDeviceIcon(device) : "headset" - size: Theme.iconSize + 4 - color: Theme.primary - anchors.verticalCenter: parent.verticalCenter - } - - Column { - anchors.verticalCenter: parent.verticalCenter - spacing: 2 - - StyledText { - text: device ? (device.name || device.deviceName) : "" - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium - } - - StyledText { - text: I18n.tr("Audio Codec Selection") - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceTextMedium - } - } - } - - Rectangle { - width: parent.width - height: 1 - color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) - } - - StyledText { - text: isLoading ? I18n.tr("Loading codecs...") : I18n.tr("Current: %1").arg(currentCodec) - font.pixelSize: Theme.fontSizeSmall - color: isLoading ? Theme.primary : Theme.surfaceTextMedium - font.weight: Font.Medium - } - - Column { - width: parent.width - spacing: Theme.spacingXS - visible: !isLoading - - Repeater { - model: availableCodecs - - Rectangle { - width: parent.width - height: 48 - radius: Theme.cornerRadius - color: { - if (modelData.name === currentCodec) - return Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency); - else if (codecMouseArea.containsMouse) - return Theme.surfaceHover; - else - return "transparent"; - } - border.color: "transparent" - border.width: 0 - - Row { - anchors.left: parent.left - anchors.leftMargin: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - spacing: Theme.spacingS - - Rectangle { - width: 6 - height: 6 - radius: 3 - color: modelData.qualityColor - anchors.verticalCenter: parent.verticalCenter - } - - Column { - anchors.verticalCenter: parent.verticalCenter - spacing: 2 - - StyledText { - text: modelData.name - font.pixelSize: Theme.fontSizeMedium - color: modelData.name === currentCodec ? Theme.primary : Theme.surfaceText - font.weight: modelData.name === currentCodec ? Font.Medium : Font.Normal - } - - StyledText { - text: modelData.description - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceTextMedium - } - } - } - - DankIcon { - name: "check" - size: Theme.iconSize - 4 - color: Theme.primary - anchors.right: parent.right - anchors.rightMargin: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - visible: modelData.name === currentCodec - } - - DankRipple { - id: codecRipple - cornerRadius: parent.radius - } - - MouseArea { - id: codecMouseArea - - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - enabled: modelData.name !== currentCodec && !isLoading - onPressed: mouse => codecRipple.trigger(mouse.x, mouse.y) - onClicked: { - selectCodec(modelData.profile); - } - } - } - } - } - } - - Behavior on opacity { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - - Behavior on scale { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.emphasizedEasing - } - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BluetoothDetail.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BluetoothDetail.qml deleted file mode 100644 index 580ea9f..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BluetoothDetail.qml +++ /dev/null @@ -1,743 +0,0 @@ -import QtQuick -import QtQuick.Controls -import Quickshell -import Quickshell.Bluetooth -import qs.Common -import qs.Services -import qs.Widgets - -Rectangle { - id: root - - LayoutMirroring.enabled: I18n.isRtl - LayoutMirroring.childrenInherit: true - - implicitHeight: { - if (height > 0) - return height; - if (!BluetoothService.adapter?.enabled) - return headerRow.height; - return headerRow.height + bluetoothContent.height + Theme.spacingM; - } - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) - border.width: 0 - - property var bluetoothCodecModalRef: null - property var devicesBeingPaired: new Set() - - signal showCodecSelector(var device) - - function isDeviceBeingPaired(deviceAddress) { - return devicesBeingPaired.has(deviceAddress); - } - - function handlePairDevice(device) { - if (!device) - return; - const deviceAddr = device.address; - const pairingSet = devicesBeingPaired; - - pairingSet.add(deviceAddr); - devicesBeingPairedChanged(); - - BluetoothService.pairDevice(device, function (response) { - pairingSet.delete(deviceAddr); - devicesBeingPairedChanged(); - - if (response.error) { - ToastService.showError(I18n.tr("Pairing failed"), response.error); - return; - } - if (!BluetoothService.enhancedPairingAvailable) { - ToastService.showSuccess(I18n.tr("Device paired")); - } - }); - } - - function updateDeviceCodecDisplay(deviceAddress, codecName) { - for (let i = 0; i < pairedRepeater.count; i++) { - const item = pairedRepeater.itemAt(i); - if (!item?.modelData) - continue; - if (item.modelData.address !== deviceAddress) - continue; - item.currentCodec = codecName; - break; - } - } - - function normalizePinList(value) { - if (Array.isArray(value)) - return value.filter(v => v); - if (typeof value === "string" && value.length > 0) - return [value]; - return []; - } - - function getPinnedDevices() { - const pins = SettingsData.bluetoothDevicePins || {}; - return normalizePinList(pins["preferredDevice"]); - } - - Row { - id: headerRow - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.leftMargin: Theme.spacingM - anchors.rightMargin: Theme.spacingM - anchors.topMargin: Theme.spacingS - height: 40 - - StyledText { - id: headerText - text: I18n.tr("Bluetooth Settings") - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium - anchors.verticalCenter: parent.verticalCenter - } - - Item { - width: Math.max(0, parent.width - headerText.implicitWidth - scanButton.width - Theme.spacingM) - height: parent.height - } - - Rectangle { - id: scanButton - - readonly property bool adapterEnabled: BluetoothService.adapter?.enabled ?? false - readonly property bool isDiscovering: BluetoothService.adapter?.discovering ?? false - - width: 100 - height: 36 - radius: 18 - color: scanMouseArea.containsMouse && adapterEnabled ? Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) : "transparent" - border.color: adapterEnabled ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) - border.width: 0 - visible: adapterEnabled - - Row { - anchors.centerIn: parent - spacing: Theme.spacingXS - - DankIcon { - name: scanButton.isDiscovering ? "stop" : "bluetooth_searching" - size: 18 - color: scanButton.adapterEnabled ? Theme.primary : Theme.surfaceVariantText - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: scanButton.isDiscovering ? I18n.tr("Scanning") : I18n.tr("Scan") - color: scanButton.adapterEnabled ? Theme.primary : Theme.surfaceVariantText - font.pixelSize: Theme.fontSizeMedium - font.weight: Font.Medium - anchors.verticalCenter: parent.verticalCenter - } - } - - DankRipple { - id: scanRipple - cornerRadius: scanButton.radius - } - - MouseArea { - id: scanMouseArea - anchors.fill: parent - hoverEnabled: true - enabled: scanButton.adapterEnabled - cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor - onPressed: mouse => scanRipple.trigger(mouse.x, mouse.y) - onClicked: { - if (!BluetoothService.adapter) - return; - BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering; - } - } - } - } - - DankFlickable { - id: bluetoothContent - anchors.top: headerRow.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: Theme.spacingM - anchors.topMargin: Theme.spacingM - visible: BluetoothService.adapter?.enabled ?? false - contentHeight: bluetoothColumn.height - clip: true - - readonly property int maxPinnedDevices: 3 - - Column { - id: bluetoothColumn - width: parent.width - spacing: Theme.spacingS - - ScriptModel { - id: pairedDevicesModel - objectProp: "address" - values: { - if (!BluetoothService.adapter?.devices) - return []; - - const pinnedList = root.getPinnedDevices(); - const devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]; - - devices.sort((a, b) => { - const aPinnedIndex = pinnedList.indexOf(a.address); - const bPinnedIndex = pinnedList.indexOf(b.address); - - if (aPinnedIndex !== -1 || bPinnedIndex !== -1) { - if (aPinnedIndex === -1) - return 1; - if (bPinnedIndex === -1) - return -1; - return aPinnedIndex - bPinnedIndex; - } - - if (a.connected !== b.connected) - return a.connected ? -1 : 1; - - return (b.signalStrength || 0) - (a.signalStrength || 0); - }); - - return devices; - } - } - - Repeater { - id: pairedRepeater - model: pairedDevicesModel - - delegate: Rectangle { - id: pairedDelegate - required property var modelData - required property int index - - readonly property string currentCodec: BluetoothService.deviceCodecs[modelData.address] || "" - readonly property bool isConnecting: modelData.state === BluetoothDeviceState.Connecting - readonly property bool isConnected: modelData.connected - readonly property bool isPinned: root.getPinnedDevices().includes(modelData.address) - readonly property string deviceName: modelData.name || modelData.deviceName || I18n.tr("Unknown Device") - - width: parent.width - height: 50 - radius: Theme.cornerRadius - - Component.onCompleted: { - if (!isConnected) - return; - if (!BluetoothService.isAudioDevice(modelData)) - return; - BluetoothService.refreshDeviceCodec(modelData); - } - - color: { - if (isConnecting) - return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12); - if (deviceMouseArea.containsMouse) - return Theme.primaryHoverLight; - return Theme.surfaceLight; - } - - border.color: { - if (isConnecting) - return Theme.warning; - if (isConnected) - return Theme.primary; - return Theme.outlineLight; - } - border.width: (isConnecting || isConnected) ? 2 : 1 - - Row { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Theme.spacingM - spacing: Theme.spacingS - - DankIcon { - name: BluetoothService.getDeviceIcon(pairedDelegate.modelData) - size: Theme.iconSize - 4 - anchors.verticalCenter: parent.verticalCenter - color: { - if (pairedDelegate.isConnecting) - return Theme.warning; - if (pairedDelegate.isConnected) - return Theme.primary; - return Theme.surfaceText; - } - } - - Column { - anchors.verticalCenter: parent.verticalCenter - width: 200 - - StyledText { - text: pairedDelegate.deviceName - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - font.weight: pairedDelegate.isConnected ? Font.Medium : Font.Normal - elide: Text.ElideRight - width: parent.width - horizontalAlignment: Text.AlignLeft - } - - Row { - spacing: Theme.spacingXS - - StyledText { - text: { - if (pairedDelegate.isConnecting) - return I18n.tr("Connecting..."); - if (!pairedDelegate.isConnected) - return I18n.tr("Paired"); - if (!pairedDelegate.currentCodec) - return I18n.tr("Connected"); - return I18n.tr("Connected") + " • " + pairedDelegate.currentCodec; - } - font.pixelSize: Theme.fontSizeSmall - color: pairedDelegate.isConnecting ? Theme.warning : Theme.surfaceVariantText - } - - StyledText { - readonly property var btBattery: { - const name = pairedDelegate.deviceName; - return BatteryService.bluetoothDevices.find(dev => dev.name === name || dev.name.toLowerCase().includes(name.toLowerCase()) || name.toLowerCase().includes(dev.name.toLowerCase())); - } - text: { - if (pairedDelegate.modelData.batteryAvailable && pairedDelegate.modelData.battery > 0) - return "• " + Math.round(pairedDelegate.modelData.battery * 100) + "%"; - if (btBattery) - return "• " + btBattery.percentage + "%"; - return ""; - } - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - visible: text.length > 0 - } - - StyledText { - text: pairedDelegate.modelData.signalStrength > 0 ? "• " + pairedDelegate.modelData.signalStrength + "%" : "" - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - visible: text.length > 0 - } - } - } - } - - Rectangle { - anchors.right: pairedOptionsButton.left - anchors.rightMargin: Theme.spacingS - anchors.verticalCenter: parent.verticalCenter - width: pinBluetoothRow.width + Theme.spacingS * 2 - height: 28 - radius: height / 2 - color: pairedDelegate.isPinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05) - - Row { - id: pinBluetoothRow - anchors.centerIn: parent - spacing: 4 - - DankIcon { - name: "push_pin" - size: 16 - color: pairedDelegate.isPinned ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: pairedDelegate.isPinned ? I18n.tr("Pinned") : I18n.tr("Pin") - font.pixelSize: Theme.fontSizeSmall - color: pairedDelegate.isPinned ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - } - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - const pins = JSON.parse(JSON.stringify(SettingsData.bluetoothDevicePins || {})); - let pinnedList = root.normalizePinList(pins["preferredDevice"]); - const pinIndex = pinnedList.indexOf(pairedDelegate.modelData.address); - - if (pinIndex !== -1) { - pinnedList.splice(pinIndex, 1); - } else { - pinnedList.unshift(pairedDelegate.modelData.address); - if (pinnedList.length > bluetoothContent.maxPinnedDevices) - pinnedList = pinnedList.slice(0, bluetoothContent.maxPinnedDevices); - } - - if (pinnedList.length > 0) { - pins["preferredDevice"] = pinnedList; - } else { - delete pins["preferredDevice"]; - } - - SettingsData.set("bluetoothDevicePins", pins); - } - } - } - - DankActionButton { - id: pairedOptionsButton - anchors.right: parent.right - anchors.rightMargin: Theme.spacingS - anchors.verticalCenter: parent.verticalCenter - iconName: "more_horiz" - buttonSize: 28 - onClicked: { - if (bluetoothContextMenu.visible) { - bluetoothContextMenu.close(); - return; - } - bluetoothContextMenu.currentDevice = pairedDelegate.modelData; - bluetoothContextMenu.popup(pairedOptionsButton, -bluetoothContextMenu.width + pairedOptionsButton.width, pairedOptionsButton.height + Theme.spacingXS); - } - } - - DankRipple { - id: deviceRipple - cornerRadius: pairedDelegate.radius - } - - MouseArea { - id: deviceMouseArea - anchors.fill: parent - anchors.rightMargin: pairedOptionsButton.width + Theme.spacingM + pinBluetoothRow.width + Theme.spacingS * 4 - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => { - const pos = mapToItem(pairedDelegate, mouse.x, mouse.y); - deviceRipple.trigger(pos.x, pos.y); - } - onClicked: { - if (pairedDelegate.isConnected) { - pairedDelegate.modelData.disconnect(); - return; - } - BluetoothService.connectDeviceWithTrust(pairedDelegate.modelData); - } - } - } - } - - Rectangle { - width: parent.width - height: 1 - color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) - visible: pairedRepeater.count > 0 && availableRepeater.count > 0 - } - - Item { - width: parent.width - height: 80 - visible: (BluetoothService.adapter?.discovering ?? false) && availableRepeater.count === 0 - - DankIcon { - anchors.centerIn: parent - name: "sync" - size: 24 - color: Qt.rgba(Theme.surfaceText.r || 0.8, Theme.surfaceText.g || 0.8, Theme.surfaceText.b || 0.8, 0.4) - - RotationAnimation on rotation { - running: parent.visible - loops: Animation.Infinite - from: 0 - to: 360 - duration: 1500 - } - } - } - - ScriptModel { - id: availableDevicesModel - objectProp: "address" - values: { - if (!BluetoothService.adapter?.discovering) - return []; - if (!Bluetooth.devices) - return []; - - const filtered = Bluetooth.devices.values.filter(dev => dev && !dev.paired && !dev.pairing && !dev.blocked && (dev.signalStrength === undefined || dev.signalStrength > 0)); - return BluetoothService.sortDevices(filtered); - } - } - - Repeater { - id: availableRepeater - model: availableDevicesModel - - delegate: Rectangle { - id: availableDelegate - required property var modelData - required property int index - - readonly property bool canConnect: BluetoothService.canConnect(modelData) - readonly property bool isBusy: BluetoothService.isDeviceBusy(modelData) || root.isDeviceBeingPaired(modelData.address) - readonly property bool isInteractive: canConnect && !isBusy - readonly property string deviceName: modelData.name || modelData.deviceName || I18n.tr("Unknown Device") - - width: parent.width - height: 50 - radius: Theme.cornerRadius - color: availableMouseArea.containsMouse && isInteractive ? Theme.primaryHoverLight : Theme.surfaceLight - border.color: Theme.outlineLight - border.width: 1 - opacity: isInteractive ? 1 : 0.6 - - Row { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Theme.spacingM - spacing: Theme.spacingS - - DankIcon { - name: BluetoothService.getDeviceIcon(availableDelegate.modelData) - size: Theme.iconSize - 4 - color: Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - Column { - anchors.verticalCenter: parent.verticalCenter - width: 200 - - StyledText { - text: availableDelegate.deviceName - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - elide: Text.ElideRight - width: parent.width - horizontalAlignment: Text.AlignLeft - } - - Row { - spacing: Theme.spacingXS - - StyledText { - text: { - if (availableDelegate.modelData.pairing || availableDelegate.isBusy) - return I18n.tr("Pairing..."); - if (availableDelegate.modelData.blocked) - return I18n.tr("Blocked"); - return BluetoothService.getSignalStrength(availableDelegate.modelData); - } - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - } - - StyledText { - text: availableDelegate.modelData.signalStrength > 0 ? "• " + availableDelegate.modelData.signalStrength + "%" : "" - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - visible: text.length > 0 && !availableDelegate.modelData.pairing && !availableDelegate.modelData.blocked - } - } - } - } - - StyledText { - anchors.right: parent.right - anchors.rightMargin: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - text: { - if (availableDelegate.isBusy) - return I18n.tr("Pairing..."); - if (!availableDelegate.canConnect) - return I18n.tr("Cannot pair"); - return I18n.tr("Pair"); - } - font.pixelSize: Theme.fontSizeSmall - color: availableDelegate.isInteractive ? Theme.primary : Theme.surfaceVariantText - font.weight: Font.Medium - } - - DankRipple { - id: availableRipple - cornerRadius: availableDelegate.radius - } - - MouseArea { - id: availableMouseArea - anchors.fill: parent - hoverEnabled: true - cursorShape: availableDelegate.isInteractive ? Qt.PointingHandCursor : Qt.ArrowCursor - enabled: availableDelegate.isInteractive - onPressed: mouse => availableRipple.trigger(mouse.x, mouse.y) - onClicked: root.handlePairDevice(availableDelegate.modelData) - } - } - } - - Item { - width: parent.width - height: 60 - visible: !BluetoothService.adapter - - StyledText { - anchors.centerIn: parent - text: I18n.tr("No Bluetooth adapter found") - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceVariantText - } - } - } - } - - Menu { - id: bluetoothContextMenu - width: 150 - closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent - - property var currentDevice: null - - readonly property bool hasDevice: currentDevice !== null - readonly property bool deviceConnected: currentDevice?.connected ?? false - readonly property bool showCodecOption: hasDevice && deviceConnected && BluetoothService.isAudioDevice(currentDevice) - - background: Rectangle { - color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency) - radius: Theme.cornerRadius - border.width: 0 - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) - } - - MenuItem { - text: bluetoothContextMenu.deviceConnected ? I18n.tr("Disconnect") : I18n.tr("Connect") - height: 32 - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - if (!bluetoothContextMenu.hasDevice) - return; - if (bluetoothContextMenu.deviceConnected) { - bluetoothContextMenu.currentDevice.disconnect(); - return; - } - BluetoothService.connectDeviceWithTrust(bluetoothContextMenu.currentDevice); - } - } - - MenuItem { - text: I18n.tr("Audio Codec") - height: bluetoothContextMenu.showCodecOption ? 32 : 0 - visible: bluetoothContextMenu.showCodecOption - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - if (!bluetoothContextMenu.hasDevice) - return; - if (!bluetoothContextMenu.currentDevice.connected) - return; - if (!BluetoothService.isAudioDevice(bluetoothContextMenu.currentDevice)) - return; - showCodecSelector(bluetoothContextMenu.currentDevice); - } - } - - MenuItem { - text: bluetoothContextMenu.currentDevice?.trusted ? I18n.tr("Untrust") : I18n.tr("Trust") - height: 32 - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - if (!bluetoothContextMenu.hasDevice) - return; - bluetoothContextMenu.currentDevice.trusted = !bluetoothContextMenu.currentDevice.trusted; - } - } - - MenuItem { - text: I18n.tr("Forget Device") - height: 32 - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.error - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - if (!bluetoothContextMenu.hasDevice) - return; - if (!BluetoothService.enhancedPairingAvailable) { - bluetoothContextMenu.currentDevice.forget(); - return; - } - - const devicePath = BluetoothService.getDevicePath(bluetoothContextMenu.currentDevice); - DMSService.bluetoothRemove(devicePath, response => { - if (!response.error) - return; - ToastService.showError(I18n.tr("Failed to remove device"), response.error); - }); - } - } - } - - Connections { - target: DMSService - - function onBluetoothPairingRequest(data) { - const modal = PopoutService.bluetoothPairingModal; - if (!modal) - return; - if (modal.token === data.token) - return; - modal.show(data); - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BrightnessDetail.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BrightnessDetail.qml deleted file mode 100644 index 0d42e62..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/BrightnessDetail.qml +++ /dev/null @@ -1,498 +0,0 @@ -import QtQuick -import Quickshell -import qs.Common -import qs.Services -import qs.Widgets - -Rectangle { - id: root - - LayoutMirroring.enabled: I18n.isRtl - LayoutMirroring.childrenInherit: true - - property string initialDeviceName: "" - property string instanceId: "" - property string screenName: "" - property string screenModel: "" - - signal deviceNameChanged(string newDeviceName) - - property string currentDeviceName: "" - - function getScreenPinKey() { - if (!screenName) - return ""; - const screen = Quickshell.screens.find(s => s.name === screenName); - if (screen) { - return SettingsData.getScreenDisplayName(screen); - } - if (SettingsData.displayNameMode === "model" && screenModel && screenModel.length > 0) { - return screenModel; - } - return screenName; - } - - function resolveDeviceName() { - if (!DisplayService.brightnessAvailable || !DisplayService.devices || DisplayService.devices.length === 0) { - return ""; - } - - const pinKey = getScreenPinKey(); - if (pinKey.length > 0) { - const pins = SettingsData.brightnessDevicePins || {}; - const pinnedDevice = pins[pinKey]; - if (pinnedDevice && pinnedDevice.length > 0) { - const found = DisplayService.devices.find(dev => dev.name === pinnedDevice); - if (found) - return found.name; - } - } - - if (initialDeviceName && initialDeviceName.length > 0) { - const found = DisplayService.devices.find(dev => dev.name === initialDeviceName); - if (found) - return found.name; - } - - const currentDeviceNameFromService = DisplayService.currentDevice; - if (currentDeviceNameFromService) { - const found = DisplayService.devices.find(dev => dev.name === currentDeviceNameFromService); - if (found) - return found.name; - } - - const backlight = DisplayService.devices.find(d => d.class === "backlight"); - if (backlight) - return backlight.name; - - const ddc = DisplayService.devices.find(d => d.class === "ddc"); - if (ddc) - return ddc.name; - - return DisplayService.devices.length > 0 ? DisplayService.devices[0].name : ""; - } - - Component.onCompleted: { - currentDeviceName = resolveDeviceName(); - } - - property bool isPinnedToScreen: { - const pinKey = getScreenPinKey(); - if (!pinKey || pinKey.length === 0) - return false; - const pins = SettingsData.brightnessDevicePins || {}; - return pins[pinKey] === currentDeviceName; - } - - function togglePinToScreen() { - const pinKey = getScreenPinKey(); - if (!pinKey || pinKey.length === 0 || !currentDeviceName || currentDeviceName.length === 0) - return; - const pins = JSON.parse(JSON.stringify(SettingsData.brightnessDevicePins || {})); - - if (isPinnedToScreen) { - delete pins[pinKey]; - } else { - pins[pinKey] = currentDeviceName; - } - - SettingsData.set("brightnessDevicePins", pins); - } - - implicitHeight: { - if (height > 0) { - return height; - } - return brightnessContent.height + Theme.spacingM; - } - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) - border.width: 0 - - DankFlickable { - id: brightnessContent - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: Theme.spacingM - anchors.topMargin: Theme.spacingM - contentHeight: brightnessColumn.height - clip: true - - Column { - id: brightnessColumn - width: parent.width - spacing: Theme.spacingS - - Item { - width: parent.width - height: 100 - visible: !DisplayService.brightnessAvailable || !DisplayService.devices || DisplayService.devices.length === 0 - - Column { - anchors.centerIn: parent - spacing: Theme.spacingM - - DankIcon { - anchors.horizontalCenter: parent.horizontalCenter - name: DisplayService.brightnessAvailable ? "brightness_6" : "error" - size: 32 - color: DisplayService.brightnessAvailable ? Theme.primary : Theme.error - } - - StyledText { - anchors.horizontalCenter: parent.horizontalCenter - text: DisplayService.brightnessAvailable ? I18n.tr("No brightness devices available") : I18n.tr("Brightness control not available") - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - horizontalAlignment: Text.AlignHCenter - } - } - } - - Rectangle { - width: parent.width - height: 40 - visible: screenName && screenName.length > 0 && DisplayService.devices && DisplayService.devices.length > 1 - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) - - Item { - anchors.fill: parent - anchors.margins: Theme.spacingM - - Row { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - spacing: Theme.spacingM - - DankIcon { - name: "monitor" - size: Theme.iconSize - color: Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: root.getScreenPinKey() || I18n.tr("Unknown Monitor") - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - } - - Rectangle { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - width: pinRow.width + Theme.spacingS * 2 - height: 28 - radius: height / 2 - color: isPinnedToScreen ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05) - - Row { - id: pinRow - anchors.centerIn: parent - spacing: 4 - - DankIcon { - name: isPinnedToScreen ? "push_pin" : "push_pin" - size: 16 - color: isPinnedToScreen ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: isPinnedToScreen ? I18n.tr("Pinned") : I18n.tr("Pin") - font.pixelSize: Theme.fontSizeSmall - color: isPinnedToScreen ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - } - - DankRipple { - id: pinRipple - cornerRadius: parent.radius - } - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y) - onClicked: root.togglePinToScreen() - } - } - } - } - - Repeater { - model: DisplayService.devices || [] - delegate: Rectangle { - required property var modelData - required property int index - - property real deviceBrightness: { - DisplayService.brightnessVersion; - return DisplayService.getDeviceBrightness(modelData.name); - } - - width: parent.width - height: 100 - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) - border.color: modelData.name === currentDeviceName ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) - border.width: modelData.name === currentDeviceName ? 2 : 0 - - Column { - anchors.fill: parent - anchors.margins: Theme.spacingM - spacing: Theme.spacingS - - Item { - width: parent.width - height: Math.max(deviceIconColumn.height, deviceInfoColumn.height, exponentControls.height) - - Row { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - spacing: Theme.spacingM - - Column { - id: deviceIconColumn - anchors.verticalCenter: parent.verticalCenter - spacing: 2 - - DankIcon { - name: { - const deviceClass = modelData.class || ""; - const deviceName = modelData.name || ""; - - if (deviceClass === "backlight" || deviceClass === "ddc") { - if (deviceBrightness <= 33) - return "brightness_low"; - if (deviceBrightness <= 66) - return "brightness_medium"; - return "brightness_high"; - } else if (deviceName.includes("kbd")) { - return "keyboard"; - } else { - return "lightbulb"; - } - } - size: Theme.iconSize - color: modelData.name === currentDeviceName ? Theme.primary : Theme.surfaceText - anchors.horizontalCenter: parent.horizontalCenter - } - - StyledText { - text: Math.round(deviceBrightness) + "%" - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - anchors.horizontalCenter: parent.horizontalCenter - } - } - - Column { - id: deviceInfoColumn - anchors.verticalCenter: parent.verticalCenter - width: parent.parent.width - deviceIconColumn.width - exponentControls.width - Theme.spacingM * 3 - - StyledText { - text: { - const name = modelData.name || ""; - const deviceClass = modelData.class || ""; - if (deviceClass === "backlight") { - return name.replace("_", " ").replace(/\b\w/g, c => c.toUpperCase()); - } - return name; - } - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - font.weight: modelData.name === currentDeviceName ? Font.Medium : Font.Normal - elide: Text.ElideRight - width: parent.width - horizontalAlignment: Text.AlignLeft - } - - StyledText { - text: modelData.name - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - elide: Text.ElideRight - width: parent.width - horizontalAlignment: Text.AlignLeft - } - - StyledText { - text: { - const deviceClass = modelData.class || ""; - if (deviceClass === "backlight") - return I18n.tr("Backlight device"); - if (deviceClass === "ddc") - return I18n.tr("DDC/CI monitor"); - if (deviceClass === "leds") - return I18n.tr("LED device"); - return deviceClass; - } - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - elide: Text.ElideRight - width: parent.width - horizontalAlignment: Text.AlignLeft - } - } - } - - Row { - id: exponentControls - width: 140 - height: 28 - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - spacing: Theme.spacingXS - visible: SessionData.getBrightnessExponential(modelData.name) - z: 1 - - StyledRect { - width: 28 - height: 28 - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) - opacity: SessionData.getBrightnessExponent(modelData.name) > 1.0 ? 1.0 : 0.4 - - DankIcon { - anchors.centerIn: parent - name: "remove" - size: 14 - color: Theme.surfaceText - } - - StateLayer { - stateColor: Theme.primary - cornerRadius: parent.radius - enabled: SessionData.getBrightnessExponent(modelData.name) > 1.0 - onClicked: { - const current = SessionData.getBrightnessExponent(modelData.name); - const newValue = Math.max(1.0, Math.round((current - 0.1) * 10) / 10); - SessionData.setBrightnessExponent(modelData.name, newValue); - } - } - } - - StyledRect { - width: 50 - height: 28 - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) - border.width: 0 - - StyledText { - anchors.centerIn: parent - text: SessionData.getBrightnessExponent(modelData.name).toFixed(1) - font.pixelSize: Theme.fontSizeSmall - font.weight: Font.Medium - color: Theme.primary - } - } - - StyledRect { - width: 28 - height: 28 - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) - opacity: SessionData.getBrightnessExponent(modelData.name) < 2.5 ? 1.0 : 0.4 - - DankIcon { - anchors.centerIn: parent - name: "add" - size: 14 - color: Theme.surfaceText - } - - StateLayer { - stateColor: Theme.primary - cornerRadius: parent.radius - enabled: SessionData.getBrightnessExponent(modelData.name) < 2.5 - onClicked: { - const current = SessionData.getBrightnessExponent(modelData.name); - const newValue = Math.min(2.5, Math.round((current + 0.1) * 10) / 10); - SessionData.setBrightnessExponent(modelData.name, newValue); - } - } - } - } - } - - Rectangle { - width: parent.width - height: 24 - radius: height / 2 - color: SessionData.getBrightnessExponential(modelData.name) ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05) - - Row { - anchors.centerIn: parent - spacing: 4 - - DankIcon { - name: "show_chart" - size: 14 - color: SessionData.getBrightnessExponential(modelData.name) ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: SessionData.getBrightnessExponential(modelData.name) ? I18n.tr("Exponential") : I18n.tr("Linear") - font.pixelSize: Theme.fontSizeSmall - color: SessionData.getBrightnessExponential(modelData.name) ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - } - - DankRipple { - id: expToggleRipple - cornerRadius: parent.radius - } - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onPressed: mouse => expToggleRipple.trigger(mouse.x, mouse.y) - onClicked: { - const currentState = SessionData.getBrightnessExponential(modelData.name); - SessionData.setBrightnessExponential(modelData.name, !currentState); - } - } - } - } - - DankRipple { - id: deviceRipple - cornerRadius: parent.radius - } - - MouseArea { - anchors.fill: parent - anchors.bottomMargin: 28 - anchors.rightMargin: SessionData.getBrightnessExponential(modelData.name) ? 145 : 0 - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => deviceRipple.trigger(mouse.x, mouse.y) - onClicked: { - const pinKey = root.getScreenPinKey(); - if (pinKey.length > 0 && modelData.name !== currentDeviceName) { - const pins = JSON.parse(JSON.stringify(SettingsData.brightnessDevicePins || {})); - if (pins[pinKey]) { - delete pins[pinKey]; - SettingsData.set("brightnessDevicePins", pins); - } - } - currentDeviceName = modelData.name; - deviceNameChanged(modelData.name); - } - } - } - } - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/DiskUsageDetail.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/DiskUsageDetail.qml deleted file mode 100644 index 90fbf9d..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/DiskUsageDetail.qml +++ /dev/null @@ -1,177 +0,0 @@ -import QtQuick -import qs.Common -import qs.Services -import qs.Widgets - -Rectangle { - id: root - - LayoutMirroring.enabled: I18n.isRtl - LayoutMirroring.childrenInherit: true - - property string currentMountPath: "/" - property string instanceId: "" - - signal mountPathChanged(string newMountPath) - - implicitHeight: diskContent.height + Theme.spacingM - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) - border.width: 0 - - Component.onCompleted: { - DgopService.addRef(["diskmounts"]); - } - - Component.onDestruction: { - DgopService.removeRef(["diskmounts"]); - } - - DankFlickable { - id: diskContent - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: Theme.spacingM - anchors.topMargin: Theme.spacingM - contentHeight: diskColumn.height - clip: true - - Column { - id: diskColumn - width: parent.width - spacing: Theme.spacingS - - Item { - width: parent.width - height: 100 - visible: !DgopService.dgopAvailable || !DgopService.diskMounts || DgopService.diskMounts.length === 0 - - Column { - anchors.centerIn: parent - spacing: Theme.spacingM - - DankIcon { - anchors.horizontalCenter: parent.horizontalCenter - name: DgopService.dgopAvailable ? "storage" : "error" - size: 32 - color: DgopService.dgopAvailable ? Theme.primary : Theme.error - } - - StyledText { - anchors.horizontalCenter: parent.horizontalCenter - text: DgopService.dgopAvailable ? I18n.tr("No disk data available") : I18n.tr("dgop not available") - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - horizontalAlignment: Text.AlignHCenter - } - } - } - - Repeater { - model: DgopService.diskMounts || [] - delegate: Rectangle { - required property var modelData - required property int index - - width: parent.width - height: 80 - radius: Theme.cornerRadius - color: Theme.surfaceLight - border.color: modelData.mount === currentMountPath ? Theme.primary : Theme.outlineLight - border.width: modelData.mount === currentMountPath ? 2 : 1 - - Row { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Theme.spacingM - spacing: Theme.spacingM - - Column { - anchors.verticalCenter: parent.verticalCenter - spacing: 2 - - DankIcon { - name: "storage" - size: Theme.iconSize - color: { - const percentStr = modelData.percent?.replace("%", "") || "0"; - const percent = parseFloat(percentStr) || 0; - if (percent > 90) - return Theme.error; - if (percent > 75) - return Theme.warning; - return modelData.mount === currentMountPath ? Theme.primary : Theme.surfaceText; - } - anchors.horizontalCenter: parent.horizontalCenter - } - - StyledText { - text: { - const percentStr = modelData.percent?.replace("%", "") || "0"; - const percent = parseFloat(percentStr) || 0; - return percent.toFixed(0) + "%"; - } - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - anchors.horizontalCenter: parent.horizontalCenter - } - } - - Column { - anchors.verticalCenter: parent.verticalCenter - width: parent.parent.width - parent.parent.anchors.leftMargin - parent.spacing - 50 - Theme.spacingM - - StyledText { - text: modelData.mount === "/" ? I18n.tr("Root Filesystem") : modelData.mount - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - font.weight: modelData.mount === currentMountPath ? Font.Medium : Font.Normal - elide: Text.ElideRight - width: parent.width - horizontalAlignment: Text.AlignLeft - } - - StyledText { - text: modelData.mount - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - elide: Text.ElideRight - width: parent.width - visible: modelData.mount !== "/" - horizontalAlignment: Text.AlignLeft - } - - StyledText { - text: `${modelData.used || "?"} / ${modelData.size || "?"}` - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - elide: Text.ElideRight - width: parent.width - horizontalAlignment: Text.AlignLeft - } - } - } - - DankRipple { - id: mountRipple - cornerRadius: parent.radius - } - - MouseArea { - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => mountRipple.trigger(mouse.x, mouse.y) - onClicked: { - currentMountPath = modelData.mount; - mountPathChanged(modelData.mount); - } - } - } - } - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/NetworkDetail.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/NetworkDetail.qml deleted file mode 100644 index 5f1738a..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ControlCenter/Details/NetworkDetail.qml +++ /dev/null @@ -1,893 +0,0 @@ -import QtQuick -import QtQuick.Controls -import Quickshell -import qs.Common -import qs.Services -import qs.Widgets -import qs.Modals - -Rectangle { - id: root - - LayoutMirroring.enabled: I18n.isRtl - LayoutMirroring.childrenInherit: true - - implicitHeight: { - if (height > 0) - return height; - if (NetworkService.wifiToggling) - return headerRow.height + wifiToggleContent.height + Theme.spacingM; - if (NetworkService.wifiEnabled) - return headerRow.height + wifiContent.height + Theme.spacingM; - return headerRow.height + wifiOffContent.height + Theme.spacingM; - } - radius: Theme.cornerRadius - color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) - border.width: 0 - - Component.onCompleted: { - NetworkService.addRef(); - } - - Component.onDestruction: { - NetworkService.removeRef(); - } - - property bool hasEthernetAvailable: (NetworkService.ethernetDevices?.length ?? 0) > 0 - property bool hasWifiAvailable: (NetworkService.wifiDevices?.length ?? 0) > 0 - property bool hasBothConnectionTypes: hasEthernetAvailable && hasWifiAvailable - property int maxPinnedNetworks: 3 - - function normalizePinList(value) { - if (Array.isArray(value)) - return value.filter(v => v); - if (typeof value === "string" && value.length > 0) - return [value]; - return []; - } - - function getPinnedNetworks() { - const pins = SettingsData.wifiNetworkPins || {}; - return normalizePinList(pins["preferredWifi"]); - } - - property int currentPreferenceIndex: { - if (DMSService.apiVersion < 5) - return 1; - if (NetworkService.backend !== "networkmanager" || DMSService.apiVersion <= 10) - return 1; - if (!hasEthernetAvailable) - return 1; - if (!hasWifiAvailable) - return 0; - - const pref = NetworkService.userPreference; - switch (pref) { - case "ethernet": - return 0; - case "wifi": - return 1; - default: - return NetworkService.networkStatus === "ethernet" ? 0 : 1; - } - } - - Row { - id: headerRow - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.leftMargin: Theme.spacingM - anchors.rightMargin: Theme.spacingM - anchors.topMargin: Theme.spacingS - height: Math.max(headerLeft.implicitHeight, rightControls.implicitHeight) + Theme.spacingS * 2 - - StyledText { - id: headerLeft - text: I18n.tr("Network") - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium - anchors.verticalCenter: parent.verticalCenter - } - - Item { - height: 1 - width: parent.width - headerLeft.width - rightControls.width - } - - Row { - id: rightControls - anchors.verticalCenter: parent.verticalCenter - spacing: Theme.spacingS - - DankDropdown { - id: wifiDeviceDropdown - anchors.verticalCenter: parent.verticalCenter - visible: currentPreferenceIndex === 1 && (NetworkService.wifiDevices?.length ?? 0) > 1 - compactMode: true - dropdownWidth: 120 - popupWidth: 160 - alignPopupRight: true - - options: { - const devices = NetworkService.wifiDevices; - if (!devices || devices.length === 0) - return [I18n.tr("Auto")]; - return [I18n.tr("Auto")].concat(devices.map(d => d.name)); - } - - currentValue: NetworkService.wifiDeviceOverride || I18n.tr("Auto") - - onValueChanged: value => { - const deviceName = value === I18n.tr("Auto") ? "" : value; - NetworkService.setWifiDeviceOverride(deviceName); - } - } - - DankButtonGroup { - id: preferenceControls - anchors.verticalCenter: parent.verticalCenter - visible: hasBothConnectionTypes && NetworkService.backend === "networkmanager" && DMSService.apiVersion > 10 - buttonHeight: 28 - textSize: Theme.fontSizeSmall - - model: [I18n.tr("Ethernet"), I18n.tr("WiFi")] - currentIndex: currentPreferenceIndex - selectionMode: "single" - onSelectionChanged: (index, selected) => { - if (!selected) - return; - NetworkService.setNetworkPreference(index === 0 ? "ethernet" : "wifi"); - } - } - - DankActionButton { - anchors.verticalCenter: parent.verticalCenter - iconName: "settings" - buttonSize: 28 - iconSize: 16 - iconColor: Theme.surfaceVariantText - onClicked: { - PopoutService.closeControlCenter(); - PopoutService.openSettingsWithTab("network"); - } - } - } - } - - Item { - id: wifiToggleContent - anchors.top: headerRow.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: Theme.spacingM - anchors.topMargin: Theme.spacingM - visible: currentPreferenceIndex === 1 && NetworkService.wifiToggling - height: visible ? wifiToggleColumn.implicitHeight + Theme.spacingM * 2 : 0 - - Column { - id: wifiToggleColumn - anchors.centerIn: parent - spacing: Theme.spacingM - - DankIcon { - anchors.horizontalCenter: parent.horizontalCenter - name: "sync" - size: 32 - color: Theme.primary - - RotationAnimation on rotation { - running: NetworkService.wifiToggling - loops: Animation.Infinite - from: 0 - to: 360 - duration: 1000 - } - } - - StyledText { - anchors.horizontalCenter: parent.horizontalCenter - text: NetworkService.wifiEnabled ? I18n.tr("Disabling WiFi...") : I18n.tr("Enabling WiFi...") - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - horizontalAlignment: Text.AlignHCenter - } - } - } - - Item { - id: wifiOffContent - anchors.top: headerRow.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: Theme.spacingM - anchors.topMargin: Theme.spacingM - visible: currentPreferenceIndex === 1 && !NetworkService.wifiEnabled && !NetworkService.wifiToggling - height: visible ? wifiOffColumn.implicitHeight + Theme.spacingM * 2 : 0 - - Column { - id: wifiOffColumn - anchors.centerIn: parent - spacing: Theme.spacingL - width: parent.width - - DankIcon { - anchors.horizontalCenter: parent.horizontalCenter - name: "wifi_off" - size: 48 - color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) - } - - StyledText { - anchors.horizontalCenter: parent.horizontalCenter - text: I18n.tr("WiFi is off") - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium - horizontalAlignment: Text.AlignHCenter - } - - Rectangle { - anchors.horizontalCenter: parent.horizontalCenter - width: enableWifiLabel.implicitWidth + Theme.spacingL * 2 - height: enableWifiLabel.implicitHeight + Theme.spacingM * 2 - radius: height / 2 - color: enableWifiButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) - border.width: 0 - border.color: Theme.primary - - StyledText { - id: enableWifiLabel - anchors.centerIn: parent - text: I18n.tr("Enable WiFi") - color: Theme.primary - font.pixelSize: Theme.fontSizeMedium - font.weight: Font.Medium - } - - MouseArea { - id: enableWifiButton - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: NetworkService.toggleWifiRadio() - } - } - } - } - - ScriptModel { - id: wiredConnectionsModel - objectProp: "uuid" - values: { - const networks = NetworkService.wiredConnections; - if (!networks) - return []; - let sorted = [...networks]; - sorted.sort((a, b) => { - if (a.isActive && !b.isActive) - return -1; - if (!a.isActive && b.isActive) - return 1; - return a.id.localeCompare(b.id); - }); - return sorted; - } - } - - DankFlickable { - id: wiredContent - anchors.top: headerRow.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: Theme.spacingM - anchors.topMargin: Theme.spacingM - visible: currentPreferenceIndex === 0 && NetworkService.backend === "networkmanager" && DMSService.apiVersion > 10 - contentHeight: wiredColumn.height - clip: true - - Column { - id: wiredColumn - width: parent.width - spacing: Theme.spacingS - - Repeater { - model: wiredConnectionsModel - - delegate: Rectangle { - id: wiredDelegate - required property var modelData - required property int index - - readonly property bool isActive: modelData.isActive - readonly property string configName: modelData.id || I18n.tr("Unknown Config") - - width: parent.width - height: wiredContentRow.implicitHeight + Theme.spacingM * 2 - radius: Theme.cornerRadius - color: wiredNetworkMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight - border.color: isActive ? Theme.primary : Theme.outlineLight - border.width: isActive ? 2 : 1 - - Row { - id: wiredContentRow - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Theme.spacingM - spacing: Theme.spacingS - - DankIcon { - name: "lan" - size: Theme.iconSize - 4 - color: wiredDelegate.isActive ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - Column { - anchors.verticalCenter: parent.verticalCenter - width: 200 - - StyledText { - text: wiredDelegate.configName - font.pixelSize: Theme.fontSizeMedium - color: wiredDelegate.isActive ? Theme.primary : Theme.surfaceText - font.weight: wiredDelegate.isActive ? Font.Medium : Font.Normal - elide: Text.ElideRight - width: parent.width - } - } - } - - DankActionButton { - id: wiredOptionsButton - anchors.right: parent.right - anchors.rightMargin: Theme.spacingS - anchors.verticalCenter: parent.verticalCenter - iconName: "more_horiz" - buttonSize: 28 - onClicked: { - if (wiredNetworkContextMenu.visible) { - wiredNetworkContextMenu.close(); - return; - } - wiredNetworkContextMenu.currentID = modelData.id; - wiredNetworkContextMenu.currentUUID = modelData.uuid; - wiredNetworkContextMenu.currentConnected = wiredDelegate.isActive; - wiredNetworkContextMenu.popup(wiredOptionsButton, -wiredNetworkContextMenu.width + wiredOptionsButton.width, wiredOptionsButton.height + Theme.spacingXS); - } - } - - DankRipple { - id: wiredRipple - cornerRadius: parent.radius - } - - MouseArea { - id: wiredNetworkMouseArea - anchors.fill: parent - anchors.rightMargin: wiredOptionsButton.width + Theme.spacingS - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => wiredRipple.trigger(mouse.x, mouse.y) - onClicked: function (event) { - if (modelData.uuid !== NetworkService.ethernetConnectionUuid) - NetworkService.connectToSpecificWiredConfig(modelData.uuid); - event.accepted = true; - } - } - } - } - } - } - - Menu { - id: wiredNetworkContextMenu - width: 150 - closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent - - property string currentID: "" - property string currentUUID: "" - property bool currentConnected: false - - background: Rectangle { - color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency) - radius: Theme.cornerRadius - border.width: 0 - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) - } - - MenuItem { - text: I18n.tr("Activate") - height: !wiredNetworkContextMenu.currentConnected ? 32 : 0 - visible: !wiredNetworkContextMenu.currentConnected - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - if (!wiredNetworkContextMenu.currentConnected) - NetworkService.connectToSpecificWiredConfig(wiredNetworkContextMenu.currentUUID); - } - } - - MenuItem { - text: I18n.tr("Disconnect") - height: wiredNetworkContextMenu.currentConnected ? 32 : 0 - visible: wiredNetworkContextMenu.currentConnected - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.error - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - NetworkService.toggleNetworkConnection("ethernet"); - } - } - - MenuItem { - text: I18n.tr("Network Info") - height: wiredNetworkContextMenu.currentConnected ? 32 : 0 - visible: wiredNetworkContextMenu.currentConnected - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - const networkData = NetworkService.getWiredNetworkInfo(wiredNetworkContextMenu.currentUUID); - networkWiredInfoModalLoader.active = true; - networkWiredInfoModalLoader.item.showNetworkInfo(wiredNetworkContextMenu.currentID, networkData); - } - } - } - - ScriptModel { - id: wifiNetworksModel - objectProp: "ssid" - values: wifiContent.menuOpen ? wifiContent.frozenNetworks : wifiContent.sortedNetworks - } - - Item { - id: wifiScanningOverlay - anchors.top: headerRow.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: Theme.spacingM - anchors.topMargin: Theme.spacingM - visible: currentPreferenceIndex === 1 && NetworkService.wifiEnabled && !NetworkService.wifiToggling && NetworkService.wifiInterface && (NetworkService.wifiNetworks?.length ?? 0) < 1 && NetworkService.isScanning - - DankIcon { - anchors.centerIn: parent - name: "refresh" - size: 48 - color: Qt.rgba(Theme.surfaceText.r || 0.8, Theme.surfaceText.g || 0.8, Theme.surfaceText.b || 0.8, 0.3) - - RotationAnimation on rotation { - running: wifiScanningOverlay.visible - loops: Animation.Infinite - from: 0 - to: 360 - duration: 1000 - } - } - } - - DankListView { - id: wifiContent - anchors.top: headerRow.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: Theme.spacingM - anchors.topMargin: Theme.spacingM - visible: currentPreferenceIndex === 1 && NetworkService.wifiEnabled && !NetworkService.wifiToggling && !wifiScanningOverlay.visible - clip: true - spacing: Theme.spacingS - model: wifiNetworksModel - - property var frozenNetworks: [] - property bool menuOpen: false - property var sortedNetworks: { - const ssid = NetworkService.currentWifiSSID; - const networks = NetworkService.wifiNetworks; - const pinnedList = root.getPinnedNetworks(); - - let sorted = [...networks]; - sorted.sort((a, b) => { - const aPinnedIndex = pinnedList.indexOf(a.ssid); - const bPinnedIndex = pinnedList.indexOf(b.ssid); - if (aPinnedIndex !== -1 || bPinnedIndex !== -1) { - if (aPinnedIndex === -1) - return 1; - if (bPinnedIndex === -1) - return -1; - return aPinnedIndex - bPinnedIndex; - } - if (a.ssid === ssid) - return -1; - if (b.ssid === ssid) - return 1; - return b.signal - a.signal; - }); - return sorted; - } - onSortedNetworksChanged: { - if (!menuOpen) - frozenNetworks = sortedNetworks; - } - onMenuOpenChanged: { - if (menuOpen) - frozenNetworks = sortedNetworks; - } - - delegate: Rectangle { - id: wifiDelegate - required property var modelData - required property int index - - readonly property bool isConnected: modelData.ssid === NetworkService.currentWifiSSID - readonly property bool isPinned: root.getPinnedNetworks().includes(modelData.ssid) - readonly property string networkName: modelData.ssid || I18n.tr("Unknown Network") - readonly property int signalStrength: modelData.signal || 0 - - width: wifiContent.width - height: wifiContentRow.implicitHeight + Theme.spacingM * 2 - radius: Theme.cornerRadius - color: networkMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight - border.color: wifiDelegate.isConnected ? Theme.primary : Theme.outlineLight - border.width: wifiDelegate.isConnected ? 2 : 1 - - Row { - id: wifiContentRow - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: Theme.spacingM - spacing: Theme.spacingS - - DankIcon { - name: { - if (wifiDelegate.signalStrength >= 50) - return "wifi"; - if (wifiDelegate.signalStrength >= 25) - return "wifi_2_bar"; - return "wifi_1_bar"; - } - size: Theme.iconSize - 4 - color: wifiDelegate.isConnected ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - Column { - anchors.verticalCenter: parent.verticalCenter - width: 200 - - StyledText { - text: wifiDelegate.networkName - font.pixelSize: Theme.fontSizeMedium - color: Theme.surfaceText - font.weight: wifiDelegate.isConnected ? Font.Medium : Font.Normal - elide: Text.ElideRight - width: parent.width - } - - Row { - spacing: Theme.spacingXS - - StyledText { - text: wifiDelegate.isConnected ? I18n.tr("Connected") + " \u2022" : (modelData.secured ? I18n.tr("Secured") + " \u2022" : I18n.tr("Open") + " \u2022") - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - } - - StyledText { - text: modelData.saved ? I18n.tr("Saved") : "" - font.pixelSize: Theme.fontSizeSmall - color: Theme.primary - visible: text.length > 0 - } - - StyledText { - text: (modelData.saved ? "\u2022 " : "") + wifiDelegate.signalStrength + "%" - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceVariantText - } - } - } - } - - DankActionButton { - id: optionsButton - anchors.right: parent.right - anchors.rightMargin: Theme.spacingS - anchors.verticalCenter: parent.verticalCenter - iconName: "more_horiz" - buttonSize: 28 - onClicked: { - if (networkContextMenu.visible) { - networkContextMenu.close(); - return; - } - wifiContent.menuOpen = true; - networkContextMenu.currentSSID = modelData.ssid; - networkContextMenu.currentSecured = modelData.secured; - networkContextMenu.currentConnected = wifiDelegate.isConnected; - networkContextMenu.currentSaved = modelData.saved; - networkContextMenu.currentSignal = modelData.signal; - networkContextMenu.currentAutoconnect = modelData.autoconnect || false; - networkContextMenu.popup(optionsButton, -networkContextMenu.width + optionsButton.width, optionsButton.height + Theme.spacingXS); - } - } - - Rectangle { - id: pinButton - anchors.right: parent.right - anchors.rightMargin: optionsButton.width + Theme.spacingM + Theme.spacingS - anchors.verticalCenter: parent.verticalCenter - width: pinWifiRow.width + Theme.spacingS * 2 - height: pinWifiRow.implicitHeight + Theme.spacingXS * 2 - radius: height / 2 - color: wifiDelegate.isPinned ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceText, 0.05) - - Row { - id: pinWifiRow - anchors.centerIn: parent - spacing: 4 - - DankIcon { - name: "push_pin" - size: 16 - color: wifiDelegate.isPinned ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: wifiDelegate.isPinned ? I18n.tr("Pinned") : I18n.tr("Pin") - font.pixelSize: Theme.fontSizeSmall - color: wifiDelegate.isPinned ? Theme.primary : Theme.surfaceText - anchors.verticalCenter: parent.verticalCenter - } - } - - DankRipple { - id: pinRipple - cornerRadius: parent.radius - } - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onPressed: mouse => pinRipple.trigger(mouse.x, mouse.y) - onClicked: { - const pins = JSON.parse(JSON.stringify(SettingsData.wifiNetworkPins || {})); - let pinnedList = root.normalizePinList(pins["preferredWifi"]); - const pinIndex = pinnedList.indexOf(modelData.ssid); - - if (pinIndex !== -1) { - pinnedList.splice(pinIndex, 1); - } else { - pinnedList.unshift(modelData.ssid); - if (pinnedList.length > root.maxPinnedNetworks) - pinnedList = pinnedList.slice(0, root.maxPinnedNetworks); - } - - if (pinnedList.length > 0) - pins["preferredWifi"] = pinnedList; - else - delete pins["preferredWifi"]; - - SettingsData.set("wifiNetworkPins", pins); - } - } - } - - DankActionButton { - id: qrCodeButton - visible: modelData.secured && modelData.saved - anchors.right: parent.right - anchors.rightMargin: optionsButton.width + pinWifiRow.width + 3 * Theme.spacingM + Theme.spacingS - anchors.verticalCenter: parent.verticalCenter - iconName: "qr_code" - buttonSize: 28 - onClicked: { - PopoutService.showWifiQRCodeModal(modelData.ssid); - } - } - - DankRipple { - id: wifiRipple - cornerRadius: parent.radius - } - - MouseArea { - id: networkMouseArea - anchors.fill: parent - anchors.rightMargin: optionsButton.width + pinWifiRow.width + (qrCodeButton.visible ? qrCodeButton.width : 0) + Theme.spacingS * 5 + Theme.spacingM - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: mouse => wifiRipple.trigger(mouse.x, mouse.y) - onClicked: function (event) { - if (wifiDelegate.isConnected) { - event.accepted = true; - return; - } - if (modelData.secured && !modelData.saved && DMSService.apiVersion < 7) { - PopoutService.showWifiPasswordModal(modelData.ssid); - } else { - NetworkService.connectToWifi(modelData.ssid); - } - event.accepted = true; - } - } - } - } - - Menu { - id: networkContextMenu - width: 150 - closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent - - property string currentSSID: "" - property bool currentSecured: false - property bool currentConnected: false - property bool currentSaved: false - property int currentSignal: 0 - property bool currentAutoconnect: false - - readonly property bool showSavedOptions: currentSaved || currentConnected - - onClosed: { - wifiContent.menuOpen = false; - } - - background: Rectangle { - color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency) - radius: Theme.cornerRadius - border.width: 0 - border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) - } - - MenuItem { - text: networkContextMenu.currentConnected ? I18n.tr("Disconnect") : I18n.tr("Connect") - height: 32 - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - if (networkContextMenu.currentConnected) { - NetworkService.disconnectWifi(); - return; - } - if (networkContextMenu.currentSecured && !networkContextMenu.currentSaved && DMSService.apiVersion < 7) { - PopoutService.showWifiPasswordModal(networkContextMenu.currentSSID); - return; - } - NetworkService.connectToWifi(networkContextMenu.currentSSID); - } - } - - MenuItem { - text: I18n.tr("Network Info") - height: 32 - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - const networkData = NetworkService.getNetworkInfo(networkContextMenu.currentSSID); - networkInfoModalLoader.active = true; - networkInfoModalLoader.item.showNetworkInfo(networkContextMenu.currentSSID, networkData); - } - } - - MenuItem { - text: networkContextMenu.currentAutoconnect ? I18n.tr("Disable Autoconnect") : I18n.tr("Enable Autoconnect") - height: networkContextMenu.showSavedOptions && DMSService.apiVersion > 13 ? 32 : 0 - visible: networkContextMenu.showSavedOptions && DMSService.apiVersion > 13 - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - NetworkService.setWifiAutoconnect(networkContextMenu.currentSSID, !networkContextMenu.currentAutoconnect); - } - } - - MenuItem { - text: I18n.tr("Forget Network") - height: networkContextMenu.showSavedOptions ? 32 : 0 - visible: networkContextMenu.showSavedOptions - - contentItem: StyledText { - text: parent.text - font.pixelSize: Theme.fontSizeSmall - color: Theme.error - leftPadding: Theme.spacingS - verticalAlignment: Text.AlignVCenter - } - - background: Rectangle { - color: parent.hovered ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08) : "transparent" - radius: Theme.cornerRadius / 2 - } - - onTriggered: { - NetworkService.forgetWifiNetwork(networkContextMenu.currentSSID); - } - } - } - - Loader { - id: networkInfoModalLoader - active: false - sourceComponent: NetworkInfoModal {} - } - - Loader { - id: networkWiredInfoModalLoader - active: false - sourceComponent: NetworkWiredInfoModal {} - } -} |