MediaMini: small fixes

This commit is contained in:
Ly-sec
2025-09-25 01:37:17 +02:00
parent 4de6489cbf
commit 2123b55aab
11 changed files with 98 additions and 87 deletions
+7 -1
View File
@@ -851,7 +851,8 @@
"media-mini": {
"show-album-art": "Albumcover anzeigen",
"show-visualizer": "Visualizer anzeigen",
"visualizer-type": "Visualizer-Typ"
"visualizer-type": "Visualizer-Typ",
"scrolling-mode": "Scrollmodus"
},
"clock": {
"use-primary-color": {
@@ -1068,6 +1069,11 @@
"mirrored": "Gespiegelt",
"wave": "Welle"
},
"scrolling-modes": {
"always": "Immer Scrollen",
"hover": "Beim Hover Scrollen",
"never": "Nie Scrollen"
},
"screen-recording": {
"sources": {
+7 -1
View File
@@ -863,7 +863,8 @@
"media-mini": {
"show-album-art": "Show album art",
"show-visualizer": "Show visualizer",
"visualizer-type": "Visualizer type"
"visualizer-type": "Visualizer type",
"scrolling-mode": "Scrolling mode"
},
"clock": {
"use-primary-color": {
@@ -1080,6 +1081,11 @@
"mirrored": "Mirrored",
"wave": "Wave"
},
"scrolling-modes": {
"always": "Scroll Always",
"hover": "Scroll On Hover",
"never": "Never Scroll"
},
"screen-recording": {
"sources": {
+7 -1
View File
@@ -861,7 +861,8 @@
"media-mini": {
"show-album-art": "Mostrar carátula del álbum",
"show-visualizer": "Mostrar visualizador",
"visualizer-type": "Tipo de visualizador"
"visualizer-type": "Tipo de visualizador",
"scrolling-mode": "Modo de desplazamiento"
},
"clock": {
"use-primary-color": {
@@ -1077,6 +1078,11 @@
"mirrored": "Espejado",
"wave": "Onda"
},
"scrolling-modes": {
"always": "Desplazar Siempre",
"hover": "Desplazar al Pasar",
"never": "Nunca Desplazar"
},
"screen-recording": {
"sources": {
"portal": "Portal",
+7 -1
View File
@@ -859,7 +859,8 @@
"media-mini": {
"show-album-art": "Afficher la pochette de l'album",
"show-visualizer": "Afficher le visualiseur",
"visualizer-type": "Type de visualiseur"
"visualizer-type": "Type de visualiseur",
"scrolling-mode": "Mode de défilement"
},
"clock": {
"use-primary-color": {
@@ -1077,6 +1078,11 @@
"mirrored": "Miroir",
"wave": "Vague"
},
"scrolling-modes": {
"always": "Défiler Toujours",
"hover": "Défiler au Survol",
"never": "Ne Jamais Défiler"
},
"frame-rates": {
"30-fps": "30 FPS",
"60-fps": "60 FPS",
+2 -1
View File
@@ -861,7 +861,8 @@
"media-mini": {
"show-album-art": "Mostrar arte do álbum",
"show-visualizer": "Mostrar visualizador",
"visualizer-type": "Tipo de visualizador"
"visualizer-type": "Tipo de visualizador",
"scrolling-mode": "Modo de rolagem"
},
"clock": {
"use-primary-color": {
+3 -3
View File
@@ -1,5 +1,5 @@
{
"settingsVersion": 5,
"settingsVersion": 6,
"bar": {
"position": "top",
"backgroundOpacity": 1,
@@ -141,7 +141,7 @@
"cavaFrameRate": 60,
"visualizerType": "linear",
"mprisBlacklist": [],
"preferredPlayer": "",
"preferredPlayer": ""
},
"ui": {
"fontDefault": "Roboto",
@@ -185,4 +185,4 @@
"wallpaperChange": "",
"darkModeChange": ""
}
}
}
+2 -4
View File
@@ -54,7 +54,7 @@ Singleton {
// Then it should be commented out again, regular users don't need to generate
// default settings on every start
// TODO: automate this someday!
// generateDefaultSettings()
//generateDefaultSettings()
// Patch-in the local default, resolved to user's home
adapter.general.avatarImage = defaultAvatar
@@ -114,7 +114,7 @@ Singleton {
JsonAdapter {
id: adapter
property int settingsVersion: 5
property int settingsVersion: 6
// bar
property JsonObject bar: JsonObject {
@@ -266,8 +266,6 @@ Singleton {
property string visualizerType: "linear"
property list<string> mprisBlacklist: []
property string preferredPlayer: ""
property bool scrollingTitle: false
property int scrollingSpeed: 18
}
// ui
+42 -53
View File
@@ -36,12 +36,10 @@ Item {
readonly property bool showAlbumArt: (widgetSettings.showAlbumArt !== undefined) ? widgetSettings.showAlbumArt : widgetMetadata.showAlbumArt
readonly property bool showVisualizer: (widgetSettings.showVisualizer !== undefined) ? widgetSettings.showVisualizer : widgetMetadata.showVisualizer
readonly property string visualizerType: (widgetSettings.visualizerType !== undefined && widgetSettings.visualizerType !== "") ? widgetSettings.visualizerType : widgetMetadata.visualizerType
readonly property bool scrollingTitle: Settings.data.audio.scrollingTitle
readonly property int scrollingSpeed: Settings.data.audio.scrollingSpeed
readonly property string scrollingMode: (widgetSettings.scrollingMode !== undefined) ? widgetSettings.scrollingMode : widgetMetadata.scrollingMode
// 6% of total width
readonly property real minWidth: Math.max(1, screen.width * 0.06)
readonly property real maxWidth: minWidth * 2
// Fixed width - no expansion
readonly property real widgetWidth: Math.max(1, screen.width * 0.06)
function getTitle() {
return MediaService.trackTitle + (MediaService.trackArtist !== "" ? ` - ${MediaService.trackArtist}` : "")
@@ -51,20 +49,8 @@ Item {
return Math.round(Style.baseWidgetSize * 0.8 * scaling)
}
function calculatedHorizontalWidth() {
let total = Style.marginM * 2 * scaling // internal padding
if (showAlbumArt) {
total += 18 * scaling + 2 * scaling // album art + spacing
} else {
total += Style.fontSizeL * scaling + 2 * scaling // icon + spacing
}
total += Math.min(fullTitleMetrics.contentWidth, maxWidth * scaling) // title text
// Row layout handles spacing between widgets
return total
}
implicitHeight: visible ? ((barPosition === "left" || barPosition === "right") ? calculatedVerticalHeight() : Math.round(Style.barHeight * scaling)) : 0
implicitWidth: visible ? ((barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (rowLayout.implicitWidth + Style.marginM * 2 * scaling)) : 0
implicitWidth: visible ? ((barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (widgetWidth * scaling)) : 0
visible: MediaService.currentPlayer !== null && MediaService.canPlay
@@ -81,7 +67,7 @@ Item {
visible: root.visible
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: (barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (rowLayout.implicitWidth + Style.marginM * 2 * scaling)
width: (barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (widgetWidth * scaling)
height: (barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : Math.round(Style.capsuleHeight * scaling)
radius: (barPosition === "left" || barPosition === "right") ? width / 2 : Math.round(Style.radiusM * scaling)
color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent
@@ -185,52 +171,55 @@ Item {
Item {
id: titleContainer
Layout.preferredWidth: {
if (mouseArea.containsMouse) {
return Math.round(Math.min(fullTitleMetrics.contentWidth, root.maxWidth * scaling))
} else {
return Math.round(Math.min(fullTitleMetrics.contentWidth, root.minWidth * scaling))
}
}
Layout.preferredWidth: widgetWidth * scaling
Layout.alignment: Qt.AlignVCenter
Layout.preferredHeight: titleText.height
clip: true
property bool shouldScroll: scrollingTitle && fullTitleMetrics.contentWidth > titleContainer.width
property bool isScrolling: false
// Start scrolling when text is too long and not hovering
// Timer for "always" mode with delay
Timer {
id: scrollStartTimer
interval: 2000 // Wait 2 seconds before starting scroll
repeat: false
onTriggered: {
if (titleContainer.shouldScroll && !mouseArea.containsMouse) {
if (scrollingMode === "always" && fullTitleMetrics.contentWidth > titleContainer.width) {
titleContainer.isScrolling = true
}
}
}
// Reset scroll position when text changes or on hover
onShouldScrollChanged: {
if (shouldScroll && !mouseArea.containsMouse) {
scrollStartTimer.restart()
} else {
scrollStartTimer.stop()
// Update scrolling state based on mode - using property instead of function
property var updateScrollingState: function () {
if (scrollingMode === "never") {
isScrolling = false
} else if (scrollingMode === "always") {
if (fullTitleMetrics.contentWidth > titleContainer.width) {
if (mouseArea.containsMouse) {
isScrolling = false
} else {
scrollStartTimer.restart()
}
} else {
scrollStartTimer.stop()
isScrolling = false
}
} else if (scrollingMode === "hover") {
isScrolling = mouseArea.containsMouse && fullTitleMetrics.contentWidth > titleContainer.width
}
}
// React to text changes
onWidthChanged: updateScrollingState()
Component.onCompleted: updateScrollingState()
// React to hover changes from the main mouse area
Connections {
target: mouseArea
function onContainsMouseChanged() {
if (mouseArea.containsMouse) {
scrollStartTimer.stop()
titleContainer.isScrolling = false
} else if (titleContainer.shouldScroll) {
scrollStartTimer.restart()
}
titleContainer.updateScrollingState()
}
}
@@ -255,7 +244,7 @@ Item {
NumberAnimation {
from: 0
to: -(fullTitleMetrics.contentWidth - titleContainer.width)
duration: scrollingSpeed * 1000 // Convert seconds to milliseconds
duration: Math.max(3000, getTitle().length * 100) // Compute from character count
easing.type: Easing.Linear
}
}
@@ -339,18 +328,18 @@ Item {
NTooltip {
id: tooltip
text: {
if (barPosition === "left" || barPosition === "right") {
return getTitle()
} else {
var str = ""
if (MediaService.canGoNext) {
str += "Right click for next.\n"
}
if (MediaService.canGoPrevious) {
str += "Middle click for previous."
}
return str
var title = getTitle()
var controls = ""
if (MediaService.canGoNext) {
controls += "Right click for next.\n"
}
if (MediaService.canGoPrevious) {
controls += "Middle click for previous."
}
if (controls !== "") {
return title + "\n\n" + controls
}
return title
}
target: (barPosition === "left" || barPosition === "right") ? verticalLayout : anchor
positionLeft: barPosition === "right"
@@ -17,12 +17,14 @@ ColumnLayout {
property bool valueShowAlbumArt: widgetData.showAlbumArt !== undefined ? widgetData.showAlbumArt : widgetMetadata.showAlbumArt
property bool valueShowVisualizer: widgetData.showVisualizer !== undefined ? widgetData.showVisualizer : widgetMetadata.showVisualizer
property string valueVisualizerType: widgetData.visualizerType || widgetMetadata.visualizerType
property string valueScrollingMode: widgetData.scrollingMode || widgetMetadata.scrollingMode
function saveSettings() {
var settings = Object.assign({}, widgetData || {})
settings.showAlbumArt = valueShowAlbumArt
settings.showVisualizer = valueShowVisualizer
settings.visualizerType = valueVisualizerType
settings.scrollingMode = valueScrollingMode
return settings
}
@@ -55,4 +57,21 @@ ColumnLayout {
onSelected: key => valueVisualizerType = key
minimumWidth: 200 * scaling
}
NComboBox {
label: I18n.tr("bar.widget-settings.media-mini.scrolling-mode")
model: [{
"key": "always",
"name": I18n.tr("options.scrolling-modes.always")
}, {
"key": "hover",
"name": I18n.tr("options.scrolling-modes.hover")
}, {
"key": "never",
"name": I18n.tr("options.scrolling-modes.never")
}]
currentKey: valueScrollingMode
onSelected: key => valueScrollingMode = key
minimumWidth: 200 * scaling
}
}
-21
View File
@@ -385,27 +385,6 @@ ColumnLayout {
currentKey: Settings.data.audio.cavaFrameRate
onSelected: key => Settings.data.audio.cavaFrameRate = key
}
// Scrolling Title Settings
NToggle {
label: I18n.tr("settings.audio.media.scrolling-title.label")
description: I18n.tr("settings.audio.media.scrolling-title.description")
checked: Settings.data.audio.scrollingTitle
onToggled: checked => Settings.data.audio.scrollingTitle = checked
}
NSpinBox {
Layout.fillWidth: true
label: I18n.tr("settings.audio.media.scrolling-speed.label")
description: I18n.tr("settings.audio.media.scrolling-speed.description")
minimum: 5
maximum: 60
value: Settings.data.audio.scrollingSpeed
stepSize: 1
suffix: "s"
enabled: Settings.data.audio.scrollingTitle
onValueChanged: Settings.data.audio.scrollingSpeed = value
}
}
NDivider {
+2 -1
View File
@@ -98,7 +98,8 @@ Singleton {
"allowUserSettings": true,
"showAlbumArt": false,
"showVisualizer": false,
"visualizerType": "linear"
"visualizerType": "linear",
"scrollingMode": "hover"
},
"ControlCenter": {
"allowUserSettings": true,