mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-18 01:04:01 -04:00
157 lines
5.2 KiB
QML
157 lines
5.2 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import qs.Common
|
|
import qs.Services
|
|
import qs.DCommon.Widgets
|
|
import qs.Modules.DDash
|
|
|
|
Rectangle {
|
|
id: root
|
|
|
|
property bool daily: false
|
|
property bool chartMode: true
|
|
property var widgetOptions: ({})
|
|
property bool live: false
|
|
readonly property int visibleCount: Math.max(1, Math.min(daily ? DashMetrics.dailyVisibleCount : DashMetrics.chartHourlyCount, Math.floor(width / DashMetrics.gridRowUnit)))
|
|
property int startIndex: daily ? 0 : (WeatherService.weather.currentHourIndex ?? new Date().getHours())
|
|
readonly property var forecasts: (daily ? WeatherService.weather.forecast : WeatherService.weather.hourlyForecast) ?? []
|
|
readonly property int maxStart: Math.max(0, forecasts.length - visibleCount)
|
|
readonly property int start: Math.max(0, Math.min(maxStart, startIndex))
|
|
|
|
radius: Theme.cornerRadiusXL
|
|
color: DashMetrics.cardColor
|
|
border.width: Theme.layerOutlineWidth
|
|
border.color: Theme.outlineMedium
|
|
|
|
function step(delta) {
|
|
const next = Math.max(0, Math.min(maxStart, start + delta));
|
|
if (next === start)
|
|
return false;
|
|
startIndex = next;
|
|
return true;
|
|
}
|
|
|
|
Item {
|
|
id: header
|
|
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.margins: Theme.spacingM
|
|
height: Theme.buttonHeightS
|
|
|
|
Row {
|
|
id: title
|
|
|
|
anchors.left: parent.left
|
|
anchors.right: actions.left
|
|
anchors.rightMargin: Theme.spacingS
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: Theme.spacingS
|
|
|
|
DIcon {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
name: root.daily ? "calendar_month" : "schedule"
|
|
size: Theme.iconSize
|
|
color: Theme.onSurface
|
|
}
|
|
|
|
StyledText {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: Math.max(0, title.width - Theme.iconSize - title.spacing)
|
|
text: root.daily ? I18n.tr("Daily") : I18n.tr("Hourly")
|
|
font.pixelSize: Theme.fontSizeLarge
|
|
font.weight: Theme.fontWeightMedium
|
|
color: Theme.onSurface
|
|
elide: Text.ElideRight
|
|
}
|
|
}
|
|
|
|
Row {
|
|
id: actions
|
|
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: Theme.spacingXS
|
|
|
|
DActionButton {
|
|
buttonSize: Theme.buttonHeightS
|
|
iconName: I18n.isRtl ? "chevron_right" : "chevron_left"
|
|
Accessible.name: I18n.tr("Previous")
|
|
enabled: root.start > 0
|
|
onClicked: root.step(-1)
|
|
}
|
|
|
|
DActionButton {
|
|
buttonSize: Theme.buttonHeightS
|
|
iconName: "today"
|
|
Accessible.name: I18n.tr("Today")
|
|
onClicked: root.startIndex = root.daily ? 0 : (WeatherService.weather.currentHourIndex ?? new Date().getHours())
|
|
}
|
|
|
|
DActionButton {
|
|
buttonSize: Theme.buttonHeightS
|
|
iconName: I18n.isRtl ? "chevron_left" : "chevron_right"
|
|
Accessible.name: I18n.tr("Next")
|
|
enabled: root.start < root.maxStart
|
|
onClicked: root.step(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: header.bottom
|
|
anchors.bottom: parent.bottom
|
|
active: root.live
|
|
sourceComponent: root.chartMode ? chart : cards
|
|
}
|
|
|
|
Component {
|
|
id: chart
|
|
WeatherForecastChart {
|
|
daily: root.daily
|
|
visibleCount: root.visibleCount
|
|
startIndex: root.start
|
|
onPageRequested: delta => root.step(delta)
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: cards
|
|
Item {
|
|
Row {
|
|
id: cardRow
|
|
anchors.fill: parent
|
|
anchors.topMargin: Theme.spacingS
|
|
anchors.leftMargin: Theme.spacingM
|
|
anchors.rightMargin: Theme.spacingM
|
|
anchors.bottomMargin: Theme.spacingM
|
|
spacing: Theme.spacingS
|
|
Repeater {
|
|
model: root.forecasts.slice(root.start, root.start + root.visibleCount)
|
|
WeatherForecastCard {
|
|
required property var modelData
|
|
required property int index
|
|
width: (cardRow.width - cardRow.spacing * (root.visibleCount - 1)) / root.visibleCount
|
|
height: cardRow.height
|
|
daily: root.daily
|
|
dense: true
|
|
forecastData: modelData
|
|
isCurrent: root.start + index === (root.daily ? 0 : (WeatherService.weather.currentHourIndex ?? new Date().getHours()))
|
|
}
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
anchors.centerIn: parent
|
|
visible: root.forecasts.length === 0
|
|
text: I18n.tr("Forecast Not Available")
|
|
color: Theme.onSurfaceVariant
|
|
}
|
|
}
|
|
}
|
|
}
|