From 8cbbbb8b50279cee43059f3ab9d5c373a95d767f Mon Sep 17 00:00:00 2001 From: purian23 Date: Sat, 12 Jul 2025 19:23:12 -0400 Subject: [PATCH] Add media controls on the top bar media widget --- Widgets/TopBar/MediaWidget.qml | 176 +++++++++++++++++++++++++++------ 1 file changed, 148 insertions(+), 28 deletions(-) diff --git a/Widgets/TopBar/MediaWidget.qml b/Widgets/TopBar/MediaWidget.qml index 31b95e57..dc5f1f9f 100644 --- a/Widgets/TopBar/MediaWidget.qml +++ b/Widgets/TopBar/MediaWidget.qml @@ -6,17 +6,15 @@ Rectangle { id: root property var activePlayer: null - property bool hasActiveMedia: activePlayer && (activePlayer.trackTitle || activePlayer.trackArtist) + property bool hasActiveMedia: false signal clicked() visible: hasActiveMedia - width: hasActiveMedia ? Math.min(200, mediaText.implicitWidth + Theme.spacingS * 2 + 20 + Theme.spacingXS) : 0 + width: hasActiveMedia ? Math.min(280, mediaRow.implicitWidth + Theme.spacingS * 2) : 0 height: 30 radius: Theme.cornerRadius - color: mediaArea.containsMouse ? - Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : - Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) + color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) Behavior on color { ColorAnimation { @@ -33,35 +31,157 @@ Rectangle { } Row { + id: mediaRow anchors.centerIn: parent spacing: Theme.spacingXS - AudioVisualization { - width: 20 - height: Theme.iconSize - anchors.verticalCenter: parent.verticalCenter - hasActiveMedia: root.hasActiveMedia - activePlayer: root.activePlayer + // Media info section (clickable to open full player) + Row { + id: mediaInfo + spacing: Theme.spacingXS + + AudioVisualization { + width: 20 + height: Theme.iconSize + anchors.verticalCenter: parent.verticalCenter + hasActiveMedia: root.hasActiveMedia + activePlayer: root.activePlayer + } + + Text { + id: mediaText + anchors.verticalCenter: parent.verticalCenter + width: 140 + + text: { + if (!activePlayer) return "Unknown Track" + + // Check if it's web media by looking at player identity + let identity = activePlayer.identity || "" + let isWebMedia = identity.toLowerCase().includes("firefox") || + identity.toLowerCase().includes("chrome") || + identity.toLowerCase().includes("chromium") || + identity.toLowerCase().includes("edge") || + identity.toLowerCase().includes("safari") + + let title = "" + let subtitle = "" + + if (isWebMedia && activePlayer.trackTitle) { + title = activePlayer.trackTitle + subtitle = activePlayer.trackArtist || identity + } else { + title = activePlayer.trackTitle || "Unknown Track" + subtitle = activePlayer.trackArtist || "" + } + + // Truncate title and subtitle to fit in available space - more generous limits + if (title.length > 20) title = title.substring(0, 20) + "..." + if (subtitle.length > 22) subtitle = subtitle.substring(0, 22) + "..." + + return subtitle.length > 0 ? title + " • " + subtitle : title + } + + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Medium + elide: Text.ElideRight + + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: root.clicked() + } + } } - Text { - id: mediaText - text: activePlayer?.trackTitle || "Unknown Track" - font.pixelSize: Theme.fontSizeSmall - color: Theme.surfaceText - font.weight: Font.Medium + // Control buttons + Row { + spacing: Theme.spacingXS anchors.verticalCenter: parent.verticalCenter - width: Math.min(implicitWidth, 150) - elide: Text.ElideRight + + // Previous button + Rectangle { + width: 20 + height: 20 + radius: 10 + anchors.verticalCenter: parent.verticalCenter + color: prevArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" + visible: activePlayer && activePlayer.canGoPrevious + + Text { + anchors.centerIn: parent + text: "skip_previous" + font.family: Theme.iconFont + font.pixelSize: 12 + color: Theme.surfaceText + } + + MouseArea { + id: prevArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + if (activePlayer) activePlayer.previous() + } + } + } + + // Play/Pause button + Rectangle { + width: 24 + height: 24 + radius: 12 + anchors.verticalCenter: parent.verticalCenter + color: activePlayer?.playbackState === 1 ? Theme.primary : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) + + Text { + anchors.centerIn: parent + text: activePlayer?.playbackState === 1 ? "pause" : "play_arrow" + font.family: Theme.iconFont + font.pixelSize: 14 + color: activePlayer?.playbackState === 1 ? Theme.background : Theme.primary + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + if (activePlayer) activePlayer.togglePlaying() + } + } + } + + // Next button + Rectangle { + width: 20 + height: 20 + radius: 10 + anchors.verticalCenter: parent.verticalCenter + color: nextArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" + visible: activePlayer && activePlayer.canGoNext + + Text { + anchors.centerIn: parent + text: "skip_next" + font.family: Theme.iconFont + font.pixelSize: 12 + color: Theme.surfaceText + } + + MouseArea { + id: nextArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + if (activePlayer) activePlayer.next() + } + } + } } } - - MouseArea { - id: mediaArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - - onClicked: root.clicked() - } } \ No newline at end of file