1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-08 04:09:15 -04:00

feat: unify media controls dropdown interactions, hover behavior and cycle controls (#2470)

* feat: unify media controls dropdown interactions, hover behavior and cycle controls

- Implement hover-to-show and hover-to-hide for all media control dropdowns.
- Make clicking the Output Devices and Media Players buttons cycle through items when expanded.
- Always display the 'speaker' icon for Output Devices to maintain visual consistency.
- Bind dropdown player properties dynamically to fix list stale rendering states.

* fix(DankDash): use trackArtist property for artist label in MediaPlayerTab

* fix(DankDash): simplify active player label for consistency with output devices

* feat(DankDash): display volume levels for audio output devices in dropdown

* fix(DankDash): display Unknown Artist when artist is empty in player list

* feat(DankDash): add keyboard shortcuts for seeking, track cycling and playback control in Media popout

* feat(DankDash): change Up/Down arrow keys to adjust volume in Media popout

* feat(DankDash): auto-open volume dropdown overlay when using Up/Down shortcuts

* feat(DankDash): add Key M shortcut to toggle mute in Media popout

* fix(mpris): clamp minimum seek position to 0.1s to prevent browser player reset

* fix(mpris): cache stable length to prevent browser transient reset issues

* fix(mpris): persist activePlayerStableLength in MprisController singleton

* fix(mpris): resolve browser player album art with raw metadata and YouTube url fallbacks

* fix(mpris): resolve browser player album art with local caching and 16:9 youtube fallbacks

* style(mpris): trim trailing whitespace in TrackArtService

* fix(mpris): address code review feedback on remote caching, stale artwork, and hover state

* fix: secure curl commands and prevent premature dropdown overlays closing on button re-hover
This commit is contained in:
Huỳnh Thiện Lộc
2026-05-27 00:44:51 +07:00
committed by GitHub
parent 12a744e985
commit 89f86be00a
9 changed files with 411 additions and 109 deletions
+6 -2
View File
@@ -8,15 +8,19 @@ Item {
id: root
property MprisPlayer activePlayer
property string artUrl: (activePlayer?.trackArtUrl) || ""
property string artUrl: TrackArtService.resolvedArtUrl
property string lastValidArtUrl: ""
property alias albumArtStatus: albumArt.imageStatus
property real albumSize: Math.min(width, height) * 0.88
property bool showAnimation: true
property real animationScale: 1.0
onActivePlayerChanged: {
lastValidArtUrl = "";
}
onArtUrlChanged: {
if (artUrl && albumArt.status !== Image.Error) {
if (artUrl && albumArtStatus !== Image.Error) {
lastValidArtUrl = artUrl;
}
}
+19 -17
View File
@@ -8,12 +8,14 @@ Item {
id: root
property MprisPlayer activePlayer
readonly property real stableLength: MprisController.activePlayerStableLength
property real seekPreviewRatio: -1
readonly property real playerValue: {
if (!activePlayer || activePlayer.length <= 0)
if (!activePlayer || stableLength <= 0)
return 0;
const pos = (activePlayer.position || 0) % Math.max(1, activePlayer.length);
const calculatedRatio = pos / activePlayer.length;
const pos = (activePlayer.position || 0) % Math.max(1, stableLength);
const calculatedRatio = pos / stableLength;
return Math.max(0, Math.min(1, calculatedRatio));
}
property real value: seekPreviewRatio >= 0 ? seekPreviewRatio : playerValue
@@ -29,20 +31,20 @@ Item {
}
function ratioForPosition(position) {
if (!activePlayer || activePlayer.length <= 0)
if (!activePlayer || stableLength <= 0)
return 0;
return clampRatio(position / activePlayer.length);
return clampRatio(position / stableLength);
}
function positionForRatio(ratio) {
if (!activePlayer || activePlayer.length <= 0)
if (!activePlayer || stableLength <= 0)
return 0;
const rawPosition = clampRatio(ratio) * activePlayer.length;
return Math.min(rawPosition, activePlayer.length * 0.99);
const rawPosition = clampRatio(ratio) * stableLength;
return Math.min(rawPosition, stableLength * 0.99);
}
function updatePreviewFromMouse(mouseX, width) {
if (!activePlayer || activePlayer.length <= 0 || width <= 0)
if (!activePlayer || stableLength <= 0 || width <= 0)
return;
seekPreviewRatio = clampRatio(mouseX / width);
}
@@ -68,7 +70,7 @@ Item {
mouseArea.pressX = mouse.x;
clearCommittedSeekPreview();
holdTimer.restart();
if (activePlayer && activePlayer.length > 0 && activePlayer.canSeek) {
if (activePlayer && stableLength > 0 && activePlayer.canSeek) {
updatePreviewFromMouse(mouse.x, width);
mouseArea.pendingSeekPosition = positionForRatio(seekPreviewRatio);
}
@@ -78,9 +80,9 @@ Item {
holdTimer.stop();
isSeeking = false;
isDraggingSeek = false;
if (mouseArea.pendingSeekPosition >= 0 && activePlayer && activePlayer.canSeek && activePlayer.length > 0) {
const clamped = Math.min(mouseArea.pendingSeekPosition, activePlayer.length * 0.99);
activePlayer.position = clamped;
if (mouseArea.pendingSeekPosition >= 0 && activePlayer && activePlayer.canSeek && stableLength > 0) {
const clamped = Math.min(mouseArea.pendingSeekPosition, stableLength * 0.99);
activePlayer.position = Math.max(0.1, clamped);
mouseArea.pendingSeekPosition = -1;
beginCommittedSeekPreview(clamped);
} else {
@@ -89,7 +91,7 @@ Item {
}
function handleSeekPositionChanged(mouse, width, mouseArea) {
if (mouseArea.pressed && isSeeking && activePlayer && activePlayer.length > 0 && activePlayer.canSeek) {
if (mouseArea.pressed && isSeeking && activePlayer && stableLength > 0 && activePlayer.canSeek) {
if (!isDraggingSeek && Math.abs(mouse.x - mouseArea.pressX) >= dragThreshold)
isDraggingSeek = true;
updatePreviewFromMouse(mouse.x, width);
@@ -129,7 +131,7 @@ Item {
Loader {
anchors.fill: parent
visible: activePlayer && activePlayer.length > 0
visible: activePlayer && stableLength > 0
sourceComponent: SettingsData.waveProgressEnabled ? waveProgressComponent : flatProgressComponent
z: 1
@@ -148,7 +150,7 @@ Item {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
enabled: activePlayer && activePlayer.canSeek && activePlayer.length > 0
enabled: activePlayer && activePlayer.canSeek && stableLength > 0
property real pendingSeekPosition: -1
property real pressX: 0
@@ -236,7 +238,7 @@ Item {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
enabled: activePlayer && activePlayer.canSeek && activePlayer.length > 0
enabled: activePlayer && activePlayer.canSeek && stableLength > 0
property real pendingSeekPosition: -1
property real pressX: 0