-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathwidget-progress-circle.js
113 lines (100 loc) · 3.35 KB
/
widget-progress-circle.js
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
/*
* progressCircle(on: Stack or Widget, value: number, colour: string, background: string, size: number, barWidth: number) : Promise<Stack>
*
* PARAMS
* on - the stack or widget to add the progress circle to
* value - a number between 1 and 100 to be the circle percentage or a number between 0 and 1 to be the circle percentage
* colour - a HTML supported (hex, rgb, hsl) colour for the progress of the circle. Alternitively, it can be two HTML supported colours seperated by a hyphen (white-black) for the first colour to be active on light mode and second on dark mode
* background - a HTML supported (hex, rgb, hsl) colour for the unfilled progress of the circle. Alternitively, it can be two HTML supported colours seperated by a hyphen (white-black) for the first colour to be active on light mode and second on dark mode
* size - the size of the progress circle
* barWidth - the width of the circular progress bar
*
* RETURNS
* A stack with the background image set to the progress circle and with set padding.
*/
// Example usage
const widget = new ListWidget()
let progressStack = await progressCircle(widget,35)
let sf = SFSymbol.named("cloud.fill")
sf.applyFont(Font.regularSystemFont(26))
sf = progressStack.addImage(sf.image)
sf.imageSize = new Size(26,26)
sf.tintColor = new Color("#fafafa")
widget.presentAccessoryCircular() // Does not present correctly
Script.setWidget(widget)
Script.complete()
async function progressCircle(
on,
value = 50,
colour = "hsl(0, 0%, 100%)",
background = "hsl(0, 0%, 10%)",
size = 56,
barWidth = 5.5
) {
if (value > 1) {
value /= 100
}
if (value < 0) {
value = 0
}
if (value > 1) {
value = 1
}
async function isUsingDarkAppearance() {
return !Color.dynamic(Color.white(), Color.black()).red
}
let isDark = await isUsingDarkAppearance()
if (colour.split("-").length > 1) {
if (isDark) {
colour = colour.split("-")[1]
} else {
colour = colour.split("-")[0]
}
}
if (background.split("-").length > 1) {
if (isDark) {
background = background.split("-")[1]
} else {
background = background.split("-")[0]
}
}
let w = new WebView()
await w.loadHTML('<canvas id="c"></canvas>')
let base64 = await w.evaluateJavaScript(
`
let colour = "${colour}",
background = "${background}",
size = ${size}*3,
lineWidth = ${barWidth}*3,
percent = ${value * 100}
let canvas = document.getElementById('c'),
c = canvas.getContext('2d')
canvas.width = size
canvas.height = size
let posX = canvas.width / 2,
posY = canvas.height / 2,
onePercent = 360 / 100,
result = onePercent * percent
c.lineCap = 'round'
c.beginPath()
c.arc( posX, posY, (size-lineWidth-1)/2, (Math.PI/180) * 270, (Math.PI/180) * (270 + 360) )
c.strokeStyle = background
c.lineWidth = lineWidth
c.stroke()
c.beginPath()
c.strokeStyle = colour
c.lineWidth = lineWidth
c.arc( posX, posY, (size-lineWidth-1)/2, (Math.PI/180) * 270, (Math.PI/180) * (270 + result) )
c.stroke()
completion(canvas.toDataURL().replace("data:image/png;base64,",""))`,
true
)
const image = Image.fromData(Data.fromBase64String(base64))
let stack = on.addStack()
stack.size = new Size(size, size)
stack.backgroundImage = image
stack.centerAlignContent()
let padding = barWidth * 2
stack.setPadding(padding, padding, padding, padding)
return stack
}