diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-08-10 23:15:32 +1000 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-08-10 23:15:32 +1000 |
| commit | 87b491d8e794995950c6667e1d831061e36aa186 (patch) | |
| tree | f17fc2be88041dda842d2e3d7db05b09768d3c0d | |
| parent | lock: better lock anim (diff) | |
| download | caelestia-shell-87b491d8e794995950c6667e1d831061e36aa186.tar.gz caelestia-shell-87b491d8e794995950c6667e1d831061e36aa186.tar.bz2 caelestia-shell-87b491d8e794995950c6667e1d831061e36aa186.zip | |
lock: add weather
Also refactor weather service
| -rw-r--r-- | modules/dashboard/dash/Weather.qml | 6 | ||||
| -rw-r--r-- | modules/lock/Content.qml | 6 | ||||
| -rw-r--r-- | modules/lock/WeatherInfo.qml | 169 | ||||
| -rw-r--r-- | services/Weather.qml | 19 |
4 files changed, 160 insertions, 40 deletions
diff --git a/modules/dashboard/dash/Weather.qml b/modules/dashboard/dash/Weather.qml index 0160229..c90ccf0a 100644 --- a/modules/dashboard/dash/Weather.qml +++ b/modules/dashboard/dash/Weather.qml @@ -20,7 +20,7 @@ Item { anchors.left: parent.left animate: true - text: Weather.icon || "cloud_alert" + text: Weather.icon color: Colours.palette.m3secondary font.pointSize: Appearance.font.size.extraLarge * 2 } @@ -38,7 +38,7 @@ Item { anchors.horizontalCenter: parent.horizontalCenter animate: true - text: Config.services.useFahrenheit ? Weather.tempF : Weather.tempC + text: Weather.temp color: Colours.palette.m3primary font.pointSize: Appearance.font.size.extraLarge font.weight: 500 @@ -48,7 +48,7 @@ Item { anchors.horizontalCenter: parent.horizontalCenter animate: true - text: Weather.description || qsTr("No weather") + text: Weather.description elide: Text.ElideRight width: Math.min(implicitWidth, root.parent.width - icon.implicitWidth - info.anchors.leftMargin - Appearance.padding.large * 2) diff --git a/modules/lock/Content.qml b/modules/lock/Content.qml index 102d8cf..ba19616 100644 --- a/modules/lock/Content.qml +++ b/modules/lock/Content.qml @@ -21,12 +21,14 @@ RowLayout { StyledRect { Layout.fillWidth: true - Layout.fillHeight: true + implicitHeight: weather.implicitHeight radius: Appearance.rounding.small color: Colours.tPalette.m3surfaceContainer - // WeatherInfo {} + WeatherInfo { + id: weather + } } StyledRect { diff --git a/modules/lock/WeatherInfo.qml b/modules/lock/WeatherInfo.qml index 1b5b29e..da35a92 100644 --- a/modules/lock/WeatherInfo.qml +++ b/modules/lock/WeatherInfo.qml @@ -1,46 +1,163 @@ import qs.components import qs.services import qs.config +import qs.utils import QtQuick import QtQuick.Layouts -RowLayout { +ColumnLayout { id: root - anchors.fill: parent - spacing: Appearance.spacing.large + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: Appearance.padding.large * 2 - MaterialIcon { - animate: true - text: Weather.icon || "cloud_alert" - color: Colours.palette.m3secondary - font.pointSize: Appearance.font.size.extraLarge * 2.5 + spacing: Appearance.spacing.small + + StyledText { + Layout.topMargin: Appearance.padding.large * 2 + Layout.alignment: Qt.AlignHCenter + text: qsTr("Weather") + color: Colours.palette.m3primary + font.pointSize: Appearance.font.size.extraLarge + font.weight: 500 } - ColumnLayout { - Layout.alignment: Qt.AlignVCenter + RowLayout { + Layout.fillWidth: true + spacing: Appearance.spacing.large - spacing: Appearance.spacing.small + MaterialIcon { + animate: true + text: Weather.icon + color: Colours.palette.m3secondary + font.pointSize: Appearance.font.size.extraLarge * 2.5 + } - StyledText { - Layout.fillWidth: true + ColumnLayout { + spacing: Appearance.spacing.small - animate: true - text: Config.services.useFahrenheit ? Weather.tempF : Weather.tempC - color: Colours.palette.m3primary - horizontalAlignment: Text.AlignHCenter - font.pointSize: Appearance.font.size.extraLarge - font.weight: 500 + StyledText { + Layout.fillWidth: true + + animate: true + text: Weather.description + color: Colours.palette.m3secondary + font.pointSize: Appearance.font.size.large + font.weight: 500 + elide: Text.ElideRight + } + + StyledText { + Layout.fillWidth: true + + animate: true + text: qsTr("Humidity: %1%").arg(Weather.humidity) + color: Colours.palette.m3onSurfaceVariant + font.pointSize: Appearance.font.size.normal + elide: Text.ElideRight + } } - StyledText { - Layout.fillWidth: true + ColumnLayout { + Layout.rightMargin: Appearance.padding.smaller + spacing: Appearance.spacing.small - animate: true - text: Weather.description || qsTr("No weather") - horizontalAlignment: Text.AlignHCenter - font.pointSize: Appearance.font.size.large - elide: Text.ElideRight + StyledText { + Layout.fillWidth: true + + animate: true + text: Weather.temp + color: Colours.palette.m3primary + horizontalAlignment: Text.AlignRight + font.pointSize: Appearance.font.size.extraLarge + font.weight: 500 + elide: Text.ElideLeft + } + + StyledText { + Layout.fillWidth: true + + animate: true + text: qsTr("Feels like: %1").arg(Weather.feelsLike) + color: Colours.palette.m3outline + horizontalAlignment: Text.AlignRight + font.pointSize: Appearance.font.size.smaller + elide: Text.ElideLeft + } + } + } + + RowLayout { + Layout.topMargin: Appearance.spacing.smaller + Layout.bottomMargin: Appearance.padding.large * 2 + Layout.fillWidth: true + spacing: Appearance.spacing.large + + Repeater { + model: { + const forecast = Weather.forecast; + if (!forecast) + return Array.from({ + length: 5 + }, () => null); + + const hours = []; + const hour = new Date().getHours(); + let count = 5; + + const today = forecast[0].hourly; + const arr = [...today, ...forecast[1].hourly]; + for (let i = 0; i < arr.length; i++) { + const time = parseInt(arr[i].time, 10) / 100; + + if (i > today.length ? time < hour : time > hour) { + hours.push(arr[i]); + count--; + } + + if (count === 0) + break; + } + + return hours; + } + + ColumnLayout { + id: forecastHour + + required property var modelData + + Layout.fillWidth: true + spacing: Appearance.spacing.small + + StyledText { + Layout.fillWidth: true + text: { + if (!forecastHour.modelData) + return "00 AM"; + const hour = parseInt(forecastHour.modelData.time, 10) / 100; + return hour > 12 ? `${(hour - 12).toString().padStart(2, "0")} PM` : `${hour.toString().padStart(2, "0")} AM`; + } + color: Colours.palette.m3outline + horizontalAlignment: Text.AlignHCenter + font.pointSize: Appearance.font.size.larger + } + + MaterialIcon { + Layout.alignment: Qt.AlignHCenter + text: forecastHour.modelData ? Icons.getWeatherIcon(forecastHour.modelData.weatherCode) : "cloud_alert" + font.pointSize: Appearance.font.size.extraLarge * 1.5 + font.weight: 500 + } + + StyledText { + Layout.alignment: Qt.AlignHCenter + text: Config.services.useFahrenheit ? `${forecastHour.modelData?.tempF ?? 0}°F` : `${forecastHour.modelData?.tempC ?? 0}°C` + color: Colours.palette.m3secondary + font.pointSize: Appearance.font.size.larger + } + } } } diff --git a/services/Weather.qml b/services/Weather.qml index 38750ae..02458c2 100644 --- a/services/Weather.qml +++ b/services/Weather.qml @@ -9,10 +9,13 @@ Singleton { id: root property string loc - property string icon - property string description - property string tempC: "0°C" - property string tempF: "0°F" + property var cc + property var forecast + readonly property string icon: cc ? Icons.getWeatherIcon(cc.weatherCode) : "cloud_alert" + readonly property string description: cc?.weatherDesc[0].value ?? qsTr("No weather") + readonly property string temp: Config.services.useFahrenheit ? `${cc?.temp_F ?? 0}°F` : `${cc?.temp_C ?? 0}°C` + readonly property string feelsLike: Config.services.useFahrenheit ? `${cc?.FeelsLikeF ?? 0}°F` : `${cc?.FeelsLikeC ?? 0}°C` + readonly property int humidity: cc?.humidity ?? 0 function reload(): void { if (Config.services.weatherLocation) @@ -25,11 +28,9 @@ Singleton { } onLocChanged: Requests.get(`https://wttr.in/${loc}?format=j1`, text => { - const json = JSON.parse(text).current_condition[0]; - icon = Icons.getWeatherIcon(json.weatherCode); - description = json.weatherDesc[0].value; - tempC = `${parseFloat(json.temp_C)}°C`; - tempF = `${parseFloat(json.temp_F)}°F`; + const json = JSON.parse(text); + cc = json.current_condition[0]; + forecast = json.weather; }) Component.onCompleted: reload() |