Skip to content

Instantly share code, notes, and snippets.

@stanley2058
Last active December 6, 2022 13:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stanley2058/c4f7704125c27c3730e647bfad560655 to your computer and use it in GitHub Desktop.
Save stanley2058/c4f7704125c27c3730e647bfad560655 to your computer and use it in GitHub Desktop.
Fix issue with plasma Media Player Control not showing thumbnails from sites like YouTube

Fix issue with plasma Media Player Control not showing thumbnails

Replace the following file:

/usr/share/plasma/plasmoids/org.kde.plasma.mediacontroller/contents/ui/AlbumArtStackView.qml
/*
SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
SPDX-FileCopyrightText: 2014 Sebastian Kügler <sebas@kde.org>
SPDX-FileCopyrightText: 2014 Kai Uwe Broulik <kde@privat.broulik.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
id: container
/**
* Whether the album art image is available or in loading status
*/
readonly property bool hasImage: (root.albumArt && albumArt.empty)
|| (albumArt.currentItem instanceof Image && (albumArt.currentItem.status === Image.Ready || albumArt.currentItem.status === Image.Loading))
readonly property bool animating: exitTransition.running || popExitTransition.running
/**
* Whether the component is used in the compact representation
*/
property bool inCompactRepresentation: false
/**
* Provides source item for \ShaderEffectSource
*/
readonly property alias albumArt: albumArt
// HACK: fix media thumbnail not loading
function albumArtFixes(url) {
// expand this array for additional fixes
const replacing = [
{ match: "https://open.spotify.com", replace: "https://open.spotify.com", to: "https://i.scdn.co" },
{ match: "https://i.ytimg.com", replace: /\?.*/, to: "" },
]
for (const { match, replace, to } of replacing) {
if (url.startsWith(match)) {
url = url.replace(replace, to)
}
}
return url
}
function loadAlbumArt() {
if (!root.albumArt) {
albumArt.clear(StackView.PopTransition);
return;
}
const oldImageRatio = albumArt.currentItem instanceof Image ? albumArt.currentItem.sourceSize.width / albumArt.currentItem.sourceSize.height : 1;
const pendingImage = albumArtComponent.createObject(albumArt, {
// apply patches to the source
"source": albumArtFixes(root.albumArt),
"opacity": 0,
});
function replaceWhenLoaded() {
if (pendingImage.status === Image.Loading) {
return;
}
if (pendingImage.status === Image.Ready) {
const newImageRatio = pendingImage.sourceSize.width / pendingImage.sourceSize.height;
exitTransitionOpacityAnimator.duration = oldImageRatio === newImageRatio ? 0 : PlasmaCore.Units.longDuration;
} else {
// Load placeholder icon, but keep the invalid image to avoid flashing application icons
exitTransitionOpacityAnimator.duration = 0;
}
albumArt.replace(pendingImage, {}, StackView.ReplaceTransition);
pendingImage.statusChanged.disconnect(replaceWhenLoaded);
}
pendingImage.statusChanged.connect(replaceWhenLoaded);
replaceWhenLoaded();
}
StackView {
id: albumArt
anchors.fill: parent
readonly property string icon: (mpris2Source.currentData && mpris2Source.currentData["Desktop Icon Name"]) || "media-album-cover"
replaceEnter: Transition {
OpacityAnimator {
from: 0
to: 1
duration: PlasmaCore.Units.longDuration
}
}
replaceExit: Transition {
id: exitTransition
SequentialAnimation {
PauseAnimation {
duration: PlasmaCore.Units.longDuration
}
/**
* If the new ratio and the old ratio are different,
* perform a fade-out animation for the old image
* to prevent it from suddenly disappearing.
*/
OpacityAnimator {
id: exitTransitionOpacityAnimator
from: 1
to: 0
duration: 0
}
}
}
popExit: Transition {
id: popExitTransition
OpacityAnimator {
from: 1
to: 0
duration: PlasmaCore.Units.longDuration
}
}
Component {
id: albumArtComponent
Image { // Album Art
horizontalAlignment: Image.AlignRight
verticalAlignment: Image.AlignVCenter
fillMode: Image.PreserveAspectFit
asynchronous: true
cache: false
StackView.onRemoved: {
source = ""; // HACK: Reduce memory usage
destroy();
}
}
}
Component {
id: fallbackIconItem
PlasmaCore.IconItem { // Fallback
id: fallbackIcon
anchors.margins: PlasmaCore.Units.largeSpacing * 2
opacity: 0
source: albumArt.icon
NumberAnimation {
duration: PlasmaCore.Units.longDuration
easing.type: Easing.OutCubic
property: "opacity"
running: true
target: fallbackIcon
to: 1
}
}
}
// "No media playing" placeholder message
Component {
id: placeholderMessage
// Put PlaceholderMessage in Item so PlaceholderMessage will not fill its parent.
Item {
property alias source: message.iconName
PlasmaExtras.PlaceholderMessage {
id: message
anchors.centerIn: parent
width: parent.width // For text wrap
iconName: albumArt.icon
text: (root.isPlaying || root.state === "paused") ? i18n("No title") : i18n("No media playing")
}
}
}
}
Loader {
anchors.fill: parent
visible: active
active: (inCompactRepresentation || Plasmoid.expanded) && !container.hasImage
asynchronous: true
sourceComponent: root.track ? fallbackIconItem : placeholderMessage
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment