diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index e060a3b9..ddd3b90f 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -904,9 +904,9 @@ "search-placeholder": "Widgets suchen..." }, "active-window": { - "auto-hide": { - "label": "Automatisch ausblenden", - "description": "Widget automatisch ausblenden, wenn kein Fenster aktiv ist." + "hide-mode": { + "label": "Ausblendmodus", + "description": "Steuert das Verhalten des Widgets, wenn kein Fenster aktiv ist." }, "show-app-icon": { "label": "App-Symbol anzeigen", @@ -1053,9 +1053,9 @@ } }, "media-mini": { - "auto-hide": { - "label": "Automatisch ausblenden", - "description": "Widget automatisch ausblenden, wenn keine Medien abgespielt werden." + "hide-mode": { + "label": "Ausblendmodus", + "description": "Steuert das Verhalten des Widgets, wenn keine Medien abgespielt werden." }, "show-album-art": { "label": "Albumcover anzeigen", diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 186651a4..d82db9cb 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -888,9 +888,9 @@ "search-placeholder": "Search widget..." }, "active-window": { - "auto-hide": { - "label": "Hide automatically", - "description": "Automatically hide the widget when no window is active." + "hide-mode": { + "label": "Hiding mode", + "description": "Controls how the widget behaves when no window is active." }, "show-app-icon": { "label": "Show app icon", @@ -1037,9 +1037,9 @@ } }, "media-mini": { - "auto-hide": { - "label": "Hide automatically", - "description": "Automatically hide the widget when no media is playing." + "hide-mode": { + "label": "Hiding mode", + "description": "Controls how the widget behaves when no media is playing." }, "show-album-art": { "label": "Show album art", @@ -1346,6 +1346,11 @@ "hover": "Scroll On Hover", "never": "Never Scroll" }, + "hide-modes": { + "visible": "Always Visible", + "hidden": "Hide When Empty", + "transparent": "Transparent When Empty" + }, "frame-rates": { "fps": "{fps} FPS" }, diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 3e08444f..56c614ac 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -887,9 +887,9 @@ "search-placeholder": "Buscar widgets..." }, "active-window": { - "auto-hide": { - "label": "Ocultar automáticamente", - "description": "Ocultar automáticamente el widget cuando no hay ventana activa." + "hide-mode": { + "label": "Modo de ocultación", + "description": "Controla el comportamiento del widget cuando no hay ventana activa." }, "show-app-icon": { "label": "Mostrar icono de la aplicación", @@ -1036,9 +1036,9 @@ } }, "media-mini": { - "auto-hide": { - "label": "Ocultar automáticamente", - "description": "Ocultar automáticamente el widget cuando no se está reproduciendo ningún medio." + "hide-mode": { + "label": "Modo de ocultación", + "description": "Controla el comportamiento del widget cuando no se está reproduciendo ningún medio." }, "show-album-art": { "label": "Mostrar arte del álbum", diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 92d98109..3fdc976d 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -895,9 +895,9 @@ "label": "Mode de défilement", "description": "Contrôler quand le défilement de texte est activé pour les titres de fenêtre longs." }, - "auto-hide": { - "label": "Masquer automatiquement", - "description": "Masquer automatiquement le widget quand aucune fenêtre n'est active." + "hide-mode": { + "label": "Mode de masquage", + "description": "Contrôle le comportement du widget lorsqu'aucune fenêtre n'est active." }, "width": { "description": "Contrôle la taille horizontale du widget.", @@ -1052,9 +1052,9 @@ "label": "Mode de défilement", "description": "Contrôler quand le défilement de texte est activé pour les titres de piste longs." }, - "auto-hide": { - "label": "Masquer automatiquement", - "description": "Masquer automatiquement le widget quand aucun média n'est en cours de lecture." + "hide-mode": { + "label": "Mode de masquage", + "description": "Contrôle le comportement du widget lorsqu'aucun média n'est en cours de lecture." }, "no-active-player": "Aucun lecteur actif" }, diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 3eef70e8..0470c9b5 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -887,9 +887,9 @@ "search-placeholder": "Pesquisar widgets..." }, "active-window": { - "auto-hide": { - "label": "Ocultar automaticamente", - "description": "Ocultar automaticamente o widget quando nenhuma janela está ativa." + "hide-mode": { + "label": "Modo de ocultação", + "description": "Controla o comportamento do widget quando nenhuma janela está ativa." }, "show-app-icon": { "label": "Mostrar ícone do aplicativo", @@ -1036,9 +1036,9 @@ } }, "media-mini": { - "auto-hide": { - "label": "Ocultar automaticamente", - "description": "Ocultar automaticamente o widget quando nenhuma mídia está sendo reproduzida." + "hide-mode": { + "label": "Modo de ocultação", + "description": "Controla o comportamento do widget quando nenhuma mídia está sendo reproduzida." }, "show-album-art": { "label": "Mostrar arte do álbum", diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 7896ba76..8ee42f65 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -887,9 +887,9 @@ "search-placeholder": "搜索小部件..." }, "active-window": { - "auto-hide": { - "label": "自动隐藏", - "description": "当没有活动窗口时自动隐藏小部件。" + "hide-mode": { + "label": "隐藏模式", + "description": "控制当没有活动窗口时小部件的行为。" }, "show-app-icon": { "label": "显示应用图标", @@ -1036,9 +1036,9 @@ } }, "media-mini": { - "auto-hide": { - "label": "自动隐藏", - "description": "当没有媒体播放时自动隐藏小部件。" + "hide-mode": { + "label": "隐藏模式", + "description": "控制当没有媒体播放时小部件的行为。" }, "show-album-art": { "label": "显示专辑封面", diff --git a/Modules/Bar/Widgets/ActiveWindow.qml b/Modules/Bar/Widgets/ActiveWindow.qml index 80aa96e3..6a10a095 100644 --- a/Modules/Bar/Widgets/ActiveWindow.qml +++ b/Modules/Bar/Widgets/ActiveWindow.qml @@ -30,7 +30,7 @@ Item { return {} } - readonly property bool hasActiveWindow: CompositorService.getFocusedWindowTitle() !== "" + readonly property bool hasFocusedWindow: CompositorService.getFocusedWindow() !== null readonly property string windowTitle: CompositorService.getFocusedWindowTitle() || "No active window" readonly property string fallbackIcon: "user-desktop" @@ -38,14 +38,16 @@ Item { // Widget settings - matching MediaMini pattern readonly property bool showIcon: (widgetSettings.showIcon !== undefined) ? widgetSettings.showIcon : widgetMetadata.showIcon - readonly property bool autoHide: (widgetSettings.autoHide !== undefined) ? widgetSettings.autoHide : widgetMetadata.autoHide + readonly property string hideMode: (widgetSettings.hideMode !== undefined) ? widgetSettings.hideMode : widgetMetadata.hideMode readonly property string scrollingMode: (widgetSettings.scrollingMode !== undefined) ? widgetSettings.scrollingMode : (widgetMetadata.scrollingMode !== undefined ? widgetMetadata.scrollingMode : "hover") readonly property int widgetWidth: (widgetSettings.width !== undefined) ? widgetSettings.width : Math.max(widgetMetadata.width, screen.width * 0.06) implicitHeight: visible ? ((barPosition === "left" || barPosition === "right") ? calculatedVerticalHeight() : Style.barHeight) : 0 implicitWidth: visible ? ((barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8) : (widgetWidth)) : 0 - opacity: !autoHide || hasActiveWindow ? 1.0 : 0 + // "visible": Always Visible, "hidden": Hide When Empty, "transparent": Transparent When Empty + visible: hideMode !== "hidden" || hasFocusedWindow + opacity: hideMode !== "transparent" || hasFocusedWindow ? 1.0 : 0 Behavior on opacity { NumberAnimation { duration: Style.animationNormal diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index e916dda9..8c72af9a 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -32,7 +32,7 @@ Item { readonly property string barPosition: Settings.data.bar.position readonly property bool compact: (Settings.data.bar.density === "compact") || (Settings.data.bar.density === "mini") - readonly property bool autoHide: (widgetSettings.autoHide !== undefined) ? widgetSettings.autoHide : widgetMetadata.autoHide + readonly property string hideMode: (widgetSettings.hideMode !== undefined) ? widgetSettings.hideMode : "hidden" // "visible", "hidden", "transparent" 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 @@ -41,7 +41,7 @@ Item { // Fixed width - no expansion readonly property real widgetWidth: Math.max(145, screen.width * 0.06) - readonly property bool hasActivePlayer: MediaService.currentPlayer !== null && getTitle() !== "" + readonly property bool hasActivePlayer: MediaService.currentPlayer !== null readonly property string placeholderText: I18n.tr("bar.widget-settings.media-mini.no-active-player") readonly property string tooltipText: { @@ -62,7 +62,9 @@ Item { implicitHeight: visible ? ((barPosition === "left" || barPosition === "right") ? calculatedVerticalHeight() : Style.barHeight) : 0 implicitWidth: visible ? ((barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8) : (widgetWidth)) : 0 - opacity: !autoHide || hasActivePlayer || (!hasActivePlayer && !autoHide) ? 1.0 : 0 + // "visible": Always Visible, "hidden": Hide When Empty, "transparent": Transparent When Empty + visible: hideMode !== "hidden" || hasActivePlayer + opacity: hideMode !== "transparent" || hasActivePlayer ? 1.0 : 0 Behavior on opacity { NumberAnimation { duration: Style.animationNormal diff --git a/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml b/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml index acd6e785..e6eb8191 100644 --- a/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml @@ -15,14 +15,20 @@ ColumnLayout { // Local state property bool valueShowIcon: widgetData.showIcon !== undefined ? widgetData.showIcon : widgetMetadata.showIcon - property bool valueAutoHide: widgetData.autoHide !== undefined ? widgetData.autoHide : widgetMetadata.autoHide + property string valueHideMode: "hidden" // Default to 'Hide When Empty' property string valueScrollingMode: widgetData.scrollingMode || widgetMetadata.scrollingMode property int valueWidth: widgetData.width !== undefined ? widgetData.width : widgetMetadata.width property bool valueColorizeIcons: widgetData.colorizeIcons !== undefined ? widgetData.colorizeIcons : widgetMetadata.colorizeIcons + Component.onCompleted: { + if (widgetData && widgetData.hideMode !== undefined) { + valueHideMode = widgetData.hideMode + } + } + function saveSettings() { var settings = Object.assign({}, widgetData || {}) - settings.autoHide = valueAutoHide + settings.hideMode = valueHideMode settings.showIcon = valueShowIcon settings.scrollingMode = valueScrollingMode settings.width = parseInt(widthInput.text) || widgetMetadata.width @@ -30,12 +36,24 @@ ColumnLayout { return settings } - NToggle { + NComboBox { Layout.fillWidth: true - label: I18n.tr("bar.widget-settings.active-window.auto-hide.label") - description: I18n.tr("bar.widget-settings.active-window.auto-hide.description") - checked: root.valueAutoHide - onToggled: checked => root.valueAutoHide = checked + label: I18n.tr("bar.widget-settings.active-window.hide-mode.label") + description: I18n.tr("bar.widget-settings.active-window.hide-mode.description") + model: [ + { + "key": "visible", + "name": I18n.tr("options.hide-modes.visible") + }, { + "key": "hidden", + "name": I18n.tr("options.hide-modes.hidden") + }, { + "key": "transparent", + "name": I18n.tr("options.hide-modes.transparent") + } + ] + currentKey: root.valueHideMode + onSelected: key => root.valueHideMode = key } NToggle { diff --git a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml index 4f14d91b..a7580143 100644 --- a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml @@ -14,15 +14,21 @@ ColumnLayout { property var widgetMetadata: null // Local state - property bool valueAutoHide: widgetData.autoHide !== undefined ? widgetData.autoHide : widgetMetadata.autoHide + property string valueHideMode: "hidden" // Default to 'Hide When Empty' 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 + Component.onCompleted: { + if (widgetData && widgetData.hideMode !== undefined) { + valueHideMode = widgetData.hideMode + } + } + function saveSettings() { var settings = Object.assign({}, widgetData || {}) - settings.autoHide = valueAutoHide + settings.hideMode = valueHideMode settings.showAlbumArt = valueShowAlbumArt settings.showVisualizer = valueShowVisualizer settings.visualizerType = valueVisualizerType @@ -30,12 +36,24 @@ ColumnLayout { return settings } - NToggle { + NComboBox { Layout.fillWidth: true - label: I18n.tr("bar.widget-settings.media-mini.auto-hide.label") - description: I18n.tr("bar.widget-settings.media-mini.auto-hide.description") - checked: root.valueAutoHide - onToggled: checked => root.valueAutoHide = checked + label: I18n.tr("bar.widget-settings.media-mini.hide-mode.label") + description: I18n.tr("bar.widget-settings.media-mini.hide-mode.description") + model: [ + { + "key": "visible", + "name": I18n.tr("options.hide-modes.visible") + }, { + "key": "hidden", + "name": I18n.tr("options.hide-modes.hidden") + }, { + "key": "transparent", + "name": I18n.tr("options.hide-modes.transparent") + } + ] + currentKey: root.valueHideMode + onSelected: key => root.valueHideMode = key } NToggle { diff --git a/Modules/Settings/SettingsPanel.qml b/Modules/Settings/SettingsPanel.qml index 2f4579e2..e5b64566 100644 --- a/Modules/Settings/SettingsPanel.qml +++ b/Modules/Settings/SettingsPanel.qml @@ -11,8 +11,8 @@ import qs.Widgets NPanel { id: root - preferredWidth: 800 * Style.uiScaleRatio - preferredHeight: 900 * Style.uiScaleRatio + preferredWidth: 820 * Style.uiScaleRatio + preferredHeight: 940 * Style.uiScaleRatio panelAnchorHorizontalCenter: true panelAnchorVerticalCenter: true diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml index f2809e14..260012ba 100644 --- a/Services/BarWidgetRegistry.qml +++ b/Services/BarWidgetRegistry.qml @@ -41,7 +41,7 @@ Singleton { "ActiveWindow": { "allowUserSettings": true, "showIcon": true, - "autoHide": false, + "hideMode": "hidden", // "visible", "hidden", "transparent" "scrollingMode": "hover", "width": 145, "colorizeIcons": false @@ -84,7 +84,7 @@ Singleton { }, "MediaMini": { "allowUserSettings": true, - "autoHide": false, + "hideMode": "hidden", // "visible", "hidden", "transparent" "scrollingMode": "hover", "showAlbumArt": false, "showVisualizer": false, diff --git a/Services/IPCService.qml b/Services/IPCService.qml index 0edea8d3..a62e2474 100644 --- a/Services/IPCService.qml +++ b/Services/IPCService.qml @@ -43,6 +43,14 @@ Item { function clear() { NotificationService.clearHistory() } + + function dismissOldest() { + NotificationService.dismissOldestActive() + } + + function dismissAll() { + NotificationService.dismissAllActive() + } } IpcHandler { diff --git a/Services/NotificationService.qml b/Services/NotificationService.qml index 2a4d23ce..249a5845 100644 --- a/Services/NotificationService.qml +++ b/Services/NotificationService.qml @@ -414,6 +414,13 @@ Singleton { removeActive(id) } + function dismissOldestActive() { + if (activeList.count > 0) { + const lastNotif = activeList.get(activeList.count - 1) + dismissActiveNotification(lastNotif.id) + } + } + function dismissAllActive() { Object.values(activeMap).forEach(n => n.dismiss()) activeList.clear()