mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-03 20:32:07 -04:00
audio: New ability to hide input/output devices
- Updated slider presets - Disabled mouse wheel scrolling on list scroll
This commit is contained in:
@@ -123,6 +123,8 @@ Singleton {
|
||||
property string vpnLastConnected: ""
|
||||
|
||||
property var deviceMaxVolumes: ({})
|
||||
property var hiddenOutputDeviceNames: []
|
||||
property var hiddenInputDeviceNames: []
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!isGreeterMode) {
|
||||
@@ -1069,6 +1071,20 @@ Singleton {
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setHiddenOutputDeviceNames(deviceNames) {
|
||||
if (!Array.isArray(deviceNames))
|
||||
return;
|
||||
hiddenOutputDeviceNames = deviceNames;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setHiddenInputDeviceNames(deviceNames) {
|
||||
if (!Array.isArray(deviceNames))
|
||||
return;
|
||||
hiddenInputDeviceNames = deviceNames;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function getDeviceMaxVolume(nodeName) {
|
||||
if (!nodeName)
|
||||
return 100;
|
||||
|
||||
@@ -75,7 +75,9 @@ var SPEC = {
|
||||
|
||||
vpnLastConnected: { def: "" },
|
||||
|
||||
deviceMaxVolumes: { def: {} }
|
||||
deviceMaxVolumes: { def: {} },
|
||||
hiddenOutputDeviceNames: { def: [] },
|
||||
hiddenInputDeviceNames: { def: [] }
|
||||
};
|
||||
|
||||
function getValidKeys() {
|
||||
|
||||
@@ -18,6 +18,22 @@ Item {
|
||||
property string editingDeviceType: ""
|
||||
property string newDeviceName: ""
|
||||
property bool isReloadingAudio: false
|
||||
property var hiddenOutputDeviceNames: SessionData.hiddenOutputDeviceNames ?? []
|
||||
property var hiddenInputDeviceNames: SessionData.hiddenInputDeviceNames ?? []
|
||||
property bool showHiddenOutputDevices: false
|
||||
property bool showHiddenInputDevices: false
|
||||
|
||||
function persistHiddenOutputDeviceNames(deviceNames) {
|
||||
const uniqueNames = [...new Set(deviceNames)];
|
||||
hiddenOutputDeviceNames = uniqueNames;
|
||||
SessionData.setHiddenOutputDeviceNames(uniqueNames);
|
||||
}
|
||||
|
||||
function persistHiddenInputDeviceNames(deviceNames) {
|
||||
const uniqueNames = [...new Set(deviceNames)];
|
||||
hiddenInputDeviceNames = uniqueNames;
|
||||
SessionData.setHiddenInputDeviceNames(uniqueNames);
|
||||
}
|
||||
|
||||
function updateDeviceList() {
|
||||
const allNodes = Pipewire.nodes.values;
|
||||
@@ -56,6 +72,8 @@ Item {
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
hiddenOutputDeviceNames = SessionData.hiddenOutputDeviceNames ?? [];
|
||||
hiddenInputDeviceNames = SessionData.hiddenInputDeviceNames ?? [];
|
||||
updateDeviceList();
|
||||
}
|
||||
|
||||
@@ -132,7 +150,7 @@ Item {
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: root.outputDevices
|
||||
model: root.outputDevices.filter(d => !root.hiddenOutputDeviceNames.includes(d.name))
|
||||
|
||||
delegate: Column {
|
||||
required property var modelData
|
||||
@@ -142,6 +160,7 @@ Item {
|
||||
DeviceAliasRow {
|
||||
deviceNode: modelData
|
||||
deviceType: "output"
|
||||
showHideButton: true
|
||||
|
||||
onEditRequested: device => {
|
||||
root.editingDevice = device;
|
||||
@@ -153,6 +172,10 @@ Item {
|
||||
onResetRequested: device => {
|
||||
AudioService.removeDeviceAlias(device.name);
|
||||
}
|
||||
|
||||
onHideRequested: device => {
|
||||
root.persistHiddenOutputDeviceNames([...root.hiddenOutputDeviceNames, device.name]);
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -161,7 +184,7 @@ Item {
|
||||
|
||||
StyledText {
|
||||
id: maxVolLabel
|
||||
text: I18n.tr("Max Volume", "Audio settings: maximum volume limit per device")
|
||||
text: I18n.tr("Max Volume", "Audio settings: maximum volume limit per device") + " · " + maxVolSlider.value + "%"
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Theme.spacingM + Theme.iconSize + Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -182,6 +205,8 @@ Item {
|
||||
maximum: 200
|
||||
step: 5
|
||||
showValue: true
|
||||
wheelEnabled: false
|
||||
centerMinimum: true
|
||||
unit: "%"
|
||||
onSliderValueChanged: newValue => {
|
||||
SessionData.setDeviceMaxVolume(modelData.name, newValue);
|
||||
@@ -204,9 +229,87 @@ Item {
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
visible: root.outputDevices.length === 0
|
||||
visible: root.outputDevices.filter(d => !root.hiddenOutputDeviceNames.includes(d.name)).length === 0 && root.hiddenOutputDeviceNames.length === 0
|
||||
topPadding: Theme.spacingM
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 0
|
||||
visible: root.hiddenOutputDeviceNames.length > 0
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Theme.outline
|
||||
opacity: 0.15
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 36
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingS
|
||||
|
||||
DankIcon {
|
||||
name: "visibility_off"
|
||||
size: Theme.iconSize - 4
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Hidden (%1)").arg(root.hiddenOutputDeviceNames.length)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
name: root.showHiddenOutputDevices ? "expand_less" : "expand_more"
|
||||
size: Theme.iconSize - 4
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.showHiddenOutputDevices = !root.showHiddenOutputDevices
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 0
|
||||
visible: root.showHiddenOutputDevices
|
||||
|
||||
Repeater {
|
||||
model: root.outputDevices.filter(d => root.hiddenOutputDeviceNames.includes(d.name))
|
||||
|
||||
delegate: DeviceAliasRow {
|
||||
required property var modelData
|
||||
deviceNode: modelData
|
||||
deviceType: "output"
|
||||
isHidden: true
|
||||
showHideButton: true
|
||||
|
||||
onHideRequested: device => {
|
||||
root.persistHiddenOutputDeviceNames(root.hiddenOutputDeviceNames.filter(n => n !== device.name));
|
||||
}
|
||||
|
||||
onResetRequested: device => {
|
||||
AudioService.removeDeviceAlias(device.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,13 +341,14 @@ Item {
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: root.inputDevices
|
||||
model: root.inputDevices.filter(d => !root.hiddenInputDeviceNames.includes(d.name))
|
||||
|
||||
delegate: DeviceAliasRow {
|
||||
required property var modelData
|
||||
|
||||
deviceNode: modelData
|
||||
deviceType: "input"
|
||||
showHideButton: true
|
||||
|
||||
onEditRequested: device => {
|
||||
root.editingDevice = device;
|
||||
@@ -256,6 +360,10 @@ Item {
|
||||
onResetRequested: device => {
|
||||
AudioService.removeDeviceAlias(device.name);
|
||||
}
|
||||
|
||||
onHideRequested: device => {
|
||||
root.persistHiddenInputDeviceNames([...root.hiddenInputDeviceNames, device.name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,9 +373,87 @@ Item {
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
visible: root.inputDevices.length === 0
|
||||
visible: root.inputDevices.filter(d => !root.hiddenInputDeviceNames.includes(d.name)).length === 0 && root.hiddenInputDeviceNames.length === 0
|
||||
topPadding: Theme.spacingM
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 0
|
||||
visible: root.hiddenInputDeviceNames.length > 0
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Theme.outline
|
||||
opacity: 0.15
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 36
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingS
|
||||
|
||||
DankIcon {
|
||||
name: "visibility_off"
|
||||
size: Theme.iconSize - 4
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: I18n.tr("Hidden (%1)").arg(root.hiddenInputDeviceNames.length)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
name: root.showHiddenInputDevices ? "expand_less" : "expand_more"
|
||||
size: Theme.iconSize - 4
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.showHiddenInputDevices = !root.showHiddenInputDevices
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 0
|
||||
visible: root.showHiddenInputDevices
|
||||
|
||||
Repeater {
|
||||
model: root.inputDevices.filter(d => root.hiddenInputDeviceNames.includes(d.name))
|
||||
|
||||
delegate: DeviceAliasRow {
|
||||
required property var modelData
|
||||
deviceNode: modelData
|
||||
deviceType: "input"
|
||||
isHidden: true
|
||||
showHideButton: true
|
||||
|
||||
onHideRequested: device => {
|
||||
root.persistHiddenInputDeviceNames(root.hiddenInputDeviceNames.filter(n => n !== device.name));
|
||||
}
|
||||
|
||||
onResetRequested: device => {
|
||||
AudioService.removeDeviceAlias(device.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,12 @@ Rectangle {
|
||||
required property var deviceNode
|
||||
property string deviceType: "output"
|
||||
|
||||
property bool showHideButton: false
|
||||
property bool isHidden: false
|
||||
|
||||
signal editRequested(var deviceNode)
|
||||
signal resetRequested(var deviceNode)
|
||||
signal hideRequested(var deviceNode)
|
||||
|
||||
width: parent?.width ?? 0
|
||||
height: deviceRowContent.height + Theme.spacingM * 2
|
||||
@@ -127,6 +131,21 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: hideButton
|
||||
visible: root.showHideButton
|
||||
buttonSize: 36
|
||||
iconName: root.isHidden ? "visibility" : "visibility_off"
|
||||
iconSize: 20
|
||||
backgroundColor: Theme.surfaceContainerHigh
|
||||
iconColor: root.isHidden ? Theme.primary : Theme.surfaceVariantText
|
||||
tooltipText: root.isHidden ? I18n.tr("Show device") : I18n.tr("Hide device")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: {
|
||||
root.hideRequested(root.deviceNode);
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
id: editButton
|
||||
buttonSize: 36
|
||||
@@ -136,6 +155,7 @@ Rectangle {
|
||||
iconColor: Theme.buttonText
|
||||
tooltipText: I18n.tr("Set custom name")
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: !root.isHidden
|
||||
onClicked: {
|
||||
root.editRequested(root.deviceNode);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ Item {
|
||||
property bool showValue: true
|
||||
property bool isDragging: false
|
||||
property bool wheelEnabled: true
|
||||
property bool centerMinimum: false
|
||||
property real valueOverride: -1
|
||||
property bool alwaysShowValue: false
|
||||
readonly property bool containsMouse: sliderMouseArea.containsMouse
|
||||
@@ -30,6 +31,8 @@ Item {
|
||||
|
||||
function updateValueFromPosition(x) {
|
||||
let ratio = Math.max(0, Math.min(1, (x - sliderHandle.width / 2) / (sliderTrack.width - sliderHandle.width)));
|
||||
if (centerMinimum)
|
||||
ratio = Math.max(0, (ratio - 0.5) * 2);
|
||||
let rawValue = minimum + ratio * (maximum - minimum);
|
||||
let newValue = step > 1 ? Math.round(rawValue / step) * step : Math.round(rawValue);
|
||||
newValue = Math.max(minimum, Math.min(maximum, newValue));
|
||||
@@ -70,7 +73,9 @@ Item {
|
||||
height: parent.height
|
||||
radius: Theme.cornerRadius
|
||||
width: {
|
||||
const ratio = (slider.value - slider.minimum) / (slider.maximum - slider.minimum);
|
||||
const range = slider.maximum - slider.minimum;
|
||||
const rawRatio = range === 0 ? 0 : (slider.value - slider.minimum) / range;
|
||||
const ratio = slider.centerMinimum ? (0.5 + rawRatio * 0.5) : rawRatio;
|
||||
const travel = sliderTrack.width - sliderHandle.width;
|
||||
const center = (travel * ratio) + sliderHandle.width / 2;
|
||||
return Math.max(0, Math.min(sliderTrack.width, center));
|
||||
@@ -87,7 +92,9 @@ Item {
|
||||
height: 24
|
||||
radius: Theme.cornerRadius
|
||||
x: {
|
||||
const ratio = (slider.value - slider.minimum) / (slider.maximum - slider.minimum);
|
||||
const range = slider.maximum - slider.minimum;
|
||||
const rawRatio = range === 0 ? 0 : (slider.value - slider.minimum) / range;
|
||||
const ratio = slider.centerMinimum ? (0.5 + rawRatio * 0.5) : rawRatio;
|
||||
const travel = sliderTrack.width - width;
|
||||
return Math.max(0, Math.min(travel, travel * ratio));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user