fix(bar): harden AudioVisualizer when ShellScreen is null

This commit is contained in:
Lysec
2026-03-31 21:04:03 +02:00
parent 90e37a1e53
commit 4f523301c9
11 changed files with 159 additions and 22 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

+7 -3
View File
@@ -45,8 +45,8 @@ Item {
readonly property bool shouldShow: (currentVisualizerType !== "" && currentVisualizerType !== "none") && (!hideWhenIdle || MediaService.isPlaying)
// Register/unregister with SpectrumService based on visibility
readonly property string spectrumComponentId: "bar:audiovisualizer:" + root.screen.name + ":" + root.section + ":" + root.sectionWidgetIndex
// Register/unregister with SpectrumService based on visibility (use screenName — screen can be null after DPMS/output changes)
readonly property string spectrumComponentId: "bar:audiovisualizer:" + screenName + ":" + root.section + ":" + root.sectionWidgetIndex
onShouldShowChanged: {
if (root.shouldShow) {
@@ -140,14 +140,16 @@ Item {
onTriggered: action => {
contextMenu.close();
if (screen) {
PanelService.closeContextMenu(screen);
}
if (action === "cycle-visualizer") {
const types = ["linear", "mirrored", "wave"];
const currentIndex = types.indexOf(currentVisualizerType);
const nextIndex = (currentIndex + 1) % types.length;
Settings.data.audio.visualizerType = types[nextIndex];
} else if (action === "widget-settings") {
} else if (action === "widget-settings" && screen) {
BarService.openWidgetSettings(screen, section, sectionWidgetIndex, widgetId, widgetSettings);
}
}
@@ -163,7 +165,9 @@ Item {
onClicked: mouse => {
if (mouse.button === Qt.RightButton) {
if (screen) {
PanelService.showContextMenu(contextMenu, root, screen);
}
} else {
const types = ["linear", "mirrored", "wave"];
const currentIndex = types.indexOf(currentVisualizerType);
+48 -2
View File
@@ -108,12 +108,35 @@ NBox {
spacing: Style.marginL
Layout.fillWidth: true
NIcon {
Item {
Layout.preferredWidth: mainWeatherIconSide
Layout.preferredHeight: mainWeatherIconSide
Layout.alignment: Qt.AlignVCenter
readonly property int mainWeatherIconSide: Math.round(Style.fontSizeXXXL * 1.75 * Style.uiScaleRatio * 1.6)
NIcon {
visible: !LocationService.taliaWeatherMascotDayActive || !weatherReady
anchors.centerIn: parent
icon: weatherReady ? LocationService.weatherSymbolFromCode(LocationService.data.weather.current_weather.weathercode, LocationService.data.weather.current_weather.is_day) : "weather-cloud-off"
pointSize: Style.fontSizeXXXL * 1.75
color: Color.mPrimary
}
Loader {
active: LocationService.taliaWeatherMascotDayActive && weatherReady
anchors.fill: parent
asynchronous: true
sourceComponent: Component {
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
smooth: true
mipmap: true
asynchronous: true
source: Qt.resolvedUrl(LocationService.taliaWeatherImageFromCode(currentWeatherCode, isDayTime))
}
}
}
}
ColumnLayout {
spacing: Style.marginXXS
@@ -186,12 +209,35 @@ NBox {
}
color: Color.mOnSurface
}
NIcon {
Item {
Layout.preferredWidth: forecastWeatherIconSide
Layout.preferredHeight: forecastWeatherIconSide
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
readonly property int forecastWeatherIconSide: Math.round(Style.fontSizeXXL * 1.6 * Style.uiScaleRatio * 1.6)
NIcon {
visible: !LocationService.taliaWeatherMascotDayActive
anchors.centerIn: parent
icon: LocationService.weatherSymbolFromCode(LocationService.data.weather.daily.weathercode[index])
pointSize: Style.fontSizeXXL * 1.6
color: Color.mPrimary
}
Loader {
active: LocationService.taliaWeatherMascotDayActive
anchors.fill: parent
asynchronous: true
sourceComponent: Component {
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
smooth: true
mipmap: true
asynchronous: true
source: Qt.resolvedUrl(LocationService.taliaWeatherImageFromCode(LocationService.data.weather.daily.weathercode[index]))
}
}
}
}
NText {
Layout.alignment: Qt.AlignHCenter
text: {
@@ -62,11 +62,27 @@ DraggableDesktopWidget {
Layout.alignment: Qt.AlignVCenter
NIcon {
visible: !LocationService.taliaWeatherMascotDayActive || !weatherReady
anchors.centerIn: parent
icon: weatherReady ? LocationService.weatherSymbolFromCode(currentWeatherCode, LocationService.data.weather.current_weather.is_day) : "weather-cloud-off"
pointSize: Math.round(Style.fontSizeXXXL * 2 * widgetScale)
color: weatherReady ? Color.mPrimary : Color.mOnSurfaceVariant
}
Loader {
active: LocationService.taliaWeatherMascotDayActive && weatherReady
anchors.fill: parent
asynchronous: true
sourceComponent: Component {
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
smooth: true
mipmap: true
asynchronous: true
source: Qt.resolvedUrl(LocationService.taliaWeatherImageFromCode(currentWeatherCode, LocationService.data.weather.current_weather.is_day))
}
}
}
}
NText {
+48 -2
View File
@@ -488,12 +488,35 @@ Item {
Layout.preferredWidth: 180
spacing: Style.marginM
NIcon {
Item {
Layout.preferredWidth: lockMainWeatherIconSide
Layout.preferredHeight: lockMainWeatherIconSide
Layout.alignment: Qt.AlignVCenter
readonly property int lockMainWeatherIconSide: Math.round(Style.fontSizeXXXL * Style.uiScaleRatio * 1.6)
NIcon {
visible: !LocationService.taliaWeatherMascotDayActive || !weatherReady
anchors.centerIn: parent
icon: weatherReady ? LocationService.weatherSymbolFromCode(LocationService.data.weather.current_weather.weathercode, LocationService.data.weather.current_weather.is_day) : "weather-cloud-off"
pointSize: Style.fontSizeXXXL
color: Color.mPrimary
}
Loader {
active: LocationService.taliaWeatherMascotDayActive && weatherReady
anchors.fill: parent
asynchronous: true
sourceComponent: Component {
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
smooth: true
mipmap: true
asynchronous: true
source: Qt.resolvedUrl(LocationService.taliaWeatherImageFromCode(LocationService.data.weather.current_weather.weathercode, LocationService.data.weather.current_weather.is_day))
}
}
}
}
ColumnLayout {
Layout.fillWidth: true
@@ -579,12 +602,35 @@ Item {
Layout.fillWidth: true
}
NIcon {
Item {
Layout.preferredWidth: lockForecastWeatherIconSide
Layout.preferredHeight: lockForecastWeatherIconSide
Layout.alignment: Qt.AlignHCenter
readonly property int lockForecastWeatherIconSide: Math.round(Style.fontSizeXL * Style.uiScaleRatio * 1.6)
NIcon {
visible: !LocationService.taliaWeatherMascotDayActive
anchors.centerIn: parent
icon: LocationService.weatherSymbolFromCode(LocationService.data.weather.daily.weathercode[index])
pointSize: Style.fontSizeXL
color: Color.mOnSurfaceVariant
}
Loader {
active: LocationService.taliaWeatherMascotDayActive
anchors.fill: parent
asynchronous: true
sourceComponent: Component {
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
smooth: true
mipmap: true
asynchronous: true
source: Qt.resolvedUrl(LocationService.taliaWeatherImageFromCode(LocationService.data.weather.daily.weathercode[index]))
}
}
}
}
NText {
text: {
+26 -1
View File
@@ -10,9 +10,18 @@ Singleton {
id: root
property string locationFile: Quickshell.env("NOCTALIA_WEATHER_FILE") || (Settings.cacheDir + "location.json")
property int weatherUpdateFrequency: 30 * 60 // 30 minutes expressed in seconds
property int weatherUpdateFrequency: 30 * 60
property bool isFetchingWeather: false
// Talia weather
readonly property int taliaMascotWeatherMonth: 3
readonly property int taliaMascotWeatherDay: 1
readonly property bool taliaWeatherMascotDayActive: {
const d = Time.now;
return d.getMonth() === root.taliaMascotWeatherMonth && d.getDate() === root.taliaMascotWeatherDay;
}
readonly property alias data: adapter
// Stable UI properties - only updated when location is successfully geocoded
@@ -266,6 +275,22 @@ Singleton {
return "weather-cloud";
}
// --------------------------------
function taliaWeatherImageFromCode(code, isDay) {
if (code >= 40 && code <= 49)
return Quickshell.shellDir + "/Assets/Talia/TaliaDazed.png";
if (code >= 95 && code <= 99)
return Quickshell.shellDir + "/Assets/Talia/TaliaFear.png";
var wet = (code >= 51 && code <= 67) || (code >= 80 && code <= 82) || (code >= 71 && code <= 77) || (code >= 85 && code <= 86);
if (wet)
return Quickshell.shellDir + "/Assets/Talia/TaliaSob.png";
if ((code === 0 || code === 1 || code === 2) && isDay === false)
return Quickshell.shellDir + "/Assets/Talia/TaliaVampire.png";
if ((code === 0 && isDay === true) || code === 1 || code === 2)
return Quickshell.shellDir + "/Assets/Talia/TaliaParty.png";
return Quickshell.shellDir + "/Assets/Talia/TaliaBlank.png";
}
// --------------------------------
function weatherDescriptionFromCode(code) {
if (code === 0)