websocket-text-relay 1.1.4 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/changelog.md +4 -0
  2. package/docs/code-structure.md +15 -11
  3. package/eslint.config.js +5 -1
  4. package/package.json +9 -9
  5. package/src/ui/css/main.css +22 -78
  6. package/src/ui/favicon.png +0 -0
  7. package/src/ui/index.html +19 -14
  8. package/src/ui/js/components/activityLabels.js +41 -0
  9. package/src/ui/js/components/activityTimeSeries.js +58 -0
  10. package/src/ui/js/components/drawSessionLabel.js +117 -0
  11. package/src/ui/js/components/footerStatus.js +37 -0
  12. package/src/ui/js/components/headers.js +100 -0
  13. package/src/ui/js/components/sessionWedges.js +96 -0
  14. package/src/ui/js/components/statusRing.js +51 -0
  15. package/src/ui/js/data/wtrActivity.js +85 -0
  16. package/src/ui/js/data/wtrActivity.types.js +3 -0
  17. package/src/ui/js/data/wtrStatus.js +134 -0
  18. package/src/ui/js/data/wtrStatus.types.js +61 -0
  19. package/src/ui/js/{util → setup}/EventEmitter.js +5 -1
  20. package/src/ui/js/{util → setup}/WebsocketClient.js +1 -4
  21. package/src/ui/js/setup/dependencyManager.js +9 -0
  22. package/src/ui/js/setup/evalOnChange.js +18 -0
  23. package/src/ui/js/setup/eventSubscriber.js +21 -0
  24. package/src/ui/js/setup.js +141 -0
  25. package/src/ui/js/util/constants.js +5 -1
  26. package/src/ui/js/util/drawing.js +26 -76
  27. package/src/websocket-interface/httpServer.js +1 -1
  28. package/src/ui/js/components/ActivityTimeseriesGraph.js +0 -194
  29. package/src/ui/js/components/HeaderSummary.js +0 -22
  30. package/src/ui/js/components/ServerStatus.js +0 -43
  31. package/src/ui/js/components/SessionLabels.js +0 -319
  32. package/src/ui/js/components/SessionWedges.js +0 -127
  33. package/src/ui/js/components/StatusRing.js +0 -54
  34. package/src/ui/js/components/grids.js +0 -36
  35. package/src/ui/js/index.js +0 -121
  36. package/src/ui/js/main.js +0 -128
  37. package/src/ui/js/util/DependencyManager.js +0 -31
@@ -1,319 +0,0 @@
1
- const {
2
- exportDeps,
3
- polarToCartesian,
4
- coordsToPathData,
5
- drawLinearPath,
6
- drawCircle,
7
- drawText,
8
- drawSvgElement,
9
- drawToolTip,
10
- } = window.__WTR__
11
-
12
- // a value with a colored circle and tooltip
13
- const drawSummaryValue = ({ x, y, label, circleClass, parentNode }) => {
14
- const tooltipWrapperGroup = drawSvgElement({
15
- tag: "g",
16
- className: "tooltip_wrapper_group",
17
- parent: parentNode,
18
- })
19
- drawCircle({
20
- cx: x,
21
- cy: y - 0.0032,
22
- r: summaryCircleRadius,
23
- className: circleClass,
24
- parentNode: tooltipWrapperGroup,
25
- })
26
- drawToolTip({ x: x, y: y - 0.0032, text: label, parentNode: tooltipWrapperGroup })
27
- return drawText({
28
- x: x + summaryCircleRadius * 2,
29
- y: y,
30
- dominantBaseline: "middle",
31
- text: "0",
32
- className: "summary_text_value",
33
- parentNode: tooltipWrapperGroup,
34
- })
35
- }
36
-
37
- // similar to summary value, but with an update function that automatically handles moving the circle on the left as the text size changes
38
- const drawRightAlignedSummaryValue = ({ x, y, label, circleClass, parentNode }) => {
39
- const tooltipWrapperGroup = drawSvgElement({
40
- tag: "g",
41
- className: "tooltip_wrapper_group",
42
- parent: parentNode,
43
- })
44
- drawToolTip({ x: x, y: y - 0.0032, text: label, parentNode: tooltipWrapperGroup })
45
- const textElement = drawText({
46
- x: x + summaryCircleRadius * 2,
47
- y: y,
48
- dominantBaseline: "middle",
49
- text: "0",
50
- textAnchor: "end",
51
- className: "summary_text_value",
52
- parentNode: tooltipWrapperGroup,
53
- })
54
- const xDiff = textElement.getBBox().width
55
- const labelCircle = drawCircle({
56
- cx: x - xDiff,
57
- cy: y - 0.0032,
58
- r: summaryCircleRadius,
59
- className: circleClass,
60
- parentNode: tooltipWrapperGroup,
61
- })
62
- const update = (value) => {
63
- textElement.textContent = value
64
- const xDiff = textElement.getBBox().width
65
- labelCircle.setAttribute("cx", x - xDiff)
66
- }
67
- return { textElement, update }
68
- }
69
-
70
- const underlinePadding = 0.01
71
- const summaryCircleRadius = 0.014
72
- const summaryLeftPadding = 0.03
73
- const summaryValueSpacing = 0.065
74
- const editorSummaryPadding = 0.025
75
-
76
- const addPadding = ({ x, y, height, width }, horizontalPadding, verticalPadding) => {
77
- if (verticalPadding == null) {
78
- verticalPadding = horizontalPadding
79
- }
80
- x -= horizontalPadding
81
- width += horizontalPadding * 2
82
- y -= verticalPadding
83
- height += verticalPadding * 2
84
- return { x, y, height, width }
85
- }
86
-
87
- const labelLineDistance = 0.07
88
-
89
- class ClientLabel {
90
- constructor({ wedgeCenterAngle, wedgeCenterRadius, parentNode }) {
91
- this.parentNode = parentNode
92
- this.wedgeCenterAngle = wedgeCenterAngle
93
- this.wedgeCenterRadius = wedgeCenterRadius
94
- this.wedgeCenter = polarToCartesian(this.wedgeCenterAngle, this.wedgeCenterRadius)
95
- this.draw()
96
- }
97
-
98
- draw() {
99
- const textStart = polarToCartesian(this.wedgeCenterAngle, this.wedgeCenterRadius + labelLineDistance)
100
-
101
- this.topNameElement = drawText({
102
- x: textStart[0],
103
- y: textStart[1] - 0.06 - underlinePadding / 2,
104
- text: "",
105
- className: ["wedge_identifier", "small_text"],
106
- parentNode: this.parentNode,
107
- })
108
- this.nameTextElement = drawText({
109
- x: textStart[0],
110
- y: textStart[1] - 0.017 - underlinePadding / 2,
111
- text: ".",
112
- className: "wedge_identifier",
113
- parentNode: this.parentNode,
114
- })
115
-
116
- drawCircle({
117
- cx: this.wedgeCenter[0],
118
- cy: this.wedgeCenter[1],
119
- r: 0.01,
120
- className: "test_circle",
121
- parentNode: this.parentNode,
122
- })
123
-
124
- const textBbox = addPadding(this.nameTextElement.getBBox(), 0.0, underlinePadding)
125
- const underlineCoords = [
126
- [this.wedgeCenter[0], this.wedgeCenter[1]],
127
- [textBbox.x, textBbox.y + textBbox.height],
128
- [textBbox.x + textBbox.width, textBbox.y + textBbox.height],
129
- ]
130
- this.underlinePath = drawLinearPath({
131
- coords: underlineCoords,
132
- className: "test_line",
133
- parentNode: this.parentNode,
134
- })
135
-
136
- const summaryMidY = textBbox.y + textBbox.height + underlinePadding + summaryCircleRadius / 2 + 0.02
137
- const summaryStartX = textBbox.x + summaryLeftPadding
138
- this.watchedCountElement = drawSummaryValue({
139
- x: summaryStartX,
140
- y: summaryMidY,
141
- label: "Watched Files",
142
- circleClass: "summary_watched_circle",
143
- parentNode: this.parentNode,
144
- })
145
- const watchedCountBbox = this.watchedCountElement.getBBox()
146
-
147
- const xDiff = summaryValueSpacing + watchedCountBbox.width
148
- this.activeCountTranslateWrapper = drawSvgElement({
149
- tag: "g",
150
- attributes: { transform: `translate(${xDiff}, 0)` },
151
- parent: this.parentNode,
152
- })
153
- this.activeCountElement = drawSummaryValue({
154
- x: summaryStartX,
155
- y: summaryMidY,
156
- label: "Active Files",
157
- circleClass: "summary_active_circle",
158
- parentNode: this.activeCountTranslateWrapper,
159
- })
160
- }
161
-
162
- update(client) {
163
- let { name } = client
164
- if (!name || name.length === 0) {
165
- name = "."
166
- }
167
-
168
- if (name.length > 14) {
169
- const halfIndex = Math.floor(name.length / 2)
170
- const nameFirstHalf = name.substring(0, halfIndex)
171
- const nameSecondHalf = name.substring(halfIndex, name.length)
172
- this.topNameElement.textContent = nameFirstHalf
173
- this.nameTextElement.textContent = nameSecondHalf
174
- this.nameTextElement.classList.add("small_text")
175
- } else {
176
- this.topNameElement.innerHTML = ""
177
- this.nameTextElement.classList.remove("small_text")
178
- this.nameTextElement.textContent = name
179
- }
180
-
181
- const textBbox = addPadding(this.nameTextElement.getBBox(), 0.0, underlinePadding)
182
- const underlineCoords = [
183
- [this.wedgeCenter[0], this.wedgeCenter[1]],
184
- [textBbox.x, textBbox.y + textBbox.height],
185
- [textBbox.x + textBbox.width, textBbox.y + textBbox.height],
186
- ]
187
- const newUnderlinePathData = coordsToPathData(underlineCoords)
188
- this.underlinePath.setAttribute("d", newUnderlinePathData)
189
-
190
- this.watchedCountElement.textContent = client.watchCount
191
- this.activeCountElement.textContent = client.activeWatchCount
192
-
193
- const xDiff = summaryValueSpacing + this.watchedCountElement.getBBox().width
194
- this.activeCountTranslateWrapper.setAttribute("transform", `translate(${xDiff}, 0)`)
195
- }
196
- }
197
-
198
- class EditorLabel {
199
- constructor({ wedgeCenterAngle, wedgeCenterRadius, parentNode }) {
200
- this.parentNode = parentNode
201
- this.wedgeCenterAngle = wedgeCenterAngle
202
- this.wedgeCenterRadius = wedgeCenterRadius
203
- this.wedgeCenter = polarToCartesian(this.wedgeCenterAngle, this.wedgeCenterRadius)
204
- this.draw()
205
- }
206
-
207
- draw() {
208
- const textStart = polarToCartesian(this.wedgeCenterAngle, this.wedgeCenterRadius + labelLineDistance)
209
-
210
- this.topNameElement = drawText({
211
- x: textStart[0],
212
- y: textStart[1] - 0.06 - underlinePadding / 2,
213
- text: "",
214
- textAnchor: "end",
215
- className: ["wedge_identifier", "small_text"],
216
- parentNode: this.parentNode,
217
- })
218
- this.nameTextElement = drawText({
219
- x: textStart[0],
220
- y: textStart[1] - 0.017 - underlinePadding / 2,
221
- text: ".",
222
- textAnchor: "end",
223
- className: "wedge_identifier",
224
- parentNode: this.parentNode,
225
- })
226
-
227
- drawCircle({
228
- cx: this.wedgeCenter[0],
229
- cy: this.wedgeCenter[1],
230
- r: 0.01,
231
- className: "test_circle",
232
- parentNode: this.parentNode,
233
- })
234
-
235
- const textBbox = addPadding(this.nameTextElement.getBBox(), 0.0, underlinePadding)
236
- const underlineCoords = [
237
- [this.wedgeCenter[0], this.wedgeCenter[1]],
238
- [textBbox.x, textBbox.y + textBbox.height],
239
- [textBbox.x + textBbox.width, textBbox.y + textBbox.height],
240
- ]
241
- this.underlinePath = drawLinearPath({
242
- coords: underlineCoords,
243
- className: "test_line",
244
- parentNode: this.parentNode,
245
- })
246
-
247
- const summaryStartX = textBbox.x + textBbox.width - summaryLeftPadding
248
- const summaryMidY = textBbox.y + textBbox.height + underlinePadding * 3 + summaryCircleRadius / 2
249
-
250
- this.activeCountSummaryValue = drawRightAlignedSummaryValue({
251
- x: summaryStartX,
252
- y: summaryMidY,
253
- label: "Active Files",
254
- circleClass: "summary_active_circle",
255
- parentNode: this.parentNode,
256
- })
257
- const xDiff =
258
- this.activeCountSummaryValue.textElement.getBBox().width +
259
- summaryCircleRadius +
260
- editorSummaryPadding * 2
261
- this.openFilesTransformGroup = drawSvgElement({
262
- tag: "g",
263
- attributes: { transform: `translate(${-xDiff})` },
264
- parent: this.parentNode,
265
- })
266
- this.openCountSummaryValue = drawRightAlignedSummaryValue({
267
- x: summaryStartX,
268
- y: summaryMidY,
269
- label: "Open Files",
270
- circleClass: "summary_watched_circle",
271
- parentNode: this.openFilesTransformGroup,
272
- })
273
- }
274
-
275
- update(editor) {
276
- let { name } = editor
277
- if (!name || name.length === 0) {
278
- name = "."
279
- } else if (name === "Visual Studio Code") {
280
- name = "VSCode"
281
- }
282
-
283
- if (editor.isServer) {
284
- name = "* " + name
285
- }
286
-
287
- if (name.length > 14) {
288
- const halfIndex = Math.floor(name.length / 2)
289
- const nameFirstHalf = name.substring(0, halfIndex)
290
- const nameSecondHalf = name.substring(halfIndex, name.length)
291
- this.topNameElement.textContent = nameFirstHalf
292
- this.nameTextElement.textContent = nameSecondHalf
293
- this.nameTextElement.classList.add("small_text")
294
- } else {
295
- this.topNameElement.innerHTML = ""
296
- this.nameTextElement.classList.remove("small_text")
297
- this.nameTextElement.textContent = name
298
- }
299
-
300
- const textBbox = addPadding(this.nameTextElement.getBBox(), 0.0, underlinePadding)
301
- const underlineCoords = [
302
- [this.wedgeCenter[0], this.wedgeCenter[1]],
303
- [textBbox.x + textBbox.width, textBbox.y + textBbox.height],
304
- [textBbox.x, textBbox.y + textBbox.height],
305
- ]
306
- const newUnderlinePathData = coordsToPathData(underlineCoords)
307
- this.underlinePath.setAttribute("d", newUnderlinePathData)
308
-
309
- this.activeCountSummaryValue.update(editor.activeOpenCount)
310
- this.openCountSummaryValue.update(editor.openCount)
311
- const xDiff =
312
- this.activeCountSummaryValue.textElement.getBBox().width +
313
- summaryCircleRadius +
314
- editorSummaryPadding * 2
315
- this.openFilesTransformGroup.setAttribute("transform", `translate(${-xDiff})`)
316
- }
317
- }
318
-
319
- exportDeps({ ClientLabel, EditorLabel })
@@ -1,127 +0,0 @@
1
- const { exportDeps, drawSvgElement, drawWedge } = window.__WTR__
2
-
3
- const numWedges = 5
4
- const wedgeSpacing = 0.01
5
- const wedgeWidth = 0.08
6
-
7
- const flashAnimationKeyframes = [{ fill: "#fff" }, { fill: "var(--wedge-active-color)" }]
8
- const flashAnimationProps = { duration: 250, easing: "ease-out", iterations: 1 }
9
-
10
- const createSessionSummary = (sessions) => {
11
- const summary = {
12
- name: `${sessions.length - numWedges + 1} others...`,
13
- watchCount: 0,
14
- activeWatchCount: 0,
15
- openCount: 0,
16
- activeOpenCount: 0,
17
- }
18
-
19
- for (let i = numWedges - 1; i < sessions.length; i++) {
20
- const session = sessions[i]
21
- summary.watchCount += session.watchCount
22
- summary.activeWatchCount += session.activeWatchCount
23
- summary.openCount += session.openCount
24
- summary.activeOpenCount += session.activeOpenCount
25
- }
26
-
27
- return summary
28
- }
29
-
30
- class SessionWedges {
31
- constructor({ outerRingRadius, outerArcSize, direction = 1, Label, parentNode }) {
32
- this.outerRingRadius = outerRingRadius
33
- this.outerArcSize = outerArcSize
34
- this.parentNode = parentNode
35
- this.direction = direction
36
- this.Label = Label
37
- this.draw()
38
- }
39
-
40
- draw() {
41
- this.parentNode.innerHTML = ""
42
- this.wedgeNodes = []
43
- const totalStartAngle = 0.25 + (this.direction * this.outerArcSize) / 2
44
- const totalAngleDelta = 0.5 - this.outerArcSize - wedgeSpacing
45
- const wedgeAngleDelta = totalAngleDelta / numWedges - wedgeSpacing
46
- const innerRadius = this.outerRingRadius - wedgeWidth / 2
47
- for (let i = 0; i < numWedges; i++) {
48
- const group = drawSvgElement({
49
- tag: "g",
50
- className: "single_wedge_group",
51
- parent: this.parentNode,
52
- })
53
-
54
- let startAngle =
55
- totalStartAngle + this.direction * (i + 1) * wedgeSpacing + this.direction * i * wedgeAngleDelta
56
- if (this.direction === -1) {
57
- startAngle -= wedgeAngleDelta
58
- }
59
-
60
- const wedge = drawWedge({
61
- startAngle,
62
- angleDelta: wedgeAngleDelta,
63
- innerRadius,
64
- radiusDelta: wedgeWidth,
65
- className: "wedge_node",
66
- parentNode: group,
67
- })
68
-
69
- const wedgeCenterAngle = startAngle + wedgeAngleDelta / 2
70
- const label = new this.Label({
71
- wedgeCenterAngle,
72
- wedgeCenterRadius: this.outerRingRadius,
73
- parentNode: group,
74
- })
75
-
76
- this.wedgeNodes.push({ group, label, wedge })
77
- }
78
- this.drawCalled = true
79
- }
80
-
81
- update(sessions) {
82
- this.sessionsData = sessions
83
- for (let i = 0; i < numWedges; i++) {
84
- const { group, label } = this.wedgeNodes[i]
85
- group.classList.remove("active", "online")
86
- let session = sessions[i]
87
- if (!session) {
88
- continue
89
- }
90
-
91
- if (i === numWedges - 1 && sessions.length > numWedges) {
92
- session = createSessionSummary(sessions)
93
- }
94
-
95
- if (session.activeWatchCount > 0 || session.activeOpenCount > 0) {
96
- group.classList.add("active")
97
- } else {
98
- group.classList.add("online")
99
- }
100
-
101
- label.update(session)
102
- }
103
- }
104
-
105
- triggerActivity(sessionIds) {
106
- const sessions = this.sessionsData
107
- if (!sessions) {
108
- return
109
- }
110
- for (let i = 0; i < numWedges; i++) {
111
- const { wedge } = this.wedgeNodes[i]
112
- const session = sessions[i]
113
- if (!session) {
114
- continue
115
- }
116
-
117
- if (
118
- (typeof sessionIds === "number" && session.id === sessionIds) ||
119
- (sessionIds.has && sessionIds.has(session.id))
120
- ) {
121
- wedge.animate(flashAnimationKeyframes, flashAnimationProps)
122
- }
123
- }
124
- }
125
- }
126
-
127
- exportDeps({ SessionWedges })
@@ -1,54 +0,0 @@
1
- const { exportDeps, drawCircle, drawWedge } = window.__WTR__
2
-
3
- class StatusRing {
4
- constructor({ innerRingRadius, outerRingRadius, outerArcSize, parentNode }) {
5
- this.innerRingRadius = innerRingRadius
6
- this.outerRingRadius = outerRingRadius
7
- this.outerArcSize = outerArcSize
8
- this.parentNode = parentNode
9
- this.draw()
10
- }
11
-
12
- draw() {
13
- this.parentNode.innerHTML = ""
14
- this.parentNode.classList.remove(...this.parentNode.classList)
15
- this.currentClassName = "offline"
16
- this.parentNode.classList.add(this.currentClassName)
17
-
18
- drawCircle({ cx: 0, cy: 0, r: this.innerRingRadius, parentNode: this.parentNode })
19
- drawWedge({
20
- startAngle: 0.25 - this.outerArcSize / 2,
21
- angleDelta: this.outerArcSize,
22
- innerRadius: this.outerRingRadius,
23
- radiusDelta: 0,
24
- parentNode: this.parentNode,
25
- })
26
- drawWedge({
27
- startAngle: 0.75 - this.outerArcSize / 2,
28
- angleDelta: this.outerArcSize,
29
- innerRadius: this.outerRingRadius,
30
- radiusDelta: 0,
31
- parentNode: this.parentNode,
32
- })
33
- }
34
-
35
- update(data) {
36
- const hasActiveClient = data.clients.some((client) => client.activeWatchCount > 0)
37
- let newClassName
38
- if (hasActiveClient) {
39
- newClassName = "active"
40
- } else if (data.clients.length > 0) {
41
- newClassName = "online"
42
- } else {
43
- newClassName = "offline"
44
- }
45
-
46
- if (newClassName != this.currentClassName) {
47
- this.parentNode.classList.remove(this.currentClassName)
48
- this.parentNode.classList.add(newClassName)
49
- this.currentClassName = newClassName
50
- }
51
- }
52
- }
53
-
54
- exportDeps({ StatusRing })
@@ -1,36 +0,0 @@
1
- const { exportDeps, drawLine, drawCircle, drawPolarLine } = window.__WTR__
2
-
3
- const gridCellWidth = 0.08
4
- const maxGrid = 1
5
-
6
- const drawGrid = (parentNode) => {
7
- for (let i = 0; i < maxGrid; i += gridCellWidth) {
8
- const className = i === 0 ? "grid_axis" : "grid_line"
9
- drawLine({ x1: -1, y1: i, x2: 1, y2: i, className, parentNode })
10
- drawLine({ x1: -1, y1: -i, x2: 1, y2: -i, className, parentNode })
11
- drawLine({ x1: i, y1: -1, x2: i, y2: 1, className, parentNode })
12
- drawLine({ x1: -i, y1: -1, x2: -i, y2: 1, className, parentNode })
13
- }
14
- }
15
-
16
- const radiusDiff = 0.04
17
- const angleDiff = 0.025
18
-
19
- const drawPolarGrid = (parentNode) => {
20
- for (let r = 0; r <= 1.0001; r += radiusDiff) {
21
- drawCircle({ cx: 0, cy: 0, r, className: "grid_line", parentNode })
22
- }
23
-
24
- for (let angle = 0; angle < 1; angle += angleDiff) {
25
- drawPolarLine({
26
- startAngle: 0,
27
- startRadius: 0,
28
- endAngle: angle,
29
- endRadius: 1,
30
- className: "grid_line",
31
- parentNode,
32
- })
33
- }
34
- }
35
-
36
- exportDeps({ drawGrid, drawPolarGrid })
@@ -1,121 +0,0 @@
1
- import { WebsocketClient } from "./util/WebsocketClient.js"
2
- import "./util/DependencyManager.js"
3
-
4
- const { cleanupEventHandlers, statusDataEmitter } = window.__WTR__
5
-
6
- const FILE_PREFIX = "websocket-text-relay/src/ui/"
7
- const CSS_FILE = "css/main.css"
8
- const cssEndsWith = FILE_PREFIX + CSS_FILE
9
-
10
- const MAIN_JS_FILE = "js/main.js"
11
- const mainJsEndsWith = FILE_PREFIX + MAIN_JS_FILE
12
-
13
- const jsFiles = [
14
- "js/util/constants.js",
15
- "js/util/drawing.js",
16
- "js/components/grids.js",
17
- "js/components/HeaderSummary.js",
18
- "js/components/StatusRing.js",
19
- "js/components/SessionWedges.js",
20
- "js/components/SessionLabels.js",
21
- "js/components/ActivityTimeseriesGraph.js",
22
- "js/components/ServerStatus.js",
23
- MAIN_JS_FILE,
24
- ]
25
-
26
- const svgRoot = document.getElementById("svg_root")
27
- const cssElement = document.getElementById("main_style")
28
-
29
- const { hostname, port, protocol } = window.location
30
- const wsProtocol = protocol === "http:" ? "ws" : "wss"
31
- const ws = new WebsocketClient({ port: port, host: hostname, protocol: wsProtocol })
32
-
33
- const handleCss = (contents) => {
34
- cssElement.innerText = contents
35
- }
36
-
37
- let lastMainContents = null
38
- let initFinished = false
39
- const handleJs = (contents) => {
40
- try {
41
- eval(contents)
42
- } catch (e) {
43
- window._lastEvalError = e
44
- console.log(e)
45
- }
46
- }
47
-
48
- ws.emitter.on("message", (message) => {
49
- console.log("got emitter message", message)
50
- if (message.endsWith === cssEndsWith) {
51
- handleCss(message.contents)
52
- return
53
- }
54
- if (message.method === "watch-file" && message.endsWith.endsWith(".js")) {
55
- if (!initFinished) {
56
- return
57
- }
58
- cleanupEventHandlers()
59
- handleJs(message.contents)
60
- if (message.endsWith === mainJsEndsWith) {
61
- lastMainContents = message.contents
62
- } else if (lastMainContents != null) {
63
- handleJs(lastMainContents)
64
- }
65
- return
66
- }
67
- if (message.method === "watch-wtr-status") {
68
- statusDataEmitter.emit("data", message.data)
69
- return
70
- }
71
- if (message.method === "watch-wtr-activity") {
72
- statusDataEmitter.emit("activity", message.data)
73
- return
74
- }
75
- })
76
-
77
- ws.emitter.on("socket-open", () => statusDataEmitter.emit("socket-open"))
78
- ws.emitter.on("socket-close", () => statusDataEmitter.emit("socket-close"))
79
-
80
- const initFiles = async () => {
81
- await fetch(CSS_FILE)
82
- .then((r) => r.text())
83
- .then(handleCss)
84
- const jsFetches = jsFiles.map(async (fileName) => {
85
- return fetch(fileName).then((r) => r.text())
86
- })
87
- const jsResults = await Promise.all(jsFetches)
88
- lastMainContents = jsResults.at(-1)
89
- requestAnimationFrame(() => {
90
- // make sure css is applied first
91
- jsResults.forEach((contents) => {
92
- handleJs(contents)
93
- })
94
- initFinished = true
95
- })
96
- }
97
-
98
- const subscribeWatchers = () => {
99
- ws.sendMessage({ method: "watch-log-messages" })
100
- ws.sendMessage({ method: "watch-wtr-status" })
101
- ws.sendMessage({ method: "watch-wtr-activity" })
102
- ws.sendMessage({ method: "init", name: "status-ui" })
103
- ws.sendMessage({ method: "watch-file", endsWith: cssEndsWith })
104
- jsFiles.forEach((jsFile) => {
105
- const jsEndsWith = FILE_PREFIX + jsFile
106
- ws.sendMessage({ method: "watch-file", endsWith: jsEndsWith })
107
- })
108
- }
109
-
110
- await initFiles()
111
- subscribeWatchers()
112
-
113
- const updateSvgDimensions = () => {
114
- svgRoot.setAttribute("height", window.innerHeight - 4)
115
- svgRoot.setAttribute("width", window.innerWidth)
116
- }
117
-
118
- updateSvgDimensions()
119
- window.addEventListener("resize", () => {
120
- updateSvgDimensions()
121
- })