mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-15 15:54:00 -04:00
296 lines
10 KiB
QML
296 lines
10 KiB
QML
import QtQuick
|
|
import qs.Common
|
|
import qs.Services
|
|
import qs.Widgets
|
|
import qs.Modules.DankDash
|
|
import qs.Modules.DankDash.Weather
|
|
import "../Weather/WeatherVisuals.js" as Visuals
|
|
|
|
Card {
|
|
id: root
|
|
|
|
property bool live: Window.window?.visible ?? false
|
|
property bool weatherRefHeld: false
|
|
|
|
readonly property bool available: WeatherService.weather.available
|
|
readonly property bool tall: height > width
|
|
readonly property bool narrow: width < DashMetrics.gridRowUnit * 2
|
|
readonly property bool compact: narrow && !tall
|
|
readonly property bool wide: width >= DashMetrics.gridRowUnit * 3
|
|
readonly property bool roomy: !narrow && height >= DashMetrics.gridRowUnit * 2
|
|
readonly property bool stacked: tall || narrow || roomy
|
|
readonly property bool heroLayout: available && roomy && wide
|
|
readonly property bool showReadings: options.readings !== false
|
|
readonly property bool showCity: options.city === true && available && !!WeatherService.weather.city
|
|
readonly property string cityText: WeatherService.weather.city ?? ""
|
|
readonly property string rowTitle: showCity && wide ? cityText + " · " + conditionText : conditionText
|
|
readonly property string rowSubtitle: {
|
|
if (showReadings)
|
|
return wide ? readingsText : feelsLikeText;
|
|
return showCity && !wide ? cityText : "";
|
|
}
|
|
readonly property string iconName: available ? WeatherService.getWeatherIcon(WeatherService.weather.wCode, WeatherService.weather.isDay) : "cloud_off"
|
|
readonly property string tempText: available ? WeatherService.currentTempText(false) : I18n.tr("No Weather")
|
|
readonly property string conditionText: available ? WeatherService.getWeatherCondition(WeatherService.weather.wCode) : ""
|
|
readonly property string feelsLikeText: {
|
|
if (!available)
|
|
return "";
|
|
const feelsLike = SettingsData.useFahrenheit ? (WeatherService.weather.feelsLikeF ?? WeatherService.weather.tempF) : (WeatherService.weather.feelsLike ?? WeatherService.weather.temp);
|
|
return I18n.tr("Feels Like %1°", "weather feels like temperature").arg(feelsLike);
|
|
}
|
|
readonly property string readingsText: {
|
|
if (!available)
|
|
return "";
|
|
const parts = [feelsLikeText];
|
|
const humidity = WeatherService.formatPercent(WeatherService.weather.humidity);
|
|
if (humidity)
|
|
parts.push(humidity);
|
|
const wind = WeatherService.formatSpeed(WeatherService.weather.wind);
|
|
if (wind)
|
|
parts.push(wind);
|
|
return parts.join(" · ");
|
|
}
|
|
|
|
entryId: "weather"
|
|
tone: options.tone ?? ""
|
|
clickable: true
|
|
pad: compact ? Theme.spacingS : Theme.spacingM
|
|
|
|
function syncWeatherRef(wanted) {
|
|
if (wanted === weatherRefHeld)
|
|
return;
|
|
weatherRefHeld = wanted;
|
|
if (wanted) {
|
|
WeatherService.addRef();
|
|
return;
|
|
}
|
|
WeatherService.removeRef();
|
|
}
|
|
|
|
onLiveChanged: syncWeatherRef(live)
|
|
Component.onCompleted: syncWeatherRef(live)
|
|
Component.onDestruction: syncWeatherRef(false)
|
|
|
|
Column {
|
|
anchors.fill: parent
|
|
spacing: Theme.spacingXS
|
|
visible: root.compact
|
|
|
|
Row {
|
|
width: parent.width
|
|
height: parent.height - compactCondition.height - parent.spacing
|
|
spacing: Theme.spacingXS
|
|
|
|
Item {
|
|
id: compactIcon
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: Math.min(parent.height, parent.width * DashMetrics.weatherCompactIconRatio)
|
|
height: width
|
|
|
|
DankIcon {
|
|
anchors.centerIn: parent
|
|
name: root.iconName
|
|
size: parent.width
|
|
color: root.accentColor
|
|
visible: root.available || !WeatherService.weather.loading
|
|
}
|
|
|
|
DankSpinner {
|
|
anchors.centerIn: parent
|
|
size: parent.width
|
|
color: root.contentColor
|
|
visible: !root.available && WeatherService.weather.loading
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: parent.width - compactIcon.width - parent.spacing
|
|
height: parent.height
|
|
text: root.available ? root.tempText : ""
|
|
font.pixelSize: Theme.fontSizeXXLarge
|
|
minimumPixelSize: Theme.fontSizeLarge
|
|
fontSizeMode: Text.HorizontalFit
|
|
font.weight: Theme.fontWeightMedium
|
|
color: root.contentColor
|
|
horizontalAlignment: Text.AlignRight
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideRight
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
id: compactCondition
|
|
width: parent.width
|
|
text: root.available ? (root.showCity ? root.cityText : root.conditionText) : root.tempText
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
font.weight: Theme.fontWeightMedium
|
|
color: root.mutedColor
|
|
elide: Text.ElideRight
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: stackedLayout
|
|
anchors.fill: parent
|
|
visible: root.stacked && !root.compact && !root.heroLayout
|
|
|
|
DankMaterialShape {
|
|
id: stackedChip
|
|
width: Math.min(parent.width * 0.5, parent.height * 0.42)
|
|
height: width
|
|
shape: Visuals.conditionShape(WeatherService.weather.wCode, WeatherService.weather.isDay)
|
|
color: root.chipColor
|
|
|
|
DankIcon {
|
|
anchors.centerIn: parent
|
|
name: root.iconName
|
|
size: parent.width * 0.55
|
|
color: root.accentColor
|
|
visible: root.available || !WeatherService.weather.loading
|
|
}
|
|
|
|
DankSpinner {
|
|
anchors.centerIn: parent
|
|
size: parent.width * 0.55
|
|
color: root.contentColor
|
|
visible: !root.available && WeatherService.weather.loading
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
anchors.top: parent.top
|
|
anchors.right: parent.right
|
|
anchors.left: stackedChip.right
|
|
anchors.leftMargin: Theme.spacingS
|
|
text: root.cityText
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
font.weight: Theme.fontWeightMedium
|
|
color: root.mutedColor
|
|
horizontalAlignment: Text.AlignRight
|
|
elide: Text.ElideRight
|
|
visible: root.showCity && !root.narrow
|
|
}
|
|
|
|
Column {
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
spacing: 0
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
text: root.tempText
|
|
font.pixelSize: root.available ? Math.min(Theme.fontSizeDisplay * 1.5, stackedLayout.height * 0.32) : Theme.fontSizeMedium
|
|
font.weight: Theme.fontWeightMedium
|
|
font.features: ({
|
|
"tnum": 1
|
|
})
|
|
minimumPixelSize: Theme.fontSizeXLarge
|
|
fontSizeMode: Text.HorizontalFit
|
|
color: root.contentColor
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
text: root.conditionText
|
|
font.pixelSize: root.narrow ? Theme.fontSizeSmall : Theme.fontSizeMedium
|
|
font.weight: Theme.fontWeightMedium
|
|
color: root.mutedColor
|
|
elide: Text.ElideRight
|
|
maximumLineCount: 1
|
|
visible: text !== ""
|
|
}
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
text: root.narrow ? root.feelsLikeText : root.readingsText
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
color: root.mutedColor
|
|
elide: Text.ElideRight
|
|
visible: root.showReadings && text !== ""
|
|
}
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
text: root.cityText
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
font.weight: Theme.fontWeightMedium
|
|
color: root.mutedColor
|
|
elide: Text.ElideRight
|
|
visible: root.showCity && root.narrow
|
|
}
|
|
}
|
|
}
|
|
|
|
WeatherHero {
|
|
anchors.fill: parent
|
|
visible: root.heroLayout
|
|
showCity: root.showCity
|
|
showSunTimes: root.showReadings
|
|
tone: root.tone
|
|
flat: true
|
|
}
|
|
|
|
Row {
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: Theme.spacingM
|
|
visible: !root.stacked
|
|
|
|
DankMaterialShape {
|
|
id: iconChip
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: Math.min(DashMetrics.weatherChipSize, root.height - root.pad * 2)
|
|
height: width
|
|
shape: Visuals.conditionShape(WeatherService.weather.wCode, WeatherService.weather.isDay)
|
|
color: root.chipColor
|
|
|
|
DankIcon {
|
|
anchors.centerIn: parent
|
|
name: root.iconName
|
|
size: Theme.iconSize
|
|
color: root.accentColor
|
|
}
|
|
}
|
|
|
|
Column {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: parent.width - iconChip.width - tempLabel.width - parent.spacing * 2
|
|
spacing: 0
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
text: root.available ? root.rowTitle : root.tempText
|
|
wrapMode: Text.NoWrap
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
font.weight: Theme.fontWeightMedium
|
|
color: root.contentColor
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
text: root.rowSubtitle
|
|
wrapMode: Text.NoWrap
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
font.weight: Theme.fontWeightMedium
|
|
color: root.mutedColor
|
|
elide: Text.ElideRight
|
|
visible: text !== ""
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
id: tempLabel
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: root.available ? root.tempText : ""
|
|
font.pixelSize: DashMetrics.weatherTempSize
|
|
font.weight: Theme.fontWeightMedium
|
|
color: root.contentColor
|
|
}
|
|
}
|
|
}
|