From 8e5e003f8ab806dd022245c038408b0f671ea4a9 Mon Sep 17 00:00:00 2001 From: Sakari <20642596+sakarie9@users.noreply.github.com> Date: Fri, 17 Oct 2025 14:57:26 +0800 Subject: [PATCH 1/2] MediaMini: implement dynamic width with max width setting --- Assets/Translations/de.json | 4 ++ Assets/Translations/en.json | 4 ++ Assets/Translations/es.json | 4 ++ Assets/Translations/fr.json | 4 ++ Assets/Translations/pt.json | 4 ++ Assets/Translations/zh-CN.json | 4 ++ Modules/Bar/Widgets/MediaMini.qml | 54 +++++++++++++++++-- .../Bar/WidgetSettings/MediaMiniSettings.qml | 11 ++++ Services/BarWidgetRegistry.qml | 1 + 9 files changed, 86 insertions(+), 4 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 2be6197b..8991324b 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -1071,6 +1071,10 @@ "label": "Visualizer-Typ", "description": "Stil des Audio-Visualizers auswählen." }, + "max-width": { + "label": "Maximale Breite", + "description": "Stellt die maximale Horizontalgröße des Widgets ein. Das Widget wird sich an kürzere Inhalte anpassen." + }, "scrolling-mode": { "label": "Scrollmodus", "description": "Steuern, wann Textscrolling für lange Track-Titel aktiviert ist." diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 915b75d1..15f35798 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -1054,6 +1054,10 @@ "label": "Visualizer type", "description": "Choose the style of audio visualizer to display." }, + "max-width": { + "label": "Maximum Width", + "description": "Sets the maximum horizontal size of the widget. The widget will shrink to fit shorter content." + }, "scrolling-mode": { "label": "Scrolling mode", "description": "Control when text scrolling is enabled for long track titles." diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 72251b3f..644ed5ba 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -1054,6 +1054,10 @@ "label": "Tipo de visualizador", "description": "Elegir el estilo de visualizador de audio a mostrar." }, + "max-width": { + "label": "Ancho Máximo", + "description": "Establece el tamaño horizontal máximo del widget. El widget se reducirá para adaptarse a contenido más corto." + }, "scrolling-mode": { "label": "Modo de desplazamiento", "description": "Controlar cuándo está habilitado el desplazamiento de texto para títulos de pista largos." diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 8399a63a..e4a78db2 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -1050,6 +1050,10 @@ "label": "Type de visualiseur", "description": "Choisir le style de visualiseur audio à afficher." }, + "max-width": { + "label": "Largeur Maximale", + "description": "Définit la taille horizontale maximale du widget. Le widget se rétrécira pour s'adapter à un contenu plus court." + }, "scrolling-mode": { "label": "Mode de défilement", "description": "Contrôler quand le défilement de texte est activé pour les titres de piste longs." diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index c4c3ea52..e2901797 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -1054,6 +1054,10 @@ "label": "Tipo de visualizador", "description": "Escolher o estilo de visualizador de áudio a exibir." }, + "max-width": { + "label": "Largura Máxima", + "description": "Define o tamanho horizontal máximo do widget. O widget será reduzido para se adequar a conteúdo mais curto." + }, "scrolling-mode": { "label": "Modo de rolagem", "description": "Controlar quando a rolagem de texto está habilitada para títulos de faixa longos." diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 0116a5da..27504728 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -1054,6 +1054,10 @@ "label": "可视化器类型", "description": "选择要显示的音频可视化器样式。" }, + "max-width": { + "label": "最大宽度", + "description": "设置小部件的最大水平尺寸。当内容较短时,小部件会自动收缩以适应内容。" + }, "scrolling-mode": { "label": "滚动模式", "description": "控制何时为长曲目标题启用文本滚动。" diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index 470bc37e..7f538b54 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -38,8 +38,8 @@ Item { readonly property string visualizerType: (widgetSettings.visualizerType !== undefined && widgetSettings.visualizerType !== "") ? widgetSettings.visualizerType : widgetMetadata.visualizerType readonly property string scrollingMode: (widgetSettings.scrollingMode !== undefined) ? widgetSettings.scrollingMode : widgetMetadata.scrollingMode - // Fixed width - no expansion - readonly property real widgetWidth: Math.max(145, screen.width * 0.06) + // Maximum widget width with user settings support + readonly property real maxWidth: (widgetSettings.maxWidth !== undefined) ? widgetSettings.maxWidth : Math.max(widgetMetadata.maxWidth, screen.width * 0.06) readonly property bool hasActivePlayer: MediaService.currentPlayer !== null readonly property string placeholderText: I18n.tr("bar.widget-settings.media-mini.no-active-player") @@ -60,7 +60,7 @@ Item { } implicitHeight: visible ? (isVerticalBar ? calculatedVerticalDimension() : Style.barHeight) : 0 - implicitWidth: visible ? (isVerticalBar ? calculatedVerticalDimension() : widgetWidth) : 0 + implicitWidth: visible ? (isVerticalBar ? calculatedVerticalDimension() : dynamicWidth) : 0 // "visible": Always Visible, "hidden": Hide When Empty, "transparent": Transparent When Empty visible: hideMode !== "hidden" || hasActivePlayer @@ -80,6 +80,44 @@ Item { return Math.round((Style.baseWidgetSize - 5) * scaling) } + function calculateContentWidth() { + // Calculate the actual content width based on visible elements + var contentWidth = 0 + var margins = Style.marginS * scaling * 2 // Left and right margins + + // Icon or album art width + if (!hasActivePlayer || !showAlbumArt) { + // Icon width + contentWidth += Style.fontSizeL * scaling + } else if (showAlbumArt && hasActivePlayer) { + // Album art width + contentWidth += 21 * scaling + } + + // Spacing between icon/art and text + contentWidth += Style.marginS * scaling + + // Text width (use the measured width) + contentWidth += fullTitleMetrics.contentWidth + + // Additional small margin for text + contentWidth += Style.marginXXS * 2 + + // Add container margins + contentWidth += margins + + return Math.ceil(contentWidth) + } + + // Dynamic width: adapt to content but respect maximum width setting + readonly property real dynamicWidth: { + if (!hasActivePlayer) { + return maxWidth + } + // Use content width but don't exceed user-set maximum width + return Math.min(calculateContentWidth(), maxWidth) + } + // A hidden text element to safely measure the full title width NText { id: fullTitleMetrics @@ -95,11 +133,19 @@ Item { visible: root.visible anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter - width: isVerticalBar ? root.width : (widgetWidth) + width: isVerticalBar ? root.width : dynamicWidth height: isVerticalBar ? width : Style.capsuleHeight radius: isVerticalBar ? width / 2 : Style.radiusM color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + // Smooth width transition + Behavior on width { + NumberAnimation { + duration: Style.animationNormal + easing.type: Easing.InOutCubic + } + } + Item { id: mainContainer anchors.fill: parent diff --git a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml index 1d03c87f..6d778510 100644 --- a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml @@ -19,6 +19,7 @@ ColumnLayout { property bool valueShowVisualizer: widgetData.showVisualizer !== undefined ? widgetData.showVisualizer : widgetMetadata.showVisualizer property string valueVisualizerType: widgetData.visualizerType || widgetMetadata.visualizerType property string valueScrollingMode: widgetData.scrollingMode || widgetMetadata.scrollingMode + property int valueMaxWidth: widgetData.maxWidth !== undefined ? widgetData.maxWidth : widgetMetadata.maxWidth Component.onCompleted: { if (widgetData && widgetData.hideMode !== undefined) { @@ -33,6 +34,7 @@ ColumnLayout { settings.showVisualizer = valueShowVisualizer settings.visualizerType = valueVisualizerType settings.scrollingMode = valueScrollingMode + settings.maxWidth = parseInt(widthInput.text) || widgetMetadata.maxWidth return settings } @@ -87,6 +89,15 @@ ColumnLayout { minimumWidth: 200 } + NTextInput { + id: widthInput + Layout.fillWidth: true + label: I18n.tr("bar.widget-settings.media-mini.max-width.label") + description: I18n.tr("bar.widget-settings.media-mini.max-width.description") + placeholderText: widgetMetadata.maxWidth + text: valueMaxWidth + } + NComboBox { label: I18n.tr("bar.widget-settings.media-mini.scrolling-mode.label") description: I18n.tr("bar.widget-settings.media-mini.scrolling-mode.description") diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml index bd134591..f23a7b16 100644 --- a/Services/BarWidgetRegistry.qml +++ b/Services/BarWidgetRegistry.qml @@ -88,6 +88,7 @@ Singleton { "hideMode": "hidden", "scrollingMode"// "visible", "hidden", "transparent" : "hover", + "maxWidth": 145, "showAlbumArt": false, "showVisualizer": false, "visualizerType": "linear" From 19bfeb2a40f6b5ac4f7f8e1f64ac0c719bdddc9b Mon Sep 17 00:00:00 2001 From: Sakari <20642596+sakarie9@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:28:32 +0800 Subject: [PATCH 2/2] MediaMini: add fixed width option --- Assets/Translations/de.json | 4 ++++ Assets/Translations/en.json | 4 ++++ Assets/Translations/es.json | 4 ++++ Assets/Translations/fr.json | 4 ++++ Assets/Translations/pt.json | 4 ++++ Assets/Translations/zh-CN.json | 4 ++++ Modules/Bar/Widgets/MediaMini.qml | 6 ++++++ .../Settings/Bar/WidgetSettings/MediaMiniSettings.qml | 9 +++++++++ Services/BarWidgetRegistry.qml | 1 + 9 files changed, 40 insertions(+) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 8991324b..21110d4f 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -1075,6 +1075,10 @@ "label": "Maximale Breite", "description": "Stellt die maximale Horizontalgröße des Widgets ein. Das Widget wird sich an kürzere Inhalte anpassen." }, + "use-fixed-width": { + "label": "Feste Breite verwenden", + "description": "Wenn aktiviert, verwendet das Widget immer die maximale Breite, anstatt sich dynamisch an den Inhalt anzupassen." + }, "scrolling-mode": { "label": "Scrollmodus", "description": "Steuern, wann Textscrolling für lange Track-Titel aktiviert ist." diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 15f35798..7ad8c91b 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -1058,6 +1058,10 @@ "label": "Maximum Width", "description": "Sets the maximum horizontal size of the widget. The widget will shrink to fit shorter content." }, + "use-fixed-width": { + "label": "Use Fixed Width", + "description": "When enabled, the widget will always use the maximum width instead of dynamically adjusting to content." + }, "scrolling-mode": { "label": "Scrolling mode", "description": "Control when text scrolling is enabled for long track titles." diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 644ed5ba..cbb96e68 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -1058,6 +1058,10 @@ "label": "Ancho Máximo", "description": "Establece el tamaño horizontal máximo del widget. El widget se reducirá para adaptarse a contenido más corto." }, + "use-fixed-width": { + "label": "Usar Ancho Fijo", + "description": "Cuando está activado, el widget siempre usará el ancho máximo en lugar de ajustarse dinámicamente al contenido." + }, "scrolling-mode": { "label": "Modo de desplazamiento", "description": "Controlar cuándo está habilitado el desplazamiento de texto para títulos de pista largos." diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index e4a78db2..e783353d 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -1054,6 +1054,10 @@ "label": "Largeur Maximale", "description": "Définit la taille horizontale maximale du widget. Le widget se rétrécira pour s'adapter à un contenu plus court." }, + "use-fixed-width": { + "label": "Utiliser une Largeur Fixe", + "description": "Lorsque activé, le widget utilisera toujours la largeur maximale au lieu de s'ajuster dynamiquement au contenu." + }, "scrolling-mode": { "label": "Mode de défilement", "description": "Contrôler quand le défilement de texte est activé pour les titres de piste longs." diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index e2901797..48bea69a 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -1058,6 +1058,10 @@ "label": "Largura Máxima", "description": "Define o tamanho horizontal máximo do widget. O widget será reduzido para se adequar a conteúdo mais curto." }, + "use-fixed-width": { + "label": "Usar Largura Fixa", + "description": "Quando ativado, o widget sempre usará a largura máxima em vez de ajustar dinamicamente ao conteúdo." + }, "scrolling-mode": { "label": "Modo de rolagem", "description": "Controlar quando a rolagem de texto está habilitada para títulos de faixa longos." diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 27504728..1fc13bda 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -1058,6 +1058,10 @@ "label": "最大宽度", "description": "设置小部件的最大水平尺寸。当内容较短时,小部件会自动收缩以适应内容。" }, + "use-fixed-width": { + "label": "使用固定宽度", + "description": "启用后,小部件将始终使用最大宽度,而不根据内容动态调整。" + }, "scrolling-mode": { "label": "滚动模式", "description": "控制何时为长曲目标题启用文本滚动。" diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index 7f538b54..38a56a34 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -40,6 +40,7 @@ Item { // Maximum widget width with user settings support readonly property real maxWidth: (widgetSettings.maxWidth !== undefined) ? widgetSettings.maxWidth : Math.max(widgetMetadata.maxWidth, screen.width * 0.06) + readonly property bool useFixedWidth: (widgetSettings.useFixedWidth !== undefined) ? widgetSettings.useFixedWidth : widgetMetadata.useFixedWidth readonly property bool hasActivePlayer: MediaService.currentPlayer !== null readonly property string placeholderText: I18n.tr("bar.widget-settings.media-mini.no-active-player") @@ -111,6 +112,11 @@ Item { // Dynamic width: adapt to content but respect maximum width setting readonly property real dynamicWidth: { + // If using fixed width mode, always use maxWidth + if (useFixedWidth) { + return maxWidth + } + // Otherwise, adapt to content if (!hasActivePlayer) { return maxWidth } diff --git a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml index 6d778510..5e109feb 100644 --- a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml @@ -20,6 +20,7 @@ ColumnLayout { property string valueVisualizerType: widgetData.visualizerType || widgetMetadata.visualizerType property string valueScrollingMode: widgetData.scrollingMode || widgetMetadata.scrollingMode property int valueMaxWidth: widgetData.maxWidth !== undefined ? widgetData.maxWidth : widgetMetadata.maxWidth + property bool valueUseFixedWidth: widgetData.useFixedWidth !== undefined ? widgetData.useFixedWidth : widgetMetadata.useFixedWidth Component.onCompleted: { if (widgetData && widgetData.hideMode !== undefined) { @@ -35,6 +36,7 @@ ColumnLayout { settings.visualizerType = valueVisualizerType settings.scrollingMode = valueScrollingMode settings.maxWidth = parseInt(widthInput.text) || widgetMetadata.maxWidth + settings.useFixedWidth = valueUseFixedWidth return settings } @@ -98,6 +100,13 @@ ColumnLayout { text: valueMaxWidth } + NToggle { + label: I18n.tr("bar.widget-settings.media-mini.use-fixed-width.label") + description: I18n.tr("bar.widget-settings.media-mini.use-fixed-width.description") + checked: valueUseFixedWidth + onToggled: checked => valueUseFixedWidth = checked + } + NComboBox { label: I18n.tr("bar.widget-settings.media-mini.scrolling-mode.label") description: I18n.tr("bar.widget-settings.media-mini.scrolling-mode.description") diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml index f23a7b16..ad78c31f 100644 --- a/Services/BarWidgetRegistry.qml +++ b/Services/BarWidgetRegistry.qml @@ -89,6 +89,7 @@ Singleton { "scrollingMode"// "visible", "hidden", "transparent" : "hover", "maxWidth": 145, + "useFixedWidth": false, "showAlbumArt": false, "showVisualizer": false, "visualizerType": "linear"