diff options
Diffstat (limited to 'modules/lock/WeatherInfo.qml')
| -rw-r--r-- | modules/lock/WeatherInfo.qml | 192 |
1 files changed, 154 insertions, 38 deletions
diff --git a/modules/lock/WeatherInfo.qml b/modules/lock/WeatherInfo.qml index b944d2f..5d10e7b 100644 --- a/modules/lock/WeatherInfo.qml +++ b/modules/lock/WeatherInfo.qml @@ -1,61 +1,177 @@ import qs.components import qs.services import qs.config +import qs.utils import QtQuick import QtQuick.Layouts -RowLayout { +ColumnLayout { id: root - Timer { - running: true - triggeredOnStart: true - repeat: true - interval: 900000 // 15 minutes - onTriggered: Weather.reload() + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: Appearance.padding.large * 2 + + 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 } - spacing: Appearance.spacing.large + RowLayout { + Layout.fillWidth: true + spacing: Appearance.spacing.large + + MaterialIcon { + animate: true + text: Weather.icon + color: Colours.palette.m3secondary + font.pointSize: Appearance.font.size.extraLarge * 2.5 + } + + ColumnLayout { + spacing: Appearance.spacing.small - MaterialIcon { - id: icon + StyledText { + Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter - Layout.topMargin: Config.lock.sizes.border / 4 + animate: true + text: Weather.description + color: Colours.palette.m3secondary + font.pointSize: Appearance.font.size.large + font.weight: 500 + elide: Text.ElideRight + } - animate: true - text: Weather.icon || "cloud_alert" - color: Colours.palette.m3secondary - font.pointSize: Appearance.font.size.extraLarge * 2.5 - } + StyledText { + Layout.fillWidth: true - ColumnLayout { - Layout.alignment: Qt.AlignVCenter - Layout.topMargin: Config.lock.sizes.border / 4 - Layout.rightMargin: Config.lock.sizes.border / 2 + animate: true + text: qsTr("Humidity: %1%").arg(Weather.humidity) + color: Colours.palette.m3onSurfaceVariant + font.pointSize: Appearance.font.size.normal + elide: Text.ElideRight + } + } - spacing: Appearance.spacing.small + Loader { + Layout.rightMargin: Appearance.padding.smaller + asynchronous: true + active: root.width > 400 + visible: active - StyledText { - Layout.fillWidth: true + sourceComponent: 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.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 + } + } } + } - StyledText { - Layout.fillWidth: true - Layout.maximumWidth: Config.lock.sizes.weatherWidth - icon.implicitWidth + RowLayout { + Layout.topMargin: Appearance.spacing.smaller + Layout.bottomMargin: Appearance.padding.large * 2 + Layout.fillWidth: true + spacing: Appearance.spacing.large - animate: true - text: Weather.description || qsTr("No weather") - horizontalAlignment: Text.AlignHCenter - font.pointSize: Appearance.font.size.large - elide: Text.ElideRight + Repeater { + model: { + const forecast = Weather.forecast; + let count = root.width < 320 ? 3 : root.width < 400 ? 4 : 5; + if (!forecast) + return Array.from({ + length: count + }, () => null); + + const hours = []; + const hour = new Date().getHours(); + + 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 + } + } } } + + Timer { + running: true + triggeredOnStart: true + repeat: true + interval: 900000 // 15 minutes + onTriggered: Weather.reload() + } } |