fix(nosignal): hardware-test feedback round 2 — weather, dashboard, tray
From the 2026-06-15 on-box hardware test (all 6 prior fixes confirmed; these are the new findings, baked into the fork source rather than shipped as pacman-hook patches, per the Phase-2 "we own the shell" approach): - F-W1 (Weather.qml): fetch at startup. Stock only called reload() on a config CHANGE, so a saved location blanked after reboot and an empty/auto location never populated on a fresh boot. Add Component.onCompleted: reload() and switch the hourly Timer to reload() (re-detects auto/IP too). - F-W3 (Weather.qml): 7-day forecast showed "undefined°" in °F mode — only maxTempC/minTempC were stored. Store rounded maxTempF/minTempF (and round °C). - F-W2 (Weather.qml): empty/auto-IP location never populated — the in-shell ipinfo.io fetch didn't set loc (provider-specific; the city path works via the same Requests.get). Repair attempt: defensive JSON parse + error callback + fallback to geojs.io. Compiled Requests module not inspectable, so this is best-effort; a saved city still works regardless. - F-D1a (modules/dashboard/*.qml): square the 25 card radii bound to the compiled Tokens.rounding.* Material defaults (which ignore shell.json rounding.scale=0) so the dashboard matches the square redesign. - F-D1b (Glyphs.qml): remap the weather glyphs to the Material-weather family (every codepoint verified present in JetBrainsMono Nerd Font Mono); the old Font-Awesome codepoints were absent (rendered "?") and thunderstorm / snowing_heavy were unmapped. - F-T1 (NsBar.qml): gate the system-tray pill on SystemTray.items count so it only shows when an app registers a tray icon (was opening an empty panel). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f21e5b5eaf
commit
53c5833de0
16 changed files with 85 additions and 42 deletions
|
|
@ -75,7 +75,7 @@ Item {
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.margins: Tokens.padding.large
|
anchors.margins: Tokens.padding.large
|
||||||
|
|
||||||
radius: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
Flickable {
|
Flickable {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ GridLayout {
|
||||||
Layout.preferredWidth: Tokens.sizes.dashboard.userWidth
|
Layout.preferredWidth: Tokens.sizes.dashboard.userWidth
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
radius: Tokens.rounding.extraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
User {
|
User {
|
||||||
id: user
|
id: user
|
||||||
|
|
@ -37,7 +37,7 @@ GridLayout {
|
||||||
Layout.preferredWidth: Tokens.sizes.dashboard.weatherWidth
|
Layout.preferredWidth: Tokens.sizes.dashboard.weatherWidth
|
||||||
Layout.preferredHeight: weather.implicitHeight
|
Layout.preferredHeight: weather.implicitHeight
|
||||||
|
|
||||||
radius: Tokens.rounding.extraLarge * 1.5
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
SmallWeather {
|
SmallWeather {
|
||||||
id: weather
|
id: weather
|
||||||
|
|
@ -49,7 +49,7 @@ GridLayout {
|
||||||
Layout.preferredWidth: dateTime.implicitWidth
|
Layout.preferredWidth: dateTime.implicitWidth
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
radius: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
DateTime {
|
DateTime {
|
||||||
id: dateTime
|
id: dateTime
|
||||||
|
|
@ -63,7 +63,7 @@ GridLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: calendar.implicitHeight
|
Layout.preferredHeight: calendar.implicitHeight
|
||||||
|
|
||||||
radius: Tokens.rounding.extraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
Calendar {
|
Calendar {
|
||||||
id: calendar
|
id: calendar
|
||||||
|
|
@ -78,7 +78,7 @@ GridLayout {
|
||||||
Layout.preferredWidth: resources.implicitWidth
|
Layout.preferredWidth: resources.implicitWidth
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
radius: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
Resources {
|
Resources {
|
||||||
id: resources
|
id: resources
|
||||||
|
|
@ -92,7 +92,7 @@ GridLayout {
|
||||||
Layout.preferredWidth: media.implicitWidth
|
Layout.preferredWidth: media.implicitWidth
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
radius: Tokens.rounding.extraLarge * 2
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
Media {
|
Media {
|
||||||
id: media
|
id: media
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ Item {
|
||||||
implicitHeight: parent.implicitHeight * 2
|
implicitHeight: parent.implicitHeight * 2
|
||||||
|
|
||||||
color: Colours.palette.m3primary
|
color: Colours.palette.m3primary
|
||||||
radius: Tokens.rounding.full
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on x {
|
Behavior on x {
|
||||||
|
|
@ -148,7 +148,7 @@ Item {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
implicitHeight: parent.height + Tokens.sizes.dashboard.tabIndicatorSpacing * 2
|
implicitHeight: parent.height + Tokens.sizes.dashboard.tabIndicatorSpacing * 2
|
||||||
|
|
||||||
radius: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface
|
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface
|
||||||
onClicked: root.dashState.currentTab = tab.TabBar.index
|
onClicked: root.dashState.currentTab = tab.TabBar.index
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: bigInfoRow.implicitHeight + Tokens.padding.small
|
implicitHeight: bigInfoRow.implicitHeight + Tokens.padding.small
|
||||||
|
|
||||||
radius: Tokens.rounding.extraLarge * 2
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
|
@ -155,7 +155,7 @@ Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: forecastItemColumn.implicitHeight + Tokens.padding.medium * 2
|
implicitHeight: forecastItemColumn.implicitHeight + Tokens.padding.medium * 2
|
||||||
|
|
||||||
radius: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
|
@ -209,7 +209,7 @@ Item {
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 60
|
Layout.preferredHeight: 60
|
||||||
radius: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ CustomMouseArea {
|
||||||
|
|
||||||
StateLayer {
|
StateLayer {
|
||||||
color: Colours.palette.m3primary
|
color: Colours.palette.m3primary
|
||||||
radius: pressed ? Tokens.rounding.small : Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
disabled: {
|
disabled: {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
return root.currMonth === now.getMonth() && root.currYear === now.getFullYear();
|
return root.currMonth === now.getMonth() && root.currYear === now.getFullYear();
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ Item {
|
||||||
|
|
||||||
implicitWidth: 10
|
implicitWidth: 10
|
||||||
implicitHeight: 10
|
implicitHeight: 10
|
||||||
radius: Tokens.rounding.full
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: Colours.palette.m3secondaryContainer
|
color: Colours.palette.m3secondaryContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,7 +229,7 @@ Item {
|
||||||
|
|
||||||
implicitWidth: 15
|
implicitWidth: 15
|
||||||
implicitHeight: 15
|
implicitHeight: 15
|
||||||
radius: Tokens.rounding.full
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: Colours.palette.m3secondaryContainer
|
color: Colours.palette.m3secondaryContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,7 +240,7 @@ Item {
|
||||||
anchors.leftMargin: -Tokens.padding.medium
|
anchors.leftMargin: -Tokens.padding.medium
|
||||||
y: Tokens.padding.extraSmall
|
y: Tokens.padding.extraSmall
|
||||||
|
|
||||||
radius: Tokens.rounding.largeIncreased
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
color: Colours.palette.m3secondaryContainer
|
color: Colours.palette.m3secondaryContainer
|
||||||
implicitWidth: wmLabel.implicitWidth + Tokens.padding.medium * 2
|
implicitWidth: wmLabel.implicitWidth + Tokens.padding.medium * 2
|
||||||
implicitHeight: wmLabel.implicitHeight + Tokens.padding.small * 2
|
implicitHeight: wmLabel.implicitHeight + Tokens.padding.small * 2
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ Item {
|
||||||
implicitWidth: shape.implicitSize + Tokens.padding.medium * 2
|
implicitWidth: shape.implicitSize + Tokens.padding.medium * 2
|
||||||
implicitHeight: shape.implicitSize + Tokens.padding.medium * 2
|
implicitHeight: shape.implicitSize + Tokens.padding.medium * 2
|
||||||
color: Colours.palette.m3primaryContainer
|
color: Colours.palette.m3primaryContainer
|
||||||
radius: Tokens.rounding.full
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
LoadingIndicator {
|
LoadingIndicator {
|
||||||
id: shape
|
id: shape
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: !btn.pressed && btn.containsMouse ? -Tokens.padding.extraSmall : 0
|
anchors.margins: !btn.pressed && btn.containsMouse ? -Tokens.padding.extraSmall : 0
|
||||||
group: blobGroup
|
group: blobGroup
|
||||||
radius: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
Behavior on anchors.margins {
|
Behavior on anchors.margins {
|
||||||
Anim {}
|
Anim {}
|
||||||
|
|
@ -50,7 +50,7 @@ Item {
|
||||||
implicitHeight: parent.height
|
implicitHeight: parent.height
|
||||||
|
|
||||||
group: blobGroup
|
group: blobGroup
|
||||||
radius: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
deformScale: 0.00001
|
deformScale: 0.00001
|
||||||
|
|
||||||
states: State {
|
states: State {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ StyledClippingRect {
|
||||||
property real animPerc: UPower.displayDevice.percentage
|
property real animPerc: UPower.displayDevice.percentage
|
||||||
|
|
||||||
color: Colours.palette.m3secondaryContainer
|
color: Colours.palette.m3secondaryContainer
|
||||||
radius: Tokens.rounding.large
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
implicitWidth: Config.dashboard.performance.showCpu || (Config.dashboard.performance.showGpu && Gpu.type !== Gpu.None) || Config.dashboard.performance.showStorage || Config.dashboard.performance.showMemory ? Tokens.sizes.dashboard.perfBattWidth : Tokens.sizes.dashboard.perfBattWidthSingle
|
implicitWidth: Config.dashboard.performance.showCpu || (Config.dashboard.performance.showGpu && Gpu.type !== Gpu.None) || Config.dashboard.performance.showStorage || Config.dashboard.performance.showMemory ? Tokens.sizes.dashboard.perfBattWidth : Tokens.sizes.dashboard.perfBattWidthSingle
|
||||||
implicitHeight: Tokens.sizes.dashboard.perfBattHeight
|
implicitHeight: Tokens.sizes.dashboard.perfBattHeight
|
||||||
|
|
@ -39,7 +39,7 @@ StyledClippingRect {
|
||||||
implicitHeight: parent.height * root.animPerc
|
implicitHeight: parent.height * root.animPerc
|
||||||
|
|
||||||
color: Colours.palette.m3secondary
|
color: Colours.palette.m3secondary
|
||||||
radius: Tokens.rounding.extraSmall
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
Contents {
|
Contents {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ StyledRect {
|
||||||
required property real temperature
|
required property real temperature
|
||||||
|
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
radius: Tokens.rounding.extraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
implicitWidth: Tokens.sizes.dashboard.perfHeroCardWidth
|
implicitWidth: Tokens.sizes.dashboard.perfHeroCardWidth
|
||||||
implicitHeight: Math.max(tempProg.implicitHeight + detailsRow.implicitHeight + Tokens.spacing.large, usageShape.implicitHeight + usageLabel.implicitHeight) + Tokens.padding.large * 2
|
implicitHeight: Math.max(tempProg.implicitHeight + detailsRow.implicitHeight + Tokens.spacing.large, usageShape.implicitHeight + usageLabel.implicitHeight) + Tokens.padding.large * 2
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ StyledRect {
|
||||||
readonly property color accent: Colours.palette.m3tertiary
|
readonly property color accent: Colours.palette.m3tertiary
|
||||||
|
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
radius: Tokens.rounding.medium
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
implicitWidth: layout.implicitWidth + Tokens.padding.extraLargeIncreased * 2
|
implicitWidth: layout.implicitWidth + Tokens.padding.extraLargeIncreased * 2
|
||||||
implicitHeight: layout.implicitHeight + Tokens.padding.large * 2
|
implicitHeight: layout.implicitHeight + Tokens.padding.large * 2
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ StyledRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
radius: Tokens.rounding.extraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
implicitWidth: Tokens.sizes.dashboard.perfNetworkCardWidth
|
implicitWidth: Tokens.sizes.dashboard.perfNetworkCardWidth
|
||||||
implicitHeight: Tokens.sizes.dashboard.perfNetworkCardHeight
|
implicitHeight: Tokens.sizes.dashboard.perfNetworkCardHeight
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ StyledRect {
|
||||||
readonly property real percentage: Storage.primaryDisk?.perc ?? 0
|
readonly property real percentage: Storage.primaryDisk?.perc ?? 0
|
||||||
|
|
||||||
color: Colours.tPalette.m3surfaceContainer
|
color: Colours.tPalette.m3surfaceContainer
|
||||||
radius: Tokens.rounding.extraExtraLarge
|
radius: 0 // nosignal: square dashboard cards to match the redesign (F-D1)
|
||||||
|
|
||||||
implicitWidth: layout.implicitWidth + layout.anchors.margins * 2
|
implicitWidth: layout.implicitWidth + layout.anchors.margins * 2
|
||||||
implicitHeight: layout.implicitHeight + Tokens.padding.large * 2
|
implicitHeight: layout.implicitHeight + Tokens.padding.large * 2
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Bluetooth
|
import Quickshell.Bluetooth
|
||||||
import Quickshell.Services.UPower
|
import Quickshell.Services.UPower
|
||||||
|
import Quickshell.Services.SystemTray
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.utils
|
import qs.utils
|
||||||
import qs.components
|
import qs.components
|
||||||
|
|
@ -139,10 +140,12 @@ Variants {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// System tray
|
// System tray — only shown when an app actually registers a tray
|
||||||
|
// icon, otherwise the pill just opened an empty panel (F-T1).
|
||||||
IconPill {
|
IconPill {
|
||||||
icon: "widgets"
|
icon: "widgets"
|
||||||
panel: "tray"
|
panel: "tray"
|
||||||
|
visible: SystemTray.items.values.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notifications bell (with unread dot overlaid on the icon)
|
// Notifications bell (with unread dot overlaid on the icon)
|
||||||
|
|
|
||||||
|
|
@ -145,16 +145,21 @@ Singleton {
|
||||||
"warning": root.cp(0xf071),
|
"warning": root.cp(0xf071),
|
||||||
"web_asset_off": root.cp(0xf2d0),
|
"web_asset_off": root.cp(0xf2d0),
|
||||||
"wifi_find": root.cp(0xf1eb),
|
"wifi_find": root.cp(0xf1eb),
|
||||||
// weather (Icons.getWeatherIcon)
|
// weather (Icons.getWeatherIcon) — Material-weather family, every
|
||||||
"clear_day": root.cp(0xf185),
|
// codepoint verified present in JetBrainsMono Nerd Font Mono. The old
|
||||||
"clear_night": root.cp(0xf186),
|
// Font-Awesome mapping had several glyphs absent from the font (rendered
|
||||||
"partly_cloudy_day": root.cp(0xf6c4),
|
// as "?" boxes) and was missing thunderstorm/snowing_heavy (F-D1).
|
||||||
"cloudy": root.cp(0xf0c2),
|
"clear_day": root.cp(0xf0599),
|
||||||
"cloud": root.cp(0xf0c2),
|
"clear_night": root.cp(0xf0594),
|
||||||
"rainy": root.cp(0xf73d),
|
"partly_cloudy_day": root.cp(0xf0595),
|
||||||
"cloudy_snowing": root.cp(0xf2dc),
|
"cloudy": root.cp(0xf0590),
|
||||||
"foggy": root.cp(0xf75f),
|
"cloud": root.cp(0xf0590),
|
||||||
"air": root.cp(0xf72e),
|
"rainy": root.cp(0xf0597),
|
||||||
|
"cloudy_snowing": root.cp(0xf0598),
|
||||||
|
"snowing_heavy": root.cp(0xf0f37),
|
||||||
|
"thunderstorm": root.cp(0xf0593),
|
||||||
|
"foggy": root.cp(0xf0591),
|
||||||
|
"air": root.cp(0xf059d),
|
||||||
// apps / devices (Icons.get*)
|
// apps / devices (Icons.get*)
|
||||||
"code": root.cp(0xf121),
|
"code": root.cp(0xf121),
|
||||||
"forum": root.cp(0xf086),
|
"forum": root.cp(0xf086),
|
||||||
|
|
|
||||||
|
|
@ -41,15 +41,43 @@ Singleton {
|
||||||
fetchCoordsFromCity(configLocation);
|
fetchCoordsFromCity(configLocation);
|
||||||
}
|
}
|
||||||
} else if (!loc || timer.elapsed() > 900) {
|
} else if (!loc || timer.elapsed() > 900) {
|
||||||
Requests.get("https://ipinfo.io/json", text => {
|
fetchLocationFromIp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-detect location from the public IP (used when weatherLocation is
|
||||||
|
// empty). Stock caelestia only queried ipinfo.io with no error handling;
|
||||||
|
// on the 2026-06-15 hardware test that call never populated `loc` (the
|
||||||
|
// city path works via the same Requests.get, so it is provider-specific —
|
||||||
|
// finding F-W2). Repair: wrap parsing defensively and fall back to a second
|
||||||
|
// provider (geojs.io, which returns separate latitude/longitude fields) on
|
||||||
|
// any error or empty response.
|
||||||
|
function fetchLocationFromIp(): void {
|
||||||
|
const useGeoJs = () => {
|
||||||
|
Requests.get("https://get.geojs.io/v1/ip/geo.json", text => {
|
||||||
|
try {
|
||||||
|
const g = JSON.parse(text);
|
||||||
|
if (g.latitude && g.longitude) {
|
||||||
|
loc = g.latitude + "," + g.longitude;
|
||||||
|
city = g.city ?? "";
|
||||||
|
timer.restart();
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Requests.get("https://ipinfo.io/json", text => {
|
||||||
|
try {
|
||||||
const response = JSON.parse(text);
|
const response = JSON.parse(text);
|
||||||
if (response.loc) {
|
if (response.loc) {
|
||||||
loc = response.loc;
|
loc = response.loc;
|
||||||
city = response.city ?? "";
|
city = response.city ?? "";
|
||||||
timer.restart();
|
timer.restart();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
} catch (e) {}
|
||||||
}
|
useGeoJs();
|
||||||
|
}, useGeoJs);
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchCityFromCoords(coords: string): void {
|
function fetchCityFromCoords(coords: string): void {
|
||||||
|
|
@ -131,8 +159,10 @@ Singleton {
|
||||||
for (let i = 0; i < json.daily.time.length; i++)
|
for (let i = 0; i < json.daily.time.length; i++)
|
||||||
forecastList.push({
|
forecastList.push({
|
||||||
date: json.daily.time[i].replace(/-/g, "/"),
|
date: json.daily.time[i].replace(/-/g, "/"),
|
||||||
maxTempC: json.daily.temperature_2m_max[i],
|
maxTempC: Math.round(json.daily.temperature_2m_max[i]),
|
||||||
minTempC: json.daily.temperature_2m_min[i],
|
minTempC: Math.round(json.daily.temperature_2m_min[i]),
|
||||||
|
maxTempF: Math.round(toFahrenheit(json.daily.temperature_2m_max[i])),
|
||||||
|
minTempF: Math.round(toFahrenheit(json.daily.temperature_2m_min[i])),
|
||||||
weatherCode: json.daily.weather_code[i],
|
weatherCode: json.daily.weather_code[i],
|
||||||
icon: Icons.getWeatherIcon(json.daily.weather_code[i])
|
icon: Icons.getWeatherIcon(json.daily.weather_code[i])
|
||||||
});
|
});
|
||||||
|
|
@ -210,6 +240,11 @@ Singleton {
|
||||||
|
|
||||||
onLocChanged: fetchWeatherData()
|
onLocChanged: fetchWeatherData()
|
||||||
|
|
||||||
|
// Stock caelestia only called reload() on a config CHANGE, never at startup,
|
||||||
|
// so a saved location blanked after a reboot and an empty (auto/IP) location
|
||||||
|
// never populated on a fresh boot (finding F-W1). Fetch once on load.
|
||||||
|
Component.onCompleted: reload()
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
function onWeatherLocationChanged(): void {
|
function onWeatherLocationChanged(): void {
|
||||||
root.reload();
|
root.reload();
|
||||||
|
|
@ -222,7 +257,7 @@ Singleton {
|
||||||
interval: 3600000 // 1 hour
|
interval: 3600000 // 1 hour
|
||||||
running: true
|
running: true
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: fetchWeatherData()
|
onTriggered: reload() // re-detect an auto/IP location too, not just refetch a known one
|
||||||
}
|
}
|
||||||
|
|
||||||
ElapsedTimer {
|
ElapsedTimer {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue