diff --git a/shell/applets/MprisApplet.qml b/shell/applets/MprisApplet.qml index e06c531..1dd4de6 100644 --- a/shell/applets/MprisApplet.qml +++ b/shell/applets/MprisApplet.qml @@ -306,50 +306,58 @@ Column { // Player switcher Item { width: root.width - height: root.players.length > 1 ? _playerFlow.implicitHeight + 6 : 0 + height: root.players.length > 1 ? 28 : 0 visible: root.players.length > 1 - Flow { - id: _playerFlow - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - width: parent.width - 16 - spacing: 6 + Flickable { + id: _switcher + anchors.centerIn: parent + width: Math.min(_playerRow.implicitWidth, parent.width - 16) + height: 22 + contentWidth: _playerRow.implicitWidth + clip: true - Repeater { - model: root.players + Row { + id: _playerRow + height: 22 + spacing: 6 - delegate: Rectangle { - required property var modelData - required property int index + Repeater { + model: root.players - readonly property bool _active: index === root.playerIdx + delegate: Rectangle { + required property var modelData + required property int index - width: _pLabel.implicitWidth + 12 - height: 18 - radius: 9 - color: _active ? S.Theme.base02 : (pHover.hovered ? S.Theme.base02 : "transparent") - border.color: _active ? root.accentColor : S.Theme.base03 - border.width: _active ? 1 : 0 + readonly property bool _active: index === root.playerIdx - Text { - id: _pLabel - anchors.centerIn: parent - text: modelData.identity ?? "Player" - color: _active ? root.accentColor : S.Theme.base04 - font.pixelSize: S.Theme.fontSize - 2 - font.family: S.Theme.fontFamily - font.bold: _active - } + width: _pLabel.implicitWidth + 12 + height: 18 + radius: 9 + color: _active ? S.Theme.base02 : (pHover.hovered ? S.Theme.base02 : "transparent") + border.color: _active ? root.accentColor : S.Theme.base03 + border.width: _active ? 1 : 0 + anchors.verticalCenter: parent.verticalCenter - HoverHandler { - id: pHover - cursorShape: Qt.PointingHandCursor - } + Text { + id: _pLabel + anchors.centerIn: parent + text: modelData.identity ?? "Player" + color: _active ? root.accentColor : S.Theme.base04 + font.pixelSize: S.Theme.fontSize - 2 + font.family: S.Theme.fontFamily + font.bold: _active + } - TapHandler { - onTapped: { - root.playerSwitched(index); + HoverHandler { + id: pHover + cursorShape: Qt.PointingHandCursor + } + + TapHandler { + onTapped: { + root.playerSwitched(index); + } } } } diff --git a/shell/services/MprisService.qml b/shell/services/MprisService.qml index c88aefa..d5941d5 100644 --- a/shell/services/MprisService.qml +++ b/shell/services/MprisService.qml @@ -1,7 +1,6 @@ pragma Singleton import QtQuick -import QtQml.Models import Quickshell.Services.Mpris QtObject { @@ -14,6 +13,7 @@ QtObject { property string _selectedIdentity: "" property var _lastPlayedTime: ({}) + property var _watchers: [] onPlayerChanged: { if (player) @@ -33,18 +33,33 @@ QtObject { } } - // Watch all raw players for state changes via Instantiator - - // delegates persist across state changes since the model only - // changes on player add/remove, not property changes - property Instantiator _stateWatchers: Instantiator { - model: Mpris.players - delegate: QtObject { - required property MprisPlayer modelData - property Connections _conn: Connections { - target: modelData - function onPlaybackStateChanged() { - root._onPlaybackStateChanged(modelData); - } + // Watch raw Mpris.players for add/remove - this does NOT fire on state changes + property Connections _mprisConn: Connections { + target: Mpris + function onPlayersChanged() { + root._reconnectWatchers(); + } + } + + function _reconnectWatchers() { + for (const w of _watchers) + w.destroy(); + + const raw = Mpris.players.values ?? []; + const newWatchers = []; + for (const p of raw) { + const conn = _watcherComp.createObject(root, { + target: p + }); + newWatchers.push(conn); + } + _watchers = newWatchers; + } + + property Component _watcherComp: Component { + Connections { + function onPlaybackStateChanged() { + root._onPlaybackStateChanged(target); } } } @@ -69,6 +84,7 @@ QtObject { } } } else if (p.playbackState === MprisPlaybackState.Paused && p === player) { + // Current player paused - switch to a playing one if available _switchToPlaying(); } } @@ -123,4 +139,6 @@ QtObject { if (players[idx]) _selectedIdentity = players[idx].identity ?? ""; } + + Component.onCompleted: _reconnectWatchers() }