Files
Panama/config/dot/quickshell/modules/datemenu/AgendaPane.qml
T

293 lines
9.7 KiB
QML

import QtQuick
import Quickshell
import qs.config
import qs.services
import qs.modules.quicksettings
Item {
id: root
readonly property bool isToday: CalendarAgenda.selectedDateKey === CalendarAgenda.dateKey(clock.date)
readonly property var upNext: CalendarAgenda.nextEventForSelectedDate
readonly property var listedEvents: CalendarAgenda.selectedEvents.filter(event => !root.upNext || event.id !== root.upNext.id)
readonly property string selectedLabel: root.isToday
? "Today"
: Qt.formatDate(CalendarAgenda.selectedDate, "dddd, MMMM d")
implicitHeight: content.implicitHeight
SystemClock {
id: clock
precision: SystemClock.Minutes
}
Column {
id: content
width: parent.width
spacing: 12
Column {
width: parent.width
spacing: 3
visible: CalendarAgenda.phase === "loading"
Text {
text: "CALENDAR"
color: Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
font.letterSpacing: 1.1
}
Text {
text: "Loading calendars…"
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.DemiBold
}
}
Column {
width: parent.width
spacing: 10
visible: CalendarAgenda.phase === "unavailable"
Text {
text: "Calendar data is unavailable"
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.DemiBold
}
Text {
width: parent.width
wrapMode: Text.WordWrap
text: "Notifications, weather, and the month grid are still available. GNOME Calendar may have more detail."
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
}
ActionPill {
text: "Open Calendar"
onClicked: CalendarAgenda.openCalendar(CalendarAgenda.selectedDate)
}
}
Rectangle {
id: nextCard
width: parent.width
height: visible ? 88 : 0
visible: CalendarAgenda.available && root.isToday && root.upNext !== null
radius: Theme.cardRadius
border.width: 1
border.color: Theme.alpha(Theme.accent, 0.18)
color: Theme.alpha(Theme.accent, 0.105)
clip: true
Rectangle {
anchors.right: parent.right
anchors.rightMargin: -24
anchors.bottom: parent.bottom
anchors.bottomMargin: -34
width: 110
height: 110
radius: 55
border.width: 0
color: Theme.alpha(Theme.accentSecondary, 0.08)
}
Column {
anchors.left: parent.left
anchors.leftMargin: 14
anchors.right: nextJoin.visible ? nextJoin.left : parent.right
anchors.rightMargin: nextJoin.visible ? 10 : 14
anchors.verticalCenter: parent.verticalCenter
spacing: 5
Text {
text: "UP NEXT · " + root.relativeStart(root.upNext)
color: Theme.accent
font.family: Theme.fontFamily
font.features: Theme.tabularFigures
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
font.letterSpacing: 0.8
}
Text {
width: parent.width
text: root.upNext?.summary ?? ""
color: Theme.fg
elide: Text.ElideRight
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.DemiBold
}
Text {
width: parent.width
text: root.eventDetail(root.upNext)
color: Theme.fgDim
elide: Text.ElideRight
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
}
ActionPill {
id: nextJoin
anchors.right: parent.right
anchors.rightMargin: 12
anchors.top: parent.top
anchors.topMargin: 12
visible: String(root.upNext?.joinUrl ?? "").startsWith("https://")
text: "Join"
accent: true
onClicked: CalendarAgenda.join(root.upNext)
}
MouseArea {
anchors.fill: parent
z: -1
cursorShape: Qt.PointingHandCursor
onClicked: CalendarAgenda.openEvent(root.upNext)
}
}
Item {
width: parent.width
height: 34
visible: CalendarAgenda.available
Column {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: 2
Text {
text: root.selectedLabel.toUpperCase()
color: Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
font.letterSpacing: 0.9
}
Text {
text: "Your schedule"
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.DemiBold
}
}
Text {
anchors.right: parent.right
anchors.bottom: parent.bottom
text: CalendarAgenda.selectedEvents.length + (CalendarAgenda.selectedEvents.length === 1 ? " event" : " events")
color: Theme.fgDim
font.family: Theme.fontFamily
font.features: Theme.tabularFigures
font.pixelSize: Theme.fontSizeSmall
}
}
Item {
width: parent.width
height: visible ? 92 : 0
visible: CalendarAgenda.available && CalendarAgenda.selectedEvents.length === 0
Column {
anchors.centerIn: parent
spacing: 8
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: "Nothing scheduled"
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
}
ActionPill {
anchors.horizontalCenter: parent.horizontalCenter
text: "Open Calendar"
onClicked: CalendarAgenda.openCalendar(CalendarAgenda.selectedDate)
}
}
}
ScrollColumn {
width: parent.width
maxHeight: 286
spacing: 0
visible: CalendarAgenda.available && root.listedEvents.length > 0
Repeater {
model: root.listedEvents
AgendaEvent {
required property var modelData
width: parent.width
eventData: modelData
past: Number(modelData.end) <= CalendarAgenda.nowEpoch
onActivated: CalendarAgenda.openEvent(modelData)
onJoinRequested: CalendarAgenda.join(modelData)
}
}
}
}
function relativeStart(event: var): string {
if (!event)
return "";
const seconds = Number(event.start) - CalendarAgenda.nowEpoch;
if (seconds <= 0)
return "NOW";
if (seconds < 3600)
return "IN " + Math.ceil(seconds / 60) + " MINUTES";
return Qt.formatTime(new Date(Number(event.start) * 1000), Settings.use24Hour ? "HH:mm" : "h:mm AP");
}
function eventDetail(event: var): string {
if (!event)
return "";
const source = CalendarAgenda.sourceForId(event.sourceId)?.name ?? "Calendar";
const location = String(event.location ?? "").trim();
return location === "" ? source : source + " · " + location;
}
component ActionPill: Rectangle {
id: action
required property string text
property bool accent: false
signal clicked
width: actionLabel.implicitWidth + 20
height: 28
radius: Theme.pillRadius
border.width: 0
color: actionMouse.containsMouse
? Theme.alpha(action.accent ? Theme.accent : Theme.fg, 0.24)
: Theme.alpha(action.accent ? Theme.accent : Theme.fg, action.accent ? 0.14 : 0.07)
Text {
id: actionLabel
anchors.centerIn: parent
text: action.text
color: action.accent ? Theme.accent : Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
}
MouseArea {
id: actionMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: action.clicked()
}
}
}