1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 05:25:41 -05:00

Media Update

This commit is contained in:
purian23
2025-09-13 19:46:41 -04:00
parent 2c451b9779
commit 77bc129dfc

View File

@@ -25,13 +25,6 @@ Item {
}
}
onAllPlayersChanged: {
if (allPlayers) {
for (let i = 0; i < allPlayers.length; i++) {
}
}
}
property string lastValidTitle: ""
property string lastValidArtist: ""
property string lastValidAlbum: ""
@@ -54,6 +47,50 @@ Item {
implicitWidth: 700
implicitHeight: 410
function getAudioDeviceIcon(device) {
if (!device || !device.name) return "speaker"
const name = device.name.toLowerCase()
if (name.includes("bluez") || name.includes("bluetooth"))
return "headset"
if (name.includes("hdmi"))
return "tv"
if (name.includes("usb"))
return "headset"
if (name.includes("analog") || name.includes("built-in"))
return "speaker"
return "speaker"
}
function getVolumeIcon(sink) {
if (!sink || !sink.audio) return "volume_off"
const volume = sink.audio.volume
const muted = sink.audio.muted
if (muted || volume === 0.0) return "volume_off"
if (volume <= 0.33) return "volume_down"
if (volume <= 0.66) return "volume_up"
return "volume_up"
}
function withAlpha(color, alpha) {
return Qt.rgba(color.r, color.g, color.b, alpha)
}
readonly property var dropdownStyle: ({
backgroundColor: withAlpha(Theme.surfaceContainer, 0.98),
borderColor: withAlpha(Theme.outline, 0.6),
borderWidth: 2,
cornerRadius: Theme.cornerRadius * 2,
shadowOffset: 8,
shadowBlur: 1.0,
shadowColor: Qt.rgba(0, 0, 0, 0.4),
shadowOpacity: 0.7,
animationDuration: Theme.mediumDuration
})
property bool isSeeking: false
@@ -73,106 +110,108 @@ Item {
}
}
ColorQuantizer {
id: colorQuantizer
source: {
const artUrl = (root.activePlayer && root.activePlayer.trackArtUrl) || root.lastValidArtUrl || ""
if (!artUrl) return ""
const urlString = String(artUrl)
if (!urlString || typeof urlString !== 'string') return ""
if (urlString.includes("scdn.co")) {
return urlString.replace(/640x640|300x300|64x64/, "640x640").replace("http://", "https://")
} else if (urlString.startsWith("file://")) {
return urlString
} else if (urlString.includes("googleusercontent.com") || urlString.includes("ytimg.com") || urlString.includes("youtube.com")) {
if (urlString.includes("=")) {
return urlString.replace(/=w\d+-h\d+/, "=w640-h640").replace(/=s\d+/, "=s640")
} else {e
return urlString + "=w640-h640"
}
} else if (urlString.includes("ggpht.com")) {
return urlString.includes("=") ? urlString.replace(/=s\d+/, "=s640") : urlString + "=s640"
} else if (urlString.includes("discordapp.com") || urlString.includes("discord.com")) {
return urlString
} else if (urlString.includes("soundcloud.com")) {
return urlString.replace("large.jpg", "t500x500.jpg")
} else if (urlString.includes("bandcamp.com")) {
return urlString.replace("_10.jpg", "_2.jpg").replace("_16.jpg", "_2.jpg")
} else if (urlString.includes("last.fm") || urlString.includes("lastfm.")) {
return urlString.replace("/174s/", "/300x300/").replace("/64s/", "/300x300/")
} else if (urlString.includes("tidal.com")) {
return urlString.replace(/\/\d+x\d+\//, "/640x640/")
}
return urlString
}
depth: 4
rescaleSize: 128
source: (root.activePlayer?.trackArtUrl) || root.lastValidArtUrl || ""
depth: 6
onSourceChanged: {
if (source) {
root.colorsExtracted = false
colorFallbackTimer.restart()
const playerName = root.activePlayer ? root.activePlayer.identity : "Unknown"
const sourceString = String(source)
let sourceDomain = "local"
if (sourceString.startsWith("file://")) {
if (sourceString.includes(".com.google.Chrome")) {
sourceDomain = "chrome-temp"
} else if (sourceString.includes("/tmp/")) {
sourceDomain = "temp-file"
} else {
sourceDomain = "local-file"
}
} else if (sourceString.includes("//")) {
const parts = sourceString.split("/")
sourceDomain = parts.length > 2 ? parts[2] : "unknown-url"
}
}
}
onColorsChanged: {
if (colors.length > 0) {
let blackColorCount = 0
for (let i = 0; i < Math.min(colors.length, 10); i++) {
const color = colors[i]
const luminance = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b
if (luminance < 0.02) {
blackColorCount++
}
}
const blackRatio = blackColorCount / Math.min(colors.length, 10)
if (blackRatio > 0.8) {
colorFallbackTimer.restart()
return
}
colorFallbackTimer.stop()
root.extractedDominantColor = colors[0]
root.extractedAccentColor = colors.length > 2 ? colors[2] : (colors.length > 1 ? colors[1] : colors[0])
let dominantColor = colors[0]
let accentColor = colors.length > 2 ? colors[2] : (colors.length > 1 ? colors[1] : colors[0])
if (isVeryDarkColor(dominantColor)) {
dominantColor = enhanceColorForBackground(dominantColor)
}
if (isVeryDarkColor(accentColor)) {
accentColor = enhanceColorForBackground(accentColor)
}
if (getColorSaturation(dominantColor) < 0.15 && colors.length > 1) {
for (let i = 1; i < Math.min(colors.length, 6); i++) {
if (getColorSaturation(colors[i]) > getColorSaturation(dominantColor)) {
dominantColor = enhanceColorForBackground(colors[i])
break
}
}
}
root.extractedDominantColor = dominantColor
root.extractedAccentColor = accentColor
root.colorsExtracted = true
}
}
}
function isVeryDarkColor(color) {
const luminance = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b
return luminance < 0.15
}
function getColorSaturation(color) {
const max = Math.max(color.r, color.g, color.b)
const min = Math.min(color.r, color.g, color.b)
if (max === 0) return 0
return (max - min) / max
}
function enhanceColorForBackground(color) {
const luminance = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b
if (luminance < 0.2) {
const boost = 0.4 / Math.max(luminance, 0.05)
return Qt.rgba(
Math.min(1.0, color.r * boost),
Math.min(1.0, color.g * boost),
Math.min(1.0, color.b * boost),
color.a
)
}
return color
}
Timer {
id: colorFallbackTimer
interval: {
const source = String(colorQuantizer.source)
if (source.includes(".com.google.Chrome") && source.includes("/tmp/")) {
return 500
} else if (source.includes("scdn.co") || source.includes("spotify.com")) {
return 2500
}
return 3000
}
interval: 3000
onTriggered: {
if (!root.colorsExtracted) {
const playerName = root.activePlayer ? root.activePlayer.identity : "Unknown"
const source = String(colorQuantizer.source)
if (source.includes("scdn.co") || source.includes("spotify.com")) {
console.info(`Spotify CORS block expected for ${playerName} - using theme colors`)
} else if (source.includes(".com.google.Chrome") && source.includes("/tmp/")) {
console.info(`Chrome temporary file inaccessible for ${playerName} - using theme colors`)
} else {
console.warn(`ColorQuantizer timeout for ${playerName} image:`, source)
console.warn("Using fallback colors - network or CORS issue likely")
}
root.extractedDominantColor = Theme.primary
root.extractedAccentColor = Theme.secondary
root.extractedDominantColor = Qt.rgba(
Theme.primary.r * 0.7 + 0.3 * 0.5,
Theme.primary.g * 0.7 + 0.3 * 0.5,
Theme.primary.b * 0.7 + 0.3 * 0.5,
Theme.primary.a
)
root.extractedAccentColor = Qt.rgba(
Theme.secondary.r * 0.8 + 0.2 * 0.4,
Theme.secondary.g * 0.8 + 0.2 * 0.4,
Theme.secondary.b * 0.8 + 0.2 * 0.4,
Theme.secondary.a
)
root.colorsExtracted = true
}
}
@@ -294,12 +333,10 @@ Item {
return node.audio && node.isSink && !node.isStream
})
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.98)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.6)
border.width: 2
radius: Theme.cornerRadius * 2
color: dropdownStyle.backgroundColor
border.color: dropdownStyle.borderColor
border.width: dropdownStyle.borderWidth
radius: dropdownStyle.cornerRadius
opacity: audioDevicesButton.devicesExpanded ? 1 : 0
@@ -308,18 +345,18 @@ Item {
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
shadowVerticalOffset: 8
shadowBlur: 1.0
shadowColor: Qt.rgba(0, 0, 0, 0.4)
shadowOpacity: 0.7
shadowVerticalOffset: dropdownStyle.shadowOffset
shadowBlur: dropdownStyle.shadowBlur
shadowColor: dropdownStyle.shadowColor
shadowOpacity: dropdownStyle.shadowOpacity
}
Behavior on height {
NumberAnimation { duration: Theme.mediumDuration }
NumberAnimation { duration: dropdownStyle.animationDuration }
}
Behavior on opacity {
NumberAnimation { duration: Theme.mediumDuration }
NumberAnimation { duration: dropdownStyle.animationDuration }
}
Column {
@@ -356,7 +393,7 @@ Item {
width: parent.width
height: 48
radius: Theme.cornerRadius
color: deviceMouseAreaLeft.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, index % 2 === 0 ? 0.3 : 0.2)
color: deviceMouseAreaLeft.containsMouse ? withAlpha(Theme.primary, 0.12) : withAlpha(Theme.surfaceVariant, index % 2 === 0 ? 0.3 : 0.2)
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: modelData === AudioService.sink ? 2 : 1
@@ -368,16 +405,7 @@ Item {
width: parent.width - Theme.spacingM * 2
DankIcon {
name: {
if (modelData.name.includes("bluez") || modelData.name.includes("bluetooth"))
return "headset"
else if (modelData.name.includes("hdmi"))
return "tv"
else if (modelData.name.includes("usb"))
return "headset"
else
return "speaker"
}
name: getAudioDeviceIcon(modelData)
size: 20
color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
@@ -446,10 +474,10 @@ Item {
clip: true
z: 150
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.98)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.6)
border.width: 2
radius: Theme.cornerRadius * 2
color: dropdownStyle.backgroundColor
border.color: dropdownStyle.borderColor
border.width: dropdownStyle.borderWidth
radius: dropdownStyle.cornerRadius
opacity: playerSelectorButton.playersExpanded ? 1 : 0
@@ -457,18 +485,18 @@ Item {
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
shadowVerticalOffset: 8
shadowBlur: 1.0
shadowColor: Qt.rgba(0, 0, 0, 0.4)
shadowOpacity: 0.7
shadowVerticalOffset: dropdownStyle.shadowOffset
shadowBlur: dropdownStyle.shadowBlur
shadowColor: dropdownStyle.shadowColor
shadowOpacity: dropdownStyle.shadowOpacity
}
Behavior on height {
NumberAnimation { duration: Theme.mediumDuration }
NumberAnimation { duration: dropdownStyle.animationDuration }
}
Behavior on opacity {
NumberAnimation { duration: Theme.mediumDuration }
NumberAnimation { duration: dropdownStyle.animationDuration }
}
Column {
@@ -555,11 +583,7 @@ Item {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData && modelData.identity) {
console.log("Switching to player:", modelData.identity)
// Pause the currently active player before switching
if (activePlayer && activePlayer !== modelData && activePlayer.canPause) {
console.log("Pausing current player:", activePlayer.identity)
activePlayer.pause()
}
@@ -581,15 +605,14 @@ Item {
}
}
}
}
}
// Center Column: Main Media Content
ColumnLayout {
x: 72 // 48 + 24 spacing
y: 20 // Adjusted top position for better centering
width: 484 // 700 - 72 (left) - 144 (right for floating buttons) = 484
height: 370 // Fixed height to fit within container (410 - 40 margin)
spacing: Theme.spacingXS // More compact spacing
x: 72
y: 20
width: 484
height: 370
spacing: Theme.spacingXS
Item {
width: parent.width
@@ -806,7 +829,6 @@ Item {
width: parent.width
Layout.fillHeight: true
// Song Info
Column {
id: songInfo
width: parent.width
@@ -1307,8 +1329,8 @@ Item {
radius: 20
x: parent.width - 40 - Theme.spacingM
y: 235
color: volumeButtonArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.8)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
color: volumeButtonArea.containsMouse ? withAlpha(Theme.primary, 0.2) : withAlpha(Theme.surfaceVariant, 0.8)
border.color: withAlpha(Theme.outline, 0.3)
border.width: 1
z: 100
@@ -1316,17 +1338,7 @@ Item {
DankIcon {
anchors.centerIn: parent
name: {
if (!defaultSink) return "volume_off"
let volume = defaultSink.audio.volume
let muted = defaultSink.audio.muted
if (muted || volume === 0.0) return "volume_off"
if (volume <= 0.33) return "volume_down"
if (volume <= 0.66) return "volume_up"
return "volume_up"
}
name: getVolumeIcon(defaultSink)
size: 18
color: defaultSink && !defaultSink.audio.muted && defaultSink.audio.volume > 0 ? Theme.primary : Theme.surfaceText
}
@@ -1477,7 +1489,7 @@ Item {
radius: 20
x: parent.width - 40 - Theme.spacingM
y: 290
color: audioDevicesArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.8)
color: audioDevicesArea.containsMouse ? withAlpha(Theme.primary, 0.2) : withAlpha(Theme.surfaceVariant, 0.8)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
border.width: 1
z: 100