@openbrf/display 0.0.0-stage → 0.1.1
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.
- package/LICENSE +661 -0
- package/LICENSE-EXCEPTION.md +28 -0
- package/README.md +126 -2
- package/dist/contract.d.ts +244 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +54 -0
- package/dist/contract.js.map +1 -0
- package/dist/fetch-loop.d.ts +87 -0
- package/dist/fetch-loop.d.ts.map +1 -0
- package/dist/fetch-loop.js +351 -0
- package/dist/fetch-loop.js.map +1 -0
- package/dist/fit.d.ts +44 -0
- package/dist/fit.d.ts.map +1 -0
- package/dist/fit.js +257 -0
- package/dist/fit.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/parse.d.ts +39 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +494 -0
- package/dist/parse.js.map +1 -0
- package/dist/renderer.d.ts +85 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +476 -0
- package/dist/renderer.js.map +1 -0
- package/dist/rotation.d.ts +129 -0
- package/dist/rotation.d.ts.map +1 -0
- package/dist/rotation.js +335 -0
- package/dist/rotation.js.map +1 -0
- package/dist/slides.d.ts +41 -0
- package/dist/slides.d.ts.map +1 -0
- package/dist/slides.js +341 -0
- package/dist/slides.js.map +1 -0
- package/dist/styles.d.ts +10 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +107 -0
- package/dist/styles.js.map +1 -0
- package/dist/text.d.ts +16 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +62 -0
- package/dist/text.js.map +1 -0
- package/dist/time.d.ts +39 -0
- package/dist/time.d.ts.map +1 -0
- package/dist/time.js +94 -0
- package/dist/time.js.map +1 -0
- package/dist/translate.d.ts +18 -0
- package/dist/translate.d.ts.map +1 -0
- package/dist/translate.js +35 -0
- package/dist/translate.js.map +1 -0
- package/dist/words.d.ts +41 -0
- package/dist/words.d.ts.map +1 -0
- package/dist/words.js +73 -0
- package/dist/words.js.map +1 -0
- package/package.json +58 -3
- package/src/contract.ts +279 -0
- package/src/fetch-loop.ts +472 -0
- package/src/fit.ts +348 -0
- package/src/index.ts +77 -0
- package/src/parse.ts +605 -0
- package/src/renderer.ts +708 -0
- package/src/rotation.ts +515 -0
- package/src/slides.ts +595 -0
- package/src/styles.ts +113 -0
- package/src/text.ts +65 -0
- package/src/time.ts +147 -0
- package/src/translate.ts +56 -0
- package/src/words.ts +91 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The renderer: mounts on an element and shows a screen content document.
|
|
3
|
+
*
|
|
4
|
+
* It takes a document and nothing else, and fetches nothing. A picture comes
|
|
5
|
+
* from a function its caller hands it, so that a device token never has to be
|
|
6
|
+
* in a picture's URL; the caller fetches the bytes with the token in a header
|
|
7
|
+
* and hands back an object URL.
|
|
8
|
+
*/
|
|
9
|
+
import type { PictureRef, ScreenContent, ScreenLocale } from "./contract.ts";
|
|
10
|
+
/** What the renderer is handed besides the element. */
|
|
11
|
+
export interface RendererOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Hands back a URL the renderer may put in an `<img>`, or null when the
|
|
14
|
+
* picture cannot be had. Called once for each `mediaFileId` and `version` a
|
|
15
|
+
* document refers to, and the result reused while documents go on referring
|
|
16
|
+
* to it; a null or a failure is asked again on a document shown five or more
|
|
17
|
+
* minutes later. The renderer never fetches.
|
|
18
|
+
*/
|
|
19
|
+
picture?: (ref: PictureRef) => Promise<string | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Told when a URL `picture` handed back is no longer used: the documents
|
|
22
|
+
* stopped referring to it, the browser could not show it, the renderer
|
|
23
|
+
* showed a message, or it was destroyed. Told once for each URL each call
|
|
24
|
+
* of `picture` handed back, also one that arrived after it was no longer
|
|
25
|
+
* wanted. The place to revoke an object URL.
|
|
26
|
+
*/
|
|
27
|
+
releasePicture?: (url: string, ref: PictureRef) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Whether `mountRenderer` adds `DISPLAY_STYLESHEET` to the document as a
|
|
30
|
+
* `<style>` element; true unless set. Set it false on a page whose content
|
|
31
|
+
* security policy has no `'unsafe-inline'` in `style-src`, which refuses that
|
|
32
|
+
* element, and serve the stylesheet as a file of its own, linked as
|
|
33
|
+
* `<link rel="stylesheet" data-obrf-display>`. A page that has such a link
|
|
34
|
+
* (or a `<style data-obrf-display>`) in its head gets no second copy without
|
|
35
|
+
* this option.
|
|
36
|
+
*/
|
|
37
|
+
stylesheet?: boolean;
|
|
38
|
+
/** The clock, for tests. Timers are the global `setTimeout` and `clearTimeout`. */
|
|
39
|
+
now?: () => Date;
|
|
40
|
+
}
|
|
41
|
+
/** How fresh the content being shown is. */
|
|
42
|
+
export interface DisplayStatus {
|
|
43
|
+
/** When the content was last fetched, or confirmed by a 304. */
|
|
44
|
+
fetchedAt: Date;
|
|
45
|
+
/** True while the instance cannot be reached and this is the last good content. */
|
|
46
|
+
stale: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A full-screen message shown instead of content, with nothing from the
|
|
50
|
+
* instance in it:
|
|
51
|
+
*
|
|
52
|
+
* - `loading`: no content yet.
|
|
53
|
+
* - `link-invalid`: the instance refused the device token; the display link
|
|
54
|
+
* is no longer valid.
|
|
55
|
+
* - `not-connected`: no content to show for 24 hours.
|
|
56
|
+
* - `link-missing`: the address holds no device token.
|
|
57
|
+
* - `paused`: the route is switched off (a plugin's device route answering 404).
|
|
58
|
+
*/
|
|
59
|
+
export type DisplayMessage = "loading" | "link-invalid" | "not-connected" | "link-missing" | "paused";
|
|
60
|
+
/** A mounted renderer. */
|
|
61
|
+
export interface DisplayRenderer {
|
|
62
|
+
/**
|
|
63
|
+
* Shows a document, replacing the previous one whole. The slide on screen
|
|
64
|
+
* stays when the new document still has a slide with its id; otherwise the
|
|
65
|
+
* rotation starts from the first. With `status.stale`, a small note says
|
|
66
|
+
* when the content was fetched.
|
|
67
|
+
*
|
|
68
|
+
* A slide the canvas cannot hold whole, such as eight events or a long news
|
|
69
|
+
* item, is shown a page at a time, each page for the slide's `seconds`, and
|
|
70
|
+
* nothing on it is cut off.
|
|
71
|
+
*/
|
|
72
|
+
show(content: ScreenContent, status?: DisplayStatus): void;
|
|
73
|
+
/** Shows a message instead of content, in the given language. */
|
|
74
|
+
message(kind: DisplayMessage, locale: ScreenLocale): void;
|
|
75
|
+
/** Clears every timer and empties the element. */
|
|
76
|
+
destroy(): void;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Mounts a renderer on `element`, replacing what it holds, and adds the
|
|
80
|
+
* stylesheet to its document once, unless `options.stylesheet` is false or the
|
|
81
|
+
* page already links it. Give the element a size, such as the whole
|
|
82
|
+
* viewport: the canvas fills it, turned by the document's orientation.
|
|
83
|
+
*/
|
|
84
|
+
export declare function mountRenderer(element: HTMLElement, options?: RendererOptions): DisplayRenderer;
|
|
85
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,YAAY,EAEb,MAAM,eAAe,CAAC;AAcvB,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtD;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,KAAK,IAAI,CAAC;IACxD;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,SAAS,EAAE,IAAI,CAAC;IAChB,mFAAmF;IACnF,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GACxB,SAAS,GAAG,cAAc,GAAG,eAAe,GAAG,cAAc,GAAG,QAAQ,CAAC;AAE3E,0BAA0B;AAC1B,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC3D,iEAAiE;IACjE,OAAO,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1D,kDAAkD;IAClD,OAAO,IAAI,IAAI,CAAC;CACjB;AAsBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,eAAoB,GAC5B,eAAe,CAojBjB"}
|
package/dist/renderer.js
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import { capitalised, element as newElement, formatTime, inSchedule, renderSlide, replaceContent, } from "./slides.js";
|
|
2
|
+
import { fitSlide } from "./fit.js";
|
|
3
|
+
import { DISPLAY_STYLESHEET } from "./styles.js";
|
|
4
|
+
import { translate } from "./translate.js";
|
|
5
|
+
import { MINUTE, zonedDayStartAfter } from "./time.js";
|
|
6
|
+
const MESSAGES = {
|
|
7
|
+
loading: { title: "loading", detail: null },
|
|
8
|
+
"link-invalid": { title: "linkInvalid", detail: "linkInvalidDetail" },
|
|
9
|
+
"not-connected": { title: "notConnected", detail: "notConnectedDetail" },
|
|
10
|
+
"link-missing": { title: "linkMissing", detail: "linkMissingDetail" },
|
|
11
|
+
paused: { title: "paused", detail: "pausedDetail" },
|
|
12
|
+
};
|
|
13
|
+
const STYLE_ATTRIBUTE = "data-obrf-display";
|
|
14
|
+
const PICTURE_RETRY = 5 * MINUTE;
|
|
15
|
+
/**
|
|
16
|
+
* Mounts a renderer on `element`, replacing what it holds, and adds the
|
|
17
|
+
* stylesheet to its document once, unless `options.stylesheet` is false or the
|
|
18
|
+
* page already links it. Give the element a size, such as the whole
|
|
19
|
+
* viewport: the canvas fills it, turned by the document's orientation.
|
|
20
|
+
*/
|
|
21
|
+
export function mountRenderer(element, options = {}) {
|
|
22
|
+
const document = element.ownerDocument;
|
|
23
|
+
const clockNow = () => (options.now ?? (() => new Date()))().getTime();
|
|
24
|
+
if (options.stylesheet !== false) {
|
|
25
|
+
addStylesheet(document);
|
|
26
|
+
}
|
|
27
|
+
const make = (tag, className, text) => newElement(document, tag, className, text);
|
|
28
|
+
const root = make("div", "obrf-display obrf-display--dark");
|
|
29
|
+
const canvas = make("div", "obrf-display-canvas");
|
|
30
|
+
const clock = make("div", "obrf-display-clock");
|
|
31
|
+
const clockDate = make("span", "obrf-display-clock-date");
|
|
32
|
+
const clockTime = make("span", "obrf-display-clock-time");
|
|
33
|
+
const stage = make("div", "obrf-display-stage");
|
|
34
|
+
const note = make("div", "obrf-display-note");
|
|
35
|
+
const off = make("div", "obrf-display-off");
|
|
36
|
+
clock.append(clockDate, clockTime);
|
|
37
|
+
canvas.append(clock, stage, note);
|
|
38
|
+
root.append(canvas, off);
|
|
39
|
+
clock.hidden = true;
|
|
40
|
+
note.hidden = true;
|
|
41
|
+
off.hidden = true;
|
|
42
|
+
replaceContent(element, root);
|
|
43
|
+
let content = null;
|
|
44
|
+
let status = null;
|
|
45
|
+
let current = null;
|
|
46
|
+
/** A hundredth of the canvas's shorter side, in pixels; 0 before it has a size. */
|
|
47
|
+
let unit = 0;
|
|
48
|
+
let slideTimer = null;
|
|
49
|
+
let minuteTimer = null;
|
|
50
|
+
let destroyed = false;
|
|
51
|
+
const pictures = new Map();
|
|
52
|
+
// The canvas is the element's box, turned. At 90 and 270 degrees its width
|
|
53
|
+
// is the element's height, so it is sized from the element in pixels.
|
|
54
|
+
const resizeObserver = typeof ResizeObserver === "function"
|
|
55
|
+
? new ResizeObserver(() => layout())
|
|
56
|
+
: null;
|
|
57
|
+
const view = document.defaultView;
|
|
58
|
+
if (resizeObserver === null) {
|
|
59
|
+
view?.addEventListener("resize", layout);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
resizeObserver.observe(element);
|
|
63
|
+
}
|
|
64
|
+
const fonts = document.fonts;
|
|
65
|
+
fonts?.addEventListener("loadingdone", refit);
|
|
66
|
+
function layout() {
|
|
67
|
+
const orientation = content?.layout.orientation ?? 0;
|
|
68
|
+
const width = element.clientWidth;
|
|
69
|
+
const height = element.clientHeight;
|
|
70
|
+
const turned = orientation === 90 || orientation === 270;
|
|
71
|
+
canvas.style.transform = `translate(-50%, -50%) rotate(${orientation}deg)`;
|
|
72
|
+
if (turned && width > 0 && height > 0) {
|
|
73
|
+
canvas.style.width = `${height}px`;
|
|
74
|
+
canvas.style.height = `${width}px`;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
canvas.style.width = "100%";
|
|
78
|
+
canvas.style.height = "100%";
|
|
79
|
+
}
|
|
80
|
+
unit = width > 0 && height > 0 ? Math.min(width, height) / 100 : 0;
|
|
81
|
+
if (unit > 0) {
|
|
82
|
+
root.style.setProperty("--obrf-display-u", `${unit}px`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
root.style.removeProperty("--obrf-display-u");
|
|
86
|
+
}
|
|
87
|
+
const portrait = turned ? width > height : height > width;
|
|
88
|
+
root.classList.toggle("obrf-display--portrait", portrait);
|
|
89
|
+
for (const degrees of [0, 90, 180, 270]) {
|
|
90
|
+
root.classList.toggle(`obrf-display--orientation-${degrees}`, degrees === orientation);
|
|
91
|
+
}
|
|
92
|
+
refit();
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Fits the slide on screen again: a new size, or a typeface that has just
|
|
96
|
+
* loaded, holds another number of items.
|
|
97
|
+
*/
|
|
98
|
+
function refit() {
|
|
99
|
+
const slide = stage.firstElementChild;
|
|
100
|
+
if (current !== null && slide?.classList.contains("obrf-display-slide")) {
|
|
101
|
+
const { page, pages } = fitSlide(slide, unit, current.page);
|
|
102
|
+
current = { ...current, page, pages };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function setTheme(theme) {
|
|
106
|
+
root.classList.toggle("obrf-display--light", theme === "light");
|
|
107
|
+
root.classList.toggle("obrf-display--dark", theme === "dark");
|
|
108
|
+
}
|
|
109
|
+
function clearSlideTimer() {
|
|
110
|
+
if (slideTimer !== null) {
|
|
111
|
+
clearTimeout(slideTimer);
|
|
112
|
+
slideTimer = null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function pictureKey(ref) {
|
|
116
|
+
return `${ref.mediaFileId}\u0000${ref.version}`;
|
|
117
|
+
}
|
|
118
|
+
function pictureOf(slide) {
|
|
119
|
+
const { body } = slide;
|
|
120
|
+
if (body.kind === "news") {
|
|
121
|
+
return body.picture;
|
|
122
|
+
}
|
|
123
|
+
return body.kind === "picture" ? body.picture : null;
|
|
124
|
+
}
|
|
125
|
+
function pictureUrl(ref) {
|
|
126
|
+
const entry = pictures.get(pictureKey(ref));
|
|
127
|
+
return entry?.state === "ready" ? entry.url : null;
|
|
128
|
+
}
|
|
129
|
+
function release(entry) {
|
|
130
|
+
if (entry.url !== null) {
|
|
131
|
+
options.releasePicture?.(entry.url, entry.ref);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function releaseAllPictures() {
|
|
135
|
+
for (const entry of pictures.values()) {
|
|
136
|
+
release(entry);
|
|
137
|
+
}
|
|
138
|
+
pictures.clear();
|
|
139
|
+
}
|
|
140
|
+
/** Asks for every picture the document refers to, and lets go of the rest. */
|
|
141
|
+
function syncPictures(next, now) {
|
|
142
|
+
const wanted = new Map();
|
|
143
|
+
for (const slide of next.rotation) {
|
|
144
|
+
const ref = pictureOf(slide);
|
|
145
|
+
if (ref !== null) {
|
|
146
|
+
wanted.set(pictureKey(ref), ref);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (const [key, entry] of pictures) {
|
|
150
|
+
if (!wanted.has(key)) {
|
|
151
|
+
release(entry);
|
|
152
|
+
pictures.delete(key);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
for (const [key, ref] of wanted) {
|
|
156
|
+
const entry = pictures.get(key);
|
|
157
|
+
if (entry === undefined ||
|
|
158
|
+
(entry.state === "failed" && now - entry.askedAt >= PICTURE_RETRY)) {
|
|
159
|
+
ask(key, ref, now);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function ask(key, ref, now) {
|
|
164
|
+
const entry = {
|
|
165
|
+
ref,
|
|
166
|
+
state: options.picture === undefined ? "failed" : "pending",
|
|
167
|
+
url: null,
|
|
168
|
+
askedAt: now,
|
|
169
|
+
};
|
|
170
|
+
pictures.set(key, entry);
|
|
171
|
+
if (options.picture === undefined) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
let request;
|
|
175
|
+
try {
|
|
176
|
+
request = options.picture(ref);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
entry.state = "failed";
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
request.then((url) => settle(key, entry, url), () => settle(key, entry, null));
|
|
183
|
+
}
|
|
184
|
+
function settle(key, entry, url) {
|
|
185
|
+
if (destroyed || pictures.get(key) !== entry) {
|
|
186
|
+
// Nobody wants it any more: hand it straight back.
|
|
187
|
+
if (url !== null) {
|
|
188
|
+
options.releasePicture?.(url, entry.ref);
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
entry.state = url === null ? "failed" : "ready";
|
|
193
|
+
entry.url = url;
|
|
194
|
+
pictureChanged(key);
|
|
195
|
+
}
|
|
196
|
+
function pictureFailed(ref) {
|
|
197
|
+
const key = pictureKey(ref);
|
|
198
|
+
const entry = pictures.get(key);
|
|
199
|
+
if (entry === undefined || entry.state !== "ready") {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
release(entry);
|
|
203
|
+
entry.state = "failed";
|
|
204
|
+
entry.url = null;
|
|
205
|
+
pictureChanged(key);
|
|
206
|
+
}
|
|
207
|
+
/** A picture arrived or went: redraw the slide that shows it, or start the rotation it unblocks. */
|
|
208
|
+
function pictureChanged(key) {
|
|
209
|
+
if (content === null) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (current === null) {
|
|
213
|
+
startRotation();
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const slide = content.rotation[current.index];
|
|
217
|
+
const ref = slide === undefined ? null : pictureOf(slide);
|
|
218
|
+
if (slide !== undefined && ref !== null && pictureKey(ref) === key) {
|
|
219
|
+
if (slide.body.kind === "picture" && pictureUrl(ref) === null) {
|
|
220
|
+
advance();
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
draw(slide, current.index, false, clockNow(), current.endsAt, current.page);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function showable(slide, now) {
|
|
228
|
+
if (slide.until !== null && now >= Date.parse(slide.until)) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
if (slide.body.kind === "picture") {
|
|
232
|
+
return pictureUrl(slide.body.picture) !== null;
|
|
233
|
+
}
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
/** What a slide looks like now: redrawn only when this changes. */
|
|
237
|
+
function slideKey(slide, shown, now) {
|
|
238
|
+
const ref = pictureOf(slide);
|
|
239
|
+
return JSON.stringify([
|
|
240
|
+
slide,
|
|
241
|
+
shown.locale,
|
|
242
|
+
shown.timeZone,
|
|
243
|
+
ref === null ? null : pictureUrl(ref),
|
|
244
|
+
// Free and busy reads the clock: what has passed drops off each minute.
|
|
245
|
+
slide.body.kind === "availability" ? Math.floor(now / MINUTE) : null,
|
|
246
|
+
// The date on a news slide and the days of events are the zone's.
|
|
247
|
+
zonedDayStartAfter(now, 0, shown.timeZone),
|
|
248
|
+
]);
|
|
249
|
+
}
|
|
250
|
+
/** Draws page `page` of a slide, or keeps it when it is already on screen. */
|
|
251
|
+
function draw(slide, index, enter, now, endsAt, page = 0) {
|
|
252
|
+
if (content === null) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const key = slideKey(slide, content, now);
|
|
256
|
+
let fit = { page, pages: current?.pages ?? 1 };
|
|
257
|
+
if (current === null ||
|
|
258
|
+
current.id !== slide.id ||
|
|
259
|
+
current.key !== key ||
|
|
260
|
+
current.page !== page) {
|
|
261
|
+
const context = {
|
|
262
|
+
document,
|
|
263
|
+
locale: content.locale,
|
|
264
|
+
timeZone: content.timeZone,
|
|
265
|
+
now,
|
|
266
|
+
pictureUrl,
|
|
267
|
+
pictureFailed,
|
|
268
|
+
};
|
|
269
|
+
const node = renderSlide(slide, context);
|
|
270
|
+
if (node === null) {
|
|
271
|
+
current = null;
|
|
272
|
+
advance();
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
replaceContent(stage, node);
|
|
276
|
+
const fitted = fitSlide(node, unit, page);
|
|
277
|
+
if (enter) {
|
|
278
|
+
node.classList.add("obrf-display-slide--enter");
|
|
279
|
+
}
|
|
280
|
+
fit = { page: fitted.page, pages: fitted.pages };
|
|
281
|
+
}
|
|
282
|
+
current = { index, id: slide.id, key, endsAt, ...fit };
|
|
283
|
+
clearSlideTimer();
|
|
284
|
+
const until = slide.until === null ? Infinity : Date.parse(slide.until);
|
|
285
|
+
slideTimer = setTimeout(advance, Math.max(0, Math.min(endsAt, until) - now));
|
|
286
|
+
}
|
|
287
|
+
/** Shows the first slide that can be shown at or after `from`, looping. */
|
|
288
|
+
function showFrom(from, enter) {
|
|
289
|
+
if (content === null) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const now = clockNow();
|
|
293
|
+
const { rotation } = content;
|
|
294
|
+
for (let step = 0; step < rotation.length; step += 1) {
|
|
295
|
+
const index = (from + step) % rotation.length;
|
|
296
|
+
const slide = rotation[index];
|
|
297
|
+
if (slide !== undefined && showable(slide, now)) {
|
|
298
|
+
// The slide on screen goes on, unless it comes back to its first page.
|
|
299
|
+
const continuing = current !== null && current.id === slide.id && current.page === 0;
|
|
300
|
+
draw(slide, index, enter && !continuing, now, now + slide.seconds * 1000);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// Nothing to show now: said quietly, so a screen just opened on a link
|
|
305
|
+
// does not look broken. The minute tick and an arriving picture try again.
|
|
306
|
+
clearSlideTimer();
|
|
307
|
+
current = null;
|
|
308
|
+
replaceContent(stage, make("p", "obrf-display-empty", translate(content.locale, "nothingToShow")));
|
|
309
|
+
}
|
|
310
|
+
function startRotation() {
|
|
311
|
+
showFrom(0, true);
|
|
312
|
+
}
|
|
313
|
+
/** The slide's next page, or the next slide after its last. */
|
|
314
|
+
function advance() {
|
|
315
|
+
slideTimer = null;
|
|
316
|
+
const slide = current === null || content === null
|
|
317
|
+
? undefined
|
|
318
|
+
: content.rotation[current.index];
|
|
319
|
+
const now = clockNow();
|
|
320
|
+
if (current !== null &&
|
|
321
|
+
slide !== undefined &&
|
|
322
|
+
current.page + 1 < current.pages &&
|
|
323
|
+
showable(slide, now)) {
|
|
324
|
+
draw(slide, current.index, true, now, now + slide.seconds * 1000, current.page + 1);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
showFrom(current === null ? 0 : current.index + 1, true);
|
|
328
|
+
}
|
|
329
|
+
function updateClock(now) {
|
|
330
|
+
if (content === null || content.layout.header !== "clock") {
|
|
331
|
+
clock.hidden = true;
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
clock.hidden = false;
|
|
335
|
+
clockDate.textContent = capitalised(formatTime(now, content.locale, content.timeZone, "weekdayDate"));
|
|
336
|
+
clockTime.textContent = formatTime(now, content.locale, content.timeZone, "time");
|
|
337
|
+
}
|
|
338
|
+
function updateNote(now) {
|
|
339
|
+
if (content === null || status === null || !status.stale) {
|
|
340
|
+
note.hidden = true;
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const fetchedAt = status.fetchedAt.getTime();
|
|
344
|
+
const { locale, timeZone } = content;
|
|
345
|
+
const sameDay = zonedDayStartAfter(fetchedAt, 0, timeZone) ===
|
|
346
|
+
zonedDayStartAfter(now, 0, timeZone);
|
|
347
|
+
const time = formatTime(fetchedAt, locale, timeZone, "time");
|
|
348
|
+
// The date and time in the data face, the words around them not.
|
|
349
|
+
const [before = "", after = ""] = translate(locale, "lastUpdated", {
|
|
350
|
+
time: "\u0000",
|
|
351
|
+
}).split("\u0000");
|
|
352
|
+
replaceContent(note, before, make("span", "obrf-display-data", sameDay
|
|
353
|
+
? time
|
|
354
|
+
: `${formatTime(fetchedAt, locale, timeZone, "date")} ${time}`), after);
|
|
355
|
+
note.hidden = false;
|
|
356
|
+
}
|
|
357
|
+
function updateSchedule(now) {
|
|
358
|
+
off.hidden =
|
|
359
|
+
content === null ||
|
|
360
|
+
inSchedule(content.schedule.on, now, content.timeZone);
|
|
361
|
+
}
|
|
362
|
+
/** Each minute: the clock, the schedule, the note, and a rotation that had nothing to show. */
|
|
363
|
+
function tick() {
|
|
364
|
+
minuteTimer = null;
|
|
365
|
+
if (destroyed) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const now = clockNow();
|
|
369
|
+
updateClock(now);
|
|
370
|
+
updateSchedule(now);
|
|
371
|
+
updateNote(now);
|
|
372
|
+
if (content !== null) {
|
|
373
|
+
if (current === null) {
|
|
374
|
+
startRotation();
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
const slide = content.rotation[current.index];
|
|
378
|
+
if (slide !== undefined &&
|
|
379
|
+
slideKey(slide, content, now) !== current.key) {
|
|
380
|
+
draw(slide, current.index, false, now, current.endsAt, current.page);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
scheduleTick(clockNow());
|
|
385
|
+
}
|
|
386
|
+
function scheduleTick(now) {
|
|
387
|
+
if (minuteTimer !== null) {
|
|
388
|
+
clearTimeout(minuteTimer);
|
|
389
|
+
}
|
|
390
|
+
minuteTimer = setTimeout(tick, MINUTE - (now % MINUTE));
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
show(next, nextStatus) {
|
|
394
|
+
if (destroyed) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const now = clockNow();
|
|
398
|
+
const previous = current;
|
|
399
|
+
content = next;
|
|
400
|
+
status = nextStatus ?? null;
|
|
401
|
+
root.lang = next.locale;
|
|
402
|
+
setTheme(next.layout.theme);
|
|
403
|
+
layout();
|
|
404
|
+
syncPictures(next, now);
|
|
405
|
+
updateClock(now);
|
|
406
|
+
updateSchedule(now);
|
|
407
|
+
updateNote(now);
|
|
408
|
+
const kept = previous === null
|
|
409
|
+
? -1
|
|
410
|
+
: next.rotation.findIndex((slide) => slide.id === previous.id);
|
|
411
|
+
const keptSlide = kept === -1 ? undefined : next.rotation[kept];
|
|
412
|
+
if (previous !== null &&
|
|
413
|
+
keptSlide !== undefined &&
|
|
414
|
+
showable(keptSlide, now)) {
|
|
415
|
+
draw(keptSlide, kept, false, now, previous.endsAt, previous.page);
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
current = null;
|
|
419
|
+
clearSlideTimer();
|
|
420
|
+
startRotation();
|
|
421
|
+
}
|
|
422
|
+
scheduleTick(now);
|
|
423
|
+
},
|
|
424
|
+
message(kind, locale) {
|
|
425
|
+
if (destroyed) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
content = null;
|
|
429
|
+
status = null;
|
|
430
|
+
current = null;
|
|
431
|
+
clearSlideTimer();
|
|
432
|
+
releaseAllPictures();
|
|
433
|
+
root.lang = locale;
|
|
434
|
+
clock.hidden = true;
|
|
435
|
+
note.hidden = true;
|
|
436
|
+
off.hidden = true;
|
|
437
|
+
layout();
|
|
438
|
+
const words = MESSAGES[kind];
|
|
439
|
+
const box = make("div", "obrf-display-message");
|
|
440
|
+
box.setAttribute("role", "status");
|
|
441
|
+
box.append(make("p", "obrf-display-message-title", translate(locale, words.title)));
|
|
442
|
+
if (words.detail !== null) {
|
|
443
|
+
box.append(make("p", "obrf-display-message-detail", translate(locale, words.detail)));
|
|
444
|
+
}
|
|
445
|
+
replaceContent(stage, box);
|
|
446
|
+
},
|
|
447
|
+
destroy() {
|
|
448
|
+
if (destroyed) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
destroyed = true;
|
|
452
|
+
clearSlideTimer();
|
|
453
|
+
if (minuteTimer !== null) {
|
|
454
|
+
clearTimeout(minuteTimer);
|
|
455
|
+
minuteTimer = null;
|
|
456
|
+
}
|
|
457
|
+
resizeObserver?.disconnect();
|
|
458
|
+
view?.removeEventListener("resize", layout);
|
|
459
|
+
fonts?.removeEventListener("loadingdone", refit);
|
|
460
|
+
releaseAllPictures();
|
|
461
|
+
content = null;
|
|
462
|
+
current = null;
|
|
463
|
+
replaceContent(element);
|
|
464
|
+
},
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
function addStylesheet(document) {
|
|
468
|
+
if (document.head.querySelector(`style[${STYLE_ATTRIBUTE}], link[${STYLE_ATTRIBUTE}]`) !== null) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const style = document.createElement("style");
|
|
472
|
+
style.setAttribute(STYLE_ATTRIBUTE, "");
|
|
473
|
+
style.textContent = DISPLAY_STYLESHEET;
|
|
474
|
+
document.head.append(style);
|
|
475
|
+
}
|
|
476
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
|