1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-14 09:42:10 -04:00

weather: light redesign for dash card

This commit is contained in:
bbedward
2026-02-12 09:42:29 -05:00
parent bd46d29ff0
commit 00e1099912
3 changed files with 551 additions and 563 deletions

View File

@@ -68,7 +68,8 @@ Rectangle {
readonly property var values: daily ? [] : [ readonly property var values: daily ? [] : [
{ {
// 'name': "Temperature", "name"// 'name': "Temperature",
:
// 'text': root.tempText, // 'text': root.tempText,
// 'icon': "thermometer" // 'icon': "thermometer"
// }, { // }, {
@@ -76,34 +77,34 @@ Rectangle {
// 'text': root.feelsLikeText, // 'text': root.feelsLikeText,
// 'icon': "thermostat" // 'icon': "thermostat"
// }, { // }, {
'name': I18n.tr("Humidity"), I18n.tr("Humidity"),
'text': root.humidityText, "text": root.humidityText,
'icon': "humidity_low" "icon": "humidity_low"
}, },
{ {
'name': I18n.tr("Wind Speed"), "name": I18n.tr("Wind Speed"),
'text': root.windText, "text": root.windText,
'icon': "air" "icon": "air"
}, },
{ {
'name': I18n.tr("Pressure"), "name": I18n.tr("Pressure"),
'text': root.pressureText, "text": root.pressureText,
'icon': "speed" "icon": "speed"
}, },
{ {
'name': I18n.tr("Precipitation Chance"), "name": I18n.tr("Precipitation Chance"),
'text': root.precipitationText, "text": root.precipitationText,
'icon': "rainy" "icon": "rainy"
}, },
{ {
'name': I18n.tr("Visibility"), "name": I18n.tr("Visibility"),
'text': root.visibilityText, "text": root.visibilityText,
'icon': "wb_sunny" "icon": "wb_sunny"
} }
] ]
color: isCurrent ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) color: isCurrent ? Theme.withAlpha(Theme.primary, 0.1) : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: isCurrent ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : "transparent" border.color: isCurrent ? Theme.withAlpha(Theme.primary, 0.3) : "transparent"
border.width: isCurrent ? 1 : 0 border.width: isCurrent ? 1 : 0
Column { Column {
@@ -129,7 +130,7 @@ Rectangle {
DankIcon { DankIcon {
name: root.forecastData ? WeatherService.getWeatherIcon(root.forecastData.wCode || 0, root.forecastData.isDay ?? true) : "cloud" name: root.forecastData ? WeatherService.getWeatherIcon(root.forecastData.wCode || 0, root.forecastData.isDay ?? true) : "cloud"
size: Theme.iconSize size: Theme.iconSize
color: root.isCurrent ? Theme.primary : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8) color: root.isCurrent ? Theme.primary : Theme.withAlpha(Theme.primary, 0.8)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
@@ -187,14 +188,14 @@ Rectangle {
DankIcon { DankIcon {
name: root.values[index].icon name: root.values[index].icon
size: 8 size: 8
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) color: Theme.withAlpha(Theme.surfaceText, 0.6)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
StyledText { StyledText {
text: root.values[index].text text: root.values[index].text
font.pixelSize: Theme.fontSizeSmall - 2 font.pixelSize: Theme.fontSizeSmall - 2
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) color: Theme.withAlpha(Theme.surfaceText, 0.6)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }

View File

@@ -14,6 +14,8 @@ Item {
implicitWidth: 700 implicitWidth: 700
implicitHeight: root.available ? mainColumn.implicitHeight : unavailableColumn.implicitHeight + Theme.spacingXL * 2 implicitHeight: root.available ? mainColumn.implicitHeight : unavailableColumn.implicitHeight + Theme.spacingXL * 2
property bool syncing: false property bool syncing: false
property bool showHourly: false
property bool available: WeatherService.weather.available
function syncFrom(type) { function syncFrom(type) {
if (!dailyLoader.item || !hourlyLoader.item) if (!dailyLoader.item || !hourlyLoader.item)
@@ -49,7 +51,66 @@ Item {
syncing = false; syncing = false;
} }
property bool available: WeatherService.weather.available readonly property string sunriseTimeText: {
if (!WeatherService.weather.rawSunrise)
return WeatherService.weather.sunrise || "";
try {
const date = new Date(WeatherService.weather.rawSunrise);
const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP";
return date.toLocaleTimeString(Qt.locale(), format);
} catch (e) {
return WeatherService.weather.sunrise || "";
}
}
readonly property string sunsetTimeText: {
if (!WeatherService.weather.rawSunset)
return WeatherService.weather.sunset || "";
try {
const date = new Date(WeatherService.weather.rawSunset);
const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP";
return date.toLocaleTimeString(Qt.locale(), format);
} catch (e) {
return WeatherService.weather.sunset || "";
}
}
readonly property var heroMetrics: {
SettingsData.useFahrenheit;
SettingsData.windSpeedUnit;
return [
{
"icon": "humidity_low",
"label": I18n.tr("Humidity"),
"value": WeatherService.formatPercent(WeatherService.weather.humidity) ?? "--"
},
{
"icon": "air",
"label": I18n.tr("Wind"),
"value": WeatherService.formatSpeed(WeatherService.weather.wind) ?? "--"
},
{
"icon": "speed",
"label": I18n.tr("Pressure"),
"value": WeatherService.formatPressure(WeatherService.weather.pressure) ?? "--"
},
{
"icon": "rainy",
"label": I18n.tr("Precipitation"),
"value": (WeatherService.weather.precipitationProbability ?? 0) + "%"
},
{
"icon": "wb_twilight",
"label": I18n.tr("Sunrise"),
"value": root.sunriseTimeText || "--"
},
{
"icon": "bedtime",
"label": I18n.tr("Sunset"),
"value": root.sunsetTimeText || "--"
}
];
}
Column { Column {
id: unavailableColumn id: unavailableColumn
@@ -60,7 +121,7 @@ Item {
DankIcon { DankIcon {
name: "cloud_off" name: "cloud_off"
size: Theme.iconSize * 2 size: Theme.iconSize * 2
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5) color: Theme.withAlpha(Theme.surfaceText, 0.5)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
@@ -73,7 +134,7 @@ Item {
id: refreshText id: refreshText
text: I18n.tr("No Weather Data Available") text: I18n.tr("No Weather Data Available")
font.pixelSize: Theme.fontSizeLarge font.pixelSize: Theme.fontSizeLarge
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Theme.withAlpha(Theme.surfaceText, 0.7)
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
@@ -81,7 +142,7 @@ Item {
id: refreshButtonTwo id: refreshButtonTwo
name: "refresh" name: "refresh"
size: Theme.iconSize - 4 size: Theme.iconSize - 4
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.4) color: Theme.withAlpha(Theme.surfaceText, 0.4)
anchors.top: parent.top anchors.top: parent.top
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -145,35 +206,39 @@ Item {
id: mainColumn id: mainColumn
anchors.fill: parent anchors.fill: parent
visible: root.available visible: root.available
spacing: Theme.spacingXS spacing: Theme.spacingS
Item {
id: weatherContainer
LayoutMirroring.enabled: false
LayoutMirroring.childrenInherit: true
Rectangle {
id: heroCard
width: parent.width width: parent.width
height: weatherColumn.height height: heroContent.height + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Theme.withAlpha(Theme.outline, 0.08)
border.width: 1
Column { Column {
id: weatherColumn id: heroContent
height: weatherInfo.height + dateStepper.height x: Theme.spacingL
width: Math.max(weatherInfo.width, dateStepper.width) y: Theme.spacingL
width: parent.width - Theme.spacingL * 2
spacing: Theme.spacingM
Item { Item {
id: weatherInfo width: parent.width
anchors.horizontalCenter: parent.horizontalCenter height: Math.max(heroLeft.height, heroMetricsGrid.height)
// anchors.verticalCenter: parent.verticalCenter
width: weatherIcon.width + tempColumn.width + sunriseColumn.width + Theme.spacingM * 2 Row {
height: Math.max(weatherIcon.height, tempColumn.height, sunriseColumn.height) id: heroLeft
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingL
DankIcon { DankIcon {
id: weatherIcon id: weatherIcon
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode) name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
size: Theme.iconSize * 1.5 size: Theme.iconSize * 2
color: Theme.primary color: Theme.primary
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
layer.enabled: true layer.enabled: true
@@ -190,8 +255,6 @@ Item {
Column { Column {
id: tempColumn id: tempColumn
spacing: Theme.spacingXS spacing: Theme.spacingXS
anchors.left: weatherIcon.right
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
Item { Item {
@@ -201,7 +264,7 @@ Item {
StyledText { StyledText {
id: tempText id: tempText
text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp) + "°" text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp) + "°"
font.pixelSize: Theme.fontSizeLarge + 4 font.pixelSize: Theme.fontSizeXLarge + 8
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Light font.weight: Font.Light
anchors.left: parent.left anchors.left: parent.left
@@ -212,7 +275,7 @@ Item {
id: unitText id: unitText
text: SettingsData.useFahrenheit ? "F" : "C" text: SettingsData.useFahrenheit ? "F" : "C"
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7) color: Theme.withAlpha(Theme.surfaceText, 0.7)
anchors.left: tempText.right anchors.left: tempText.right
anchors.leftMargin: Theme.spacingXS anchors.leftMargin: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -222,111 +285,86 @@ Item {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (WeatherService.weather.available) { if (WeatherService.weather.available)
SettingsData.set("useFahrenheit", !SettingsData.useFahrenheit); SettingsData.set("useFahrenheit", !SettingsData.useFahrenheit);
} }
}
enabled: WeatherService.weather.available enabled: WeatherService.weather.available
} }
} }
} }
StyledText {
text: WeatherService.getWeatherCondition(WeatherService.weather.wCode)
font.pixelSize: Theme.fontSizeMedium
color: Theme.withAlpha(Theme.surfaceText, 0.7)
}
StyledText { StyledText {
property var feelsLike: SettingsData.useFahrenheit ? (WeatherService.weather.feelsLikeF || WeatherService.weather.tempF) : (WeatherService.weather.feelsLike || WeatherService.weather.temp) property var feelsLike: SettingsData.useFahrenheit ? (WeatherService.weather.feelsLikeF || WeatherService.weather.tempF) : (WeatherService.weather.feelsLike || WeatherService.weather.temp)
text: I18n.tr("Feels Like %1°", "weather feels like temperature").arg(feelsLike) text: I18n.tr("Feels Like %1°", "weather feels like temperature").arg(feelsLike)
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.withAlpha(Theme.surfaceText, 0.7) color: Theme.withAlpha(Theme.surfaceText, 0.5)
} }
StyledText { StyledText {
text: WeatherService.weather.city || "" text: WeatherService.weather.city || ""
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeSmall
color: Theme.withAlpha(Theme.surfaceText, 0.7) color: Theme.withAlpha(Theme.surfaceText, 0.5)
visible: text.length > 0 visible: text.length > 0
} }
} }
}
Grid {
id: heroMetricsGrid
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
columns: 3
columnSpacing: Theme.spacingXL
rowSpacing: Theme.spacingS
Repeater {
model: root.heroMetrics
Row {
spacing: Theme.spacingXS
DankIcon {
name: modelData.icon
size: Theme.iconSizeSmall - 2
color: Theme.withAlpha(Theme.surfaceText, 0.5)
anchors.verticalCenter: parent.verticalCenter
}
Column { Column {
id: sunriseColumn spacing: 2
spacing: Theme.spacingXS
anchors.left: tempColumn.right
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
visible: WeatherService.weather.sunrise && WeatherService.weather.sunset
Item { StyledText {
width: sunriseIcon.width + sunriseText.width + Theme.spacingXS text: modelData.label
height: sunriseIcon.height font.pixelSize: Theme.fontSizeSmall
color: Theme.withAlpha(Theme.surfaceText, 0.5)
DankIcon {
id: sunriseIcon
name: "wb_twilight"
size: Theme.iconSize - 6
color: Theme.withAlpha(Theme.surfaceText, 0.6)
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
} }
StyledText { StyledText {
id: sunriseText text: modelData.value
text: { font.pixelSize: Theme.fontSizeMedium
if (!WeatherService.weather.rawSunrise) color: Theme.surfaceText
return WeatherService.weather.sunrise || ""; }
try { }
const date = new Date(WeatherService.weather.rawSunrise); }
const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP"; }
return date.toLocaleTimeString(Qt.locale(), format);
} catch (e) {
return WeatherService.weather.sunrise || "";
} }
} }
font.pixelSize: Theme.fontSizeSmall
color: Theme.withAlpha(Theme.surfaceText, 0.6)
anchors.left: sunriseIcon.right
anchors.leftMargin: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
} }
} }
Item { Item {
width: sunsetIcon.width + sunsetText.width + Theme.spacingXS id: skyDateRow
height: sunsetIcon.height width: parent.width
height: dateStepper.height
DankIcon {
id: sunsetIcon
name: "bedtime"
size: Theme.iconSize - 6
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
id: sunsetText
text: {
if (!WeatherService.weather.rawSunset)
return WeatherService.weather.sunset || "";
try {
const date = new Date(WeatherService.weather.rawSunset);
const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP";
return date.toLocaleTimeString(Qt.locale(), format);
} catch (e) {
return WeatherService.weather.sunset || "";
}
}
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
anchors.left: sunsetIcon.right
anchors.leftMargin: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
Item { Item {
id: dateStepper id: dateStepper
anchors.horizontalCenter: parent.horizontalCenter
height: dateStepperInner.height + Theme.spacingM * 2 height: dateStepperInner.height + Theme.spacingM * 2
width: dateStepperInner.width width: dateStepperInner.width
@@ -373,8 +411,6 @@ Item {
anchors.leftMargin: parent.space anchors.leftMargin: parent.space
width: implicitWidth width: implicitWidth
text: dateStepper.splitDate[0] text: dateStepper.splitDate[0]
// onIncrement: () => dateStepper.changeDate(0, +1)
// onDecrement: () => dateStepper.changeDate(0, -1)
} }
DankNumberStepper { DankNumberStepper {
@@ -475,14 +511,17 @@ Item {
onCurrentDateChanged: if (!syncing) onCurrentDateChanged: if (!syncing)
root.syncFrom("date") root.syncFrom("date")
} }
}
Rectangle { Rectangle {
id: skyBox id: skyBox
height: weatherColumn.height anchors.left: dateStepper.right
anchors.left: weatherColumn.right
anchors.right: parent.right
anchors.leftMargin: Theme.spacingM anchors.leftMargin: Theme.spacingM
anchors.right: parent.right
height: parent.height
LayoutMirroring.enabled: false
LayoutMirroring.childrenInherit: true
property var backgroundOpacity: 0.3 property var backgroundOpacity: 0.3
property var sunTime: WeatherService.getCurrentSunTime(dateStepper.currentDate) property var sunTime: WeatherService.getCurrentSunTime(dateStepper.currentDate)
property var periodIndex: sunTime?.periodIndex property var periodIndex: sunTime?.periodIndex
@@ -494,40 +533,12 @@ Item {
return Theme.blend(blackColor, blueColor, r); return Theme.blend(blackColor, blueColor, r);
} }
property var topColor: { property var topColor: {
const colorMap = [blackColor // "night" const colorMap = [blackColor, Theme.withAlpha(blackBlue(0.0), 0.8), Theme.withAlpha(blackBlue(0.2), 0.7), Theme.withAlpha(blackBlue(0.5), 0.6), Theme.withAlpha(blackBlue(0.7), 0.6), Theme.withAlpha(blackBlue(0.9), 0.6), Theme.withAlpha(blackBlue(1.0), 0.6), Theme.withAlpha(blackBlue(0.9), 0.6), Theme.withAlpha(blackBlue(0.7), 0.6), Theme.withAlpha(blackBlue(0.5), 0.6), Theme.withAlpha(blackBlue(0.2), 0.7), Theme.withAlpha(blackBlue(0.0), 0.8), blackColor, blackColor];
, Theme.withAlpha(blackBlue(0.0), 0.8) // "astronomicalTwilight"
, Theme.withAlpha(blackBlue(0.2), 0.7) // "nauticalTwilight"
, Theme.withAlpha(blackBlue(0.5), 0.6) // "civilTwilight"
, Theme.withAlpha(blackBlue(0.7), 0.6) // "sunrise"
, Theme.withAlpha(blackBlue(0.9), 0.6) // "goldenHourMorning"
, Theme.withAlpha(blackBlue(1.0), 0.6) // "daytime"
, Theme.withAlpha(blackBlue(0.9), 0.6) // "afternoon"
, Theme.withAlpha(blackBlue(0.7), 0.6) // "goldenHourEvening"
, Theme.withAlpha(blackBlue(0.5), 0.6) // "sunset"
, Theme.withAlpha(blackBlue(0.2), 0.7) // "civilTwilight"
, Theme.withAlpha(blackBlue(0.0), 0.8) // "nauticalTwilightEvening"
, blackColor // "astronomicalTwilightEvening"
, blackColor // "night"
,];
const index = periodIndex ?? 0; const index = periodIndex ?? 0;
return Theme.blend(colorMap[index], colorMap[index + 1], periodPercent ?? 0); return Theme.blend(colorMap[index], colorMap[index + 1], periodPercent ?? 0);
} }
property var sunColor: { property var sunColor: {
const colorMap = [Theme.withAlpha(redColor, 0.05) // "night" const colorMap = [Theme.withAlpha(redColor, 0.05), Theme.withAlpha(redColor, 0.1), Theme.withAlpha(redColor, 0.3), Theme.withAlpha(redColor, 0.4), Theme.withAlpha(redColor, 0.5), Theme.withAlpha(blueColor, 0.2), Theme.withAlpha(blueColor, 0.0), Theme.withAlpha(blueColor, 0.2), Theme.withAlpha(redColor, 0.5), Theme.withAlpha(redColor, 0.4), Theme.withAlpha(redColor, 0.3), Theme.withAlpha(redColor, 0.1), Theme.withAlpha(redColor, 0.05), Theme.withAlpha(redColor, 0.0)];
, Theme.withAlpha(redColor, 0.1) // "astronomicalTwilight"
, Theme.withAlpha(redColor, 0.3) // "nauticalTwilight"
, Theme.withAlpha(redColor, 0.4) // "civilTwilight"
, Theme.withAlpha(redColor, 0.5) // "sunrise"
, Theme.withAlpha(blueColor, 0.2) // "goldenHourMorning"
, Theme.withAlpha(blueColor, 0.0) // "daytime"
, Theme.withAlpha(blueColor, 0.2) // "afternoon"
, Theme.withAlpha(redColor, 0.5) // "goldenHourEvening"
, Theme.withAlpha(redColor, 0.4) // "sunset"
, Theme.withAlpha(redColor, 0.3) // "civilTwilight"
, Theme.withAlpha(redColor, 0.1) // "nauticalTwilightEvening"
, Theme.withAlpha(redColor, 0.05) // "astronomicalTwilightEvening"
, Theme.withAlpha(redColor, 0.0) // "night"
,];
const index = periodIndex ?? 0; const index = periodIndex ?? 0;
return Theme.blend(colorMap[index], colorMap[index + 1], periodPercent ?? 0); return Theme.blend(colorMap[index], colorMap[index + 1], periodPercent ?? 0);
} }
@@ -742,7 +753,6 @@ Item {
} }
Rectangle { Rectangle {
// Rightmost Line
height: 1 height: 1
anchors.leftMargin: Theme.spacingS anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS anchors.rightMargin: Theme.spacingS
@@ -753,7 +763,6 @@ Item {
} }
Rectangle { Rectangle {
// Middle Right Line
height: 1 height: 1
anchors.leftMargin: Theme.spacingS anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS anchors.rightMargin: Theme.spacingS
@@ -764,7 +773,6 @@ Item {
} }
Rectangle { Rectangle {
// Middle Left Line
height: 1 height: 1
anchors.leftMargin: Theme.spacingS anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS anchors.rightMargin: Theme.spacingS
@@ -775,7 +783,6 @@ Item {
} }
Rectangle { Rectangle {
// Leftmost Line
height: 1 height: 1
anchors.leftMargin: Theme.spacingS anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS anchors.rightMargin: Theme.spacingS
@@ -830,14 +837,42 @@ Item {
} }
} }
} }
}
Item {
width: parent.width
height: forecastChips.height
DankFilterChips {
id: forecastChips
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
model: [I18n.tr("Daily"), I18n.tr("Hourly")]
currentIndex: root.showHourly ? 1 : 0
showCheck: false
showCounts: false
onSelectionChanged: index => {
root.showHourly = index === 1;
}
}
DankActionButton {
id: denseButton
anchors.right: refreshButton.left
anchors.rightMargin: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
visible: root.showHourly && hourlyLoader.item !== null
iconName: SessionData.weatherHourlyDetailed ? "tile_large" : "tile_medium"
onClicked: SessionData.setWeatherHourlyDetailed(!SessionData.weatherHourlyDetailed)
}
DankIcon { DankIcon {
id: refreshButton id: refreshButton
name: "refresh" name: "refresh"
size: Theme.iconSize - 4 size: Theme.iconSize - 4
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.4) color: Theme.withAlpha(Theme.surfaceText, 0.4)
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.verticalCenter: parent.verticalCenter
property bool isRefreshing: false property bool isRefreshing: false
enabled: !isRefreshing enabled: !isRefreshing
@@ -894,45 +929,16 @@ Item {
} }
} }
Row {
width: parent.width
height: Math.max(hourlyHeader.height, denseButton.height) + Theme.spacingS
spacing: Theme.spacingS
StyledText {
id: hourlyHeader
anchors.verticalCenter: parent.verticalCenter
text: I18n.tr("Hourly Forecast")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: parent.width - denseButton.width - hourlyHeader.width - 2 * parent.spacing
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
}
DankActionButton {
id: denseButton
anchors.verticalCenter: parent.verticalCenter
visible: hourlyLoader.item !== null
iconName: SessionData.weatherHourlyDetailed ? "tile_large" : "tile_medium"
onClicked: SessionData.setWeatherHourlyDetailed(!SessionData.weatherHourlyDetailed)
}
}
Item { Item {
width: parent.width width: parent.width
height: (hourlyLoader.item?.cardHeight ?? (Theme.fontSizeLarge * 6)) + Theme.spacingXS height: root.showHourly ? ((hourlyLoader.item?.cardHeight ?? (Theme.fontSizeLarge * 6)) + Theme.spacingXS) : ((dailyLoader.item?.cardHeight ?? (Theme.fontSizeLarge * 6)) + Theme.spacingXS)
Loader { Loader {
id: hourlyLoader id: dailyLoader
anchors.fill: parent anchors.fill: parent
sourceComponent: hourlyComponent sourceComponent: dailyComponent
active: root.visible && root.available active: root.visible && root.available
visible: !root.showHourly
asynchronous: true asynchronous: true
opacity: 0 opacity: 0
onLoaded: { onLoaded: {
@@ -944,6 +950,25 @@ Item {
} }
} }
Loader {
id: hourlyLoader
anchors.fill: parent
sourceComponent: hourlyComponent
active: root.visible && root.available
visible: root.showHourly
asynchronous: true
opacity: 0
onLoaded: {
root.syncing = true;
item.currentIndex = item.initialIndex;
item.positionViewAtIndex(item.initialIndex, ListView.SnapPosition);
root.syncing = false;
opacity = 1;
}
}
}
}
Component { Component {
id: hourlyComponent id: hourlyComponent
ListView { ListView {
@@ -979,7 +1004,7 @@ Item {
d.setHours(index); d.setHours(index);
return d; return d;
} }
forecastData: WeatherService.weather.hourlyForecast?.[index] forecastData: WeatherService.weather.hourlyForecast[index]
} }
onCurrentIndexChanged: if (!syncing) onCurrentIndexChanged: if (!syncing)
@@ -1032,49 +1057,6 @@ Item {
} }
} }
} }
}
Row {
width: parent.width
height: dailyHeader.height + Theme.spacingS
spacing: Theme.spacingS
StyledText {
id: dailyHeader
anchors.verticalCenter: parent.verticalCenter
text: I18n.tr("Daily Forecast")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: parent.width - denseButton.width - dailyHeader.width - 2 * parent.spacing
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
}
}
Item {
width: parent.width
height: (dailyLoader.item?.cardHeight ?? (Theme.fontSizeLarge * 6)) + Theme.spacingXS
Loader {
id: dailyLoader
anchors.fill: parent
sourceComponent: dailyComponent
active: root.visible && root.available
asynchronous: true
opacity: 0
onLoaded: {
root.syncing = true;
item.currentIndex = item.initialIndex;
item.positionViewAtIndex(item.initialIndex, ListView.SnapPosition);
root.syncing = false;
opacity = 1;
}
}
Component { Component {
id: dailyComponent id: dailyComponent
@@ -1111,7 +1093,7 @@ Item {
date.setDate(date.getDate() + index); date.setDate(date.getDate() + index);
return date; return date;
} }
forecastData: WeatherService.weather.forecast?.[index] forecastData: WeatherService.weather.forecast[index]
} }
onCurrentIndexChanged: if (!syncing) onCurrentIndexChanged: if (!syncing)
@@ -1135,6 +1117,4 @@ Item {
} }
} }
} }
}
}
} }

View File

@@ -64,6 +64,12 @@ Flow {
} }
} }
DankRipple {
id: chipRipple
cornerRadius: chip.radius
rippleColor: chip.selected ? Theme.primaryText : Theme.surfaceVariantText
}
Row { Row {
id: contentRow id: contentRow
anchors.centerIn: parent anchors.centerIn: parent
@@ -91,6 +97,7 @@ Flow {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onPressed: mouse => chipRipple.trigger(mouse.x, mouse.y)
onClicked: { onClicked: {
root.currentIndex = chip.index; root.currentIndex = chip.index;
root.selectionChanged(chip.index); root.selectionChanged(chip.index);