-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTimeUntilWidget.qml
More file actions
145 lines (122 loc) · 4.19 KB
/
TimeUntilWidget.qml
File metadata and controls
145 lines (122 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import QtQuick
import Quickshell
import qs.Common
import qs.Widgets
import qs.Modules.Plugins
PluginComponent {
id: root
layerNamespacePlugin: "timeUntil"
// settings from pluginData
property string targetTimestamp: pluginData.targetTimestamp || ""
property string unit: pluginData.unit || "days"
property string label: pluginData.label || ""
property real value: 0
function recalc() {
if (!targetTimestamp) {
value = NaN
return
}
const target = new Date(targetTimestamp.replace("T", " "))
if (isNaN(target.getTime())) {
value = NaN
return
}
const now = new Date()
let diffMs = target.getTime() - now.getTime()
let divisor
switch (unit) {
case "hours": divisor = 1000 * 60 * 60; break
case "days": divisor = 1000 * 60 * 60 * 24; break
case "weeks": divisor = 1000 * 60 * 60 * 24 * 7; break
case "months": divisor = 1000 * 60 * 60 * 24 * 30.44; break
default: divisor = 1000 * 60 * 60 * 24
}
if (diffMs < 0) {
const raw = Math.abs(diffMs) / divisor
value = -(Math.round(raw * 10) / 10)
return
}
const raw = diffMs / divisor
value = Math.round(raw * 10) / 10
}
function displayText() {
if (isNaN(value))
return targetTimestamp ? "Invalid date" : "No date set"
const absValue = Math.abs(value)
const effectiveLabel = value < 0 ? "overdue" : (label && label.trim().length > 0 ? label.trim() : "remaining")
const display = absValue % 1 === 0 ? absValue.toFixed(0) : absValue.toFixed(1)
const pluralUnit = absValue === 1 ? unit.slice(0, -1) : unit
return display + " " + pluralUnit + " " + effectiveLabel
}
function shortUnit() {
switch (unit) {
case "hours": return "h"
case "days": return "d"
case "weeks": return "w"
case "months": return "mo"
default: return "d"
}
}
function displayTextShort() {
if (isNaN(value))
return targetTimestamp ? "!date" : "—"
const absValue = Math.abs(value)
const display = absValue % 1 === 0 ? absValue.toFixed(0) : absValue.toFixed(1)
const suffix = value < 0 ? "!" : ""
return display + shortUnit() + suffix
}
// Recalculate the remaining time when settings are changed
onTargetTimestampChanged: recalc()
onUnitChanged: recalc()
onLabelChanged: recalc()
Timer {
interval: {
switch (root.unit) {
case "hours": return 1000 * 60 * 6 // 0.1 hour
case "days": return 1000 * 60 * 60 * 2.4 // 0.1 day
case "weeks": return 1000 * 60 * 60 * 24 // 1 day
case "months": return 1000 * 60 * 60 * 24 // 1 day
default: return 1000 * 60 * 60 * 2.4
}
}
running: true
repeat: true
onTriggered: recalc()
}
Component.onCompleted: recalc()
horizontalBarPill: Component {
Row {
spacing: Theme.spacingXS
StyledText {
text: displayText()
font.pixelSize: Theme.fontSizeMedium
}
}
}
verticalBarPill: Component {
Column {
spacing: Theme.spacingXS
StyledText {
text: displayTextShort()
font.pixelSize: Theme.fontSizeMedium
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
popoutContent: Component {
PopoutComponent {
id: popout
showCloseButton: false
StyledText {
width: parent.width
readonly property string helpText: "Set the target date in DMS Settings > Plugins > Time Until"
text: !root.targetTimestamp ? helpText : (root.value < 0 ? "Time since " : "Time until ") + root.targetTimestamp
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
}
}
popoutWidth: 250
}