lock: better scaling for weather & fetch

This commit is contained in:
2 * r + 2 * t 2025-08-11 15:42:00 +10:00
parent 0771aad11e
commit efa806b8d6
3 changed files with 124 additions and 69 deletions

View file

@ -30,6 +30,8 @@ RowLayout {
WeatherInfo { WeatherInfo {
id: weather id: weather
rootHeight: root.height
} }
} }

View file

@ -1,3 +1,5 @@
pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.services import qs.services
import qs.config import qs.config
@ -13,9 +15,11 @@ ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: Appearance.padding.large * 2 anchors.margins: Appearance.padding.large * 2
spacing: Appearance.spacing.large * 2 spacing: Appearance.spacing.small
RowLayout { RowLayout {
Layout.fillWidth: true
Layout.fillHeight: false
spacing: Appearance.spacing.normal spacing: Appearance.spacing.normal
StyledRect { StyledRect {
@ -30,29 +34,56 @@ ColumnLayout {
anchors.centerIn: parent anchors.centerIn: parent
text: ">" text: ">"
font.pointSize: root.width > 400 ? Appearance.font.size.larger : Appearance.font.size.normal
color: Colours.palette.m3onPrimary color: Colours.palette.m3onPrimary
} }
} }
MonoText { MonoText {
Layout.fillWidth: true
text: "caelestiafetch.sh" text: "caelestiafetch.sh"
font.pointSize: root.width > 400 ? Appearance.font.size.larger : Appearance.font.size.normal
elide: Text.ElideRight
}
Loader {
Layout.fillHeight: true
asynchronous: true
active: !iconLoader.active
visible: active
sourceComponent: IconImage {
source: Quickshell.iconPath(SysInfo.logo)
implicitSize: height
}
} }
} }
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: false
spacing: Appearance.spacing.large * 2 spacing: height * 0.15
Loader {
id: iconLoader
IconImage {
Layout.fillHeight: true Layout.fillHeight: true
source: Quickshell.iconPath(SysInfo.logo)
implicitSize: height asynchronous: true
active: root.width > 320
visible: active
sourceComponent: IconImage {
source: Quickshell.iconPath(SysInfo.logo)
implicitSize: height
}
} }
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.topMargin: Appearance.padding.normal
Layout.bottomMargin: Appearance.padding.normal
Layout.leftMargin: iconLoader.active ? 0 : width * 0.1
spacing: Appearance.spacing.normal spacing: Appearance.spacing.normal
FetchText { FetchText {
@ -73,26 +104,34 @@ ColumnLayout {
} }
} }
RowLayout { Loader {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
spacing: Appearance.spacing.large
Repeater { asynchronous: true
model: 8 active: root.height > 250
visible: active
StyledRect { sourceComponent: RowLayout {
required property int index spacing: Appearance.spacing.large
implicitWidth: implicitHeight Repeater {
implicitHeight: Appearance.font.size.larger * 2 model: Math.min(8, root.width / (Appearance.font.size.larger * 2 + Appearance.spacing.large))
color: Colours.palette[`term${index}`]
radius: Appearance.rounding.small StyledRect {
required property int index
implicitWidth: implicitHeight
implicitHeight: Appearance.font.size.larger * 2
color: Colours.palette[`term${index}`]
radius: Appearance.rounding.small
}
} }
} }
} }
component FetchText: MonoText { component FetchText: MonoText {
font.pointSize: Appearance.font.size.larger Layout.fillWidth: true
font.pointSize: root.width > 400 ? Appearance.font.size.larger : Appearance.font.size.normal
elide: Text.ElideRight elide: Text.ElideRight
} }

View file

@ -1,3 +1,5 @@
pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.services import qs.services
import qs.config import qs.config
@ -8,6 +10,8 @@ import QtQuick.Layouts
ColumnLayout { ColumnLayout {
id: root id: root
required property int rootHeight
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.margins: Appearance.padding.large * 2 anchors.margins: Appearance.padding.large * 2
@ -24,6 +28,7 @@ ColumnLayout {
} }
RowLayout { RowLayout {
Layout.bottomMargin: forecastLoader.active ? 0 : Appearance.padding.large
Layout.fillWidth: true Layout.fillWidth: true
spacing: Appearance.spacing.large spacing: Appearance.spacing.large
@ -94,74 +99,83 @@ ColumnLayout {
} }
} }
RowLayout { Loader {
id: forecastLoader
Layout.topMargin: Appearance.spacing.smaller Layout.topMargin: Appearance.spacing.smaller
Layout.bottomMargin: Appearance.padding.large * 2 Layout.bottomMargin: Appearance.padding.large * 2
Layout.fillWidth: true Layout.fillWidth: true
spacing: Appearance.spacing.large
Repeater { asynchronous: true
model: { active: root.rootHeight > 820
const forecast = Weather.forecast; visible: active
let count = root.width < 320 ? 3 : root.width < 400 ? 4 : 5;
if (!forecast)
return Array.from({
length: count
}, () => null);
const hours = []; sourceComponent: RowLayout {
const hour = new Date().getHours(); spacing: Appearance.spacing.large
const today = forecast[0].hourly; Repeater {
const arr = [...today, ...forecast[1].hourly]; model: {
for (let i = 0; i < arr.length; i++) { const forecast = Weather.forecast;
const time = parseInt(arr[i].time, 10) / 100; let count = root.width < 320 ? 3 : root.width < 400 ? 4 : 5;
if (!forecast)
return Array.from({
length: count
}, () => null);
if (i > today.length ? time < hour : time > hour) { const hours = [];
hours.push(arr[i]); const hour = new Date().getHours();
count--;
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;
} }
if (count === 0) return hours;
break;
} }
return hours; ColumnLayout {
} id: forecastHour
ColumnLayout { required property var modelData
id: forecastHour
required property var modelData
Layout.fillWidth: true
spacing: Appearance.spacing.small
StyledText {
Layout.fillWidth: true Layout.fillWidth: true
text: { spacing: Appearance.spacing.small
if (!forecastHour.modelData)
return "00 AM"; StyledText {
const hour = parseInt(forecastHour.modelData.time, 10) / 100; Layout.fillWidth: true
return hour > 12 ? `${(hour - 12).toString().padStart(2, "0")} PM` : `${hour.toString().padStart(2, "0")} AM`; 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
} }
color: Colours.palette.m3outline
horizontalAlignment: Text.AlignHCenter
font.pointSize: Appearance.font.size.larger
}
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
text: forecastHour.modelData ? Icons.getWeatherIcon(forecastHour.modelData.weatherCode) : "cloud_alert" text: forecastHour.modelData ? Icons.getWeatherIcon(forecastHour.modelData.weatherCode) : "cloud_alert"
font.pointSize: Appearance.font.size.extraLarge * 1.5 font.pointSize: Appearance.font.size.extraLarge * 1.5
font.weight: 500 font.weight: 500
} }
StyledText { StyledText {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
text: Config.services.useFahrenheit ? `${forecastHour.modelData?.tempF ?? 0}°F` : `${forecastHour.modelData?.tempC ?? 0}°C` text: Config.services.useFahrenheit ? `${forecastHour.modelData?.tempF ?? 0}°F` : `${forecastHour.modelData?.tempC ?? 0}°C`
color: Colours.palette.m3secondary color: Colours.palette.m3secondary
font.pointSize: Appearance.font.size.larger font.pointSize: Appearance.font.size.larger
}
} }
} }
} }