cursedbelt 4.1.0 → 4.3.0
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/dist/react/master-lock/MasterLockDialog.d.ts.map +1 -1
- package/dist/react/master-lock/MasterLockDialog.js +25 -5
- package/dist/react/master-lock/MasterLockDialog.js.map +1 -1
- package/dist/react/master-lock/MasterLockProvider.d.ts +19 -0
- package/dist/react/master-lock/MasterLockProvider.d.ts.map +1 -1
- package/dist/react/master-lock/MasterLockProvider.js +19 -0
- package/dist/react/master-lock/MasterLockProvider.js.map +1 -1
- package/dist/react/media/CanvasVideoPlayer.d.ts +3 -2
- package/dist/react/media/CanvasVideoPlayer.d.ts.map +1 -1
- package/dist/react/media/CanvasVideoPlayer.js +4 -3
- package/dist/react/media/CanvasVideoPlayer.js.map +1 -1
- package/dist/react/media/FrameGrabber.d.ts +16 -2
- package/dist/react/media/FrameGrabber.d.ts.map +1 -1
- package/dist/react/media/FrameGrabber.js +68 -43
- package/dist/react/media/FrameGrabber.js.map +1 -1
- package/dist/react/media/PictureEditor.d.ts +17 -2
- package/dist/react/media/PictureEditor.d.ts.map +1 -1
- package/dist/react/media/PictureEditor.js +33 -7
- package/dist/react/media/PictureEditor.js.map +1 -1
- package/dist/react/media/VideoChapterEditor.d.ts +17 -2
- package/dist/react/media/VideoChapterEditor.d.ts.map +1 -1
- package/dist/react/media/VideoChapterEditor.js +21 -3
- package/dist/react/media/VideoChapterEditor.js.map +1 -1
- package/dist/react/media/VideoCutEditor.d.ts +16 -2
- package/dist/react/media/VideoCutEditor.d.ts.map +1 -1
- package/dist/react/media/VideoCutEditor.js +21 -3
- package/dist/react/media/VideoCutEditor.js.map +1 -1
- package/dist/react/media/VideoPlayer.d.ts +37 -9
- package/dist/react/media/VideoPlayer.d.ts.map +1 -1
- package/dist/react/media/VideoPlayer.js +130 -39
- package/dist/react/media/VideoPlayer.js.map +1 -1
- package/dist/react/media/hlsSource.d.ts +24 -3
- package/dist/react/media/hlsSource.d.ts.map +1 -1
- package/dist/react/media/hlsSource.js +109 -8
- package/dist/react/media/hlsSource.js.map +1 -1
- package/dist/react/media/pictureEditor.css +2 -0
- package/dist/react/media/sourceFault.d.ts +146 -0
- package/dist/react/media/sourceFault.d.ts.map +1 -0
- package/dist/react/media/sourceFault.js +139 -0
- package/dist/react/media/sourceFault.js.map +1 -0
- package/dist/react/media/videoChapterEditor.css +19 -0
- package/dist/react/media/videoCutEditor.css +22 -0
- package/dist/react/media-gallery/MediaGallery.d.ts +12 -1
- package/dist/react/media-gallery/MediaGallery.d.ts.map +1 -1
- package/dist/react/media-gallery/MediaGallery.js +166 -13
- package/dist/react/media-gallery/MediaGallery.js.map +1 -1
- package/dist/react/media-gallery/galleryItemMedia.d.ts +4 -0
- package/dist/react/media-gallery/galleryItemMedia.d.ts.map +1 -1
- package/dist/react/media-gallery/galleryItemMedia.js +27 -3
- package/dist/react/media-gallery/galleryItemMedia.js.map +1 -1
- package/dist/react/media-gallery/mediaGalleryModel.d.ts.map +1 -1
- package/dist/react/media-gallery/mediaGalleryModel.js +5 -0
- package/dist/react/media-gallery/mediaGalleryModel.js.map +1 -1
- package/dist/react/media-gallery/types.d.ts +23 -0
- package/dist/react/media-gallery/types.d.ts.map +1 -1
- package/dist/scripts/guardrailsEnforce.d.ts +1 -0
- package/dist/scripts/guardrailsEnforce.d.ts.map +1 -1
- package/dist/styles-areas/master-lock.css +1 -1
- package/dist/styles-areas/media-gallery.css +1 -1
- package/dist/styles-areas/media.css +1 -1
- package/package.json +3 -2
- package/scripts/guardrailsEnforce.spec.ts +244 -1
- package/scripts/guardrailsEnforce.ts +224 -7
- package/src/iframesMakeNoRealRequest.spec.ts +92 -0
- package/src/react/components/IsolatedFrame.spec.tsx +27 -9
- package/src/react/master-lock/MasterLockDialog.tsx +24 -5
- package/src/react/master-lock/MasterLockProvider.spec.tsx +39 -0
- package/src/react/master-lock/MasterLockProvider.tsx +19 -0
- package/src/react/media/CanvasVideoPlayer.tsx +11 -6
- package/src/react/media/FrameGrabber.spec.tsx +57 -1
- package/src/react/media/FrameGrabber.tsx +138 -84
- package/src/react/media/PictureEditor.spec.tsx +90 -0
- package/src/react/media/PictureEditor.tsx +78 -23
- package/src/react/media/VideoChapterEditor.spec.tsx +86 -0
- package/src/react/media/VideoChapterEditor.tsx +64 -18
- package/src/react/media/VideoCutEditor.spec.tsx +44 -0
- package/src/react/media/VideoCutEditor.tsx +63 -18
- package/src/react/media/VideoPlayer.spec.tsx +101 -0
- package/src/react/media/VideoPlayer.tsx +221 -73
- package/src/react/media/hlsSource.answer.spec.ts +255 -0
- package/src/react/media/hlsSource.ts +136 -8
- package/src/react/media/pictureEditor.css +2 -0
- package/src/react/media/sourceFault.spec.tsx +224 -0
- package/src/react/media/sourceFault.tsx +220 -0
- package/src/react/media/videoChapterEditor.css +19 -0
- package/src/react/media/videoCutEditor.css +22 -0
- package/src/react/media-gallery/MediaGallery.spec.tsx +288 -0
- package/src/react/media-gallery/MediaGallery.tsx +356 -45
- package/src/react/media-gallery/galleryItemMedia.tsx +27 -4
- package/src/react/media-gallery/mediaGalleryModel.spec.ts +36 -0
- package/src/react/media-gallery/mediaGalleryModel.ts +4 -0
- package/src/react/media-gallery/types.ts +23 -0
- package/src/styles-areas/master-lock.css +1 -1
- package/src/styles-areas/media-gallery.css +1 -1
- package/src/styles-areas/media.css +1 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a media URL ANSWERED, when what it answered was not the bytes.
|
|
3
|
+
*
|
|
4
|
+
* ── 🔴 The report this exists for ───────────────────────────────────────────────────────
|
|
5
|
+
* Owner, 2026-09-17: *"make a 404 stop the media player spinner so I don't think it's going
|
|
6
|
+
* to eventually load."* One item in his catalogue has no ladder, so the very first request a
|
|
7
|
+
* player makes is answered honestly and immediately:
|
|
8
|
+
*
|
|
9
|
+
* GET …/u_fd668e6a….hls/master.m3u8 → 404 {"error":"not_found"} in 0.2 s
|
|
10
|
+
*
|
|
11
|
+
* and the spinner then ran until he gave up. **A 404 is a COMPLETE ANSWER** — there is
|
|
12
|
+
* nothing still in flight, nothing to wait for, and no amount of waiting changes it — and it
|
|
13
|
+
* was the one status every surface here treated as "still loading".
|
|
14
|
+
*
|
|
15
|
+
* ── 🔴 The distinction this module is entirely about ────────────────────────────────────
|
|
16
|
+
* A hang and an answer must not look the same to somebody watching a spinner:
|
|
17
|
+
*
|
|
18
|
+
* | what happened | is it an answer? | what the viewer should see |
|
|
19
|
+
* |---|---|---|
|
|
20
|
+
* | slow segment, tunnel blinked, origin waking | no — still in flight | keep spinning |
|
|
21
|
+
* | `404` / `410` | yes, and it is final | the reason, now |
|
|
22
|
+
* | `401` / `403` | yes, and it is RECOVERABLE | re-ask the app, then the reason |
|
|
23
|
+
* | any other `4xx`/`5xx` | yes, and we cannot name it | the reason, now |
|
|
24
|
+
*
|
|
25
|
+
* `403` is split out because it is the one that comes back on its own: every signed URL in
|
|
26
|
+
* this fleet carries `exp = iat + 2 × window`, so a page left open across a window boundary
|
|
27
|
+
* meets a stale token legitimately and the fix is to ASK THE APP AGAIN, not to tell the
|
|
28
|
+
* viewer his film is gone. Collapsing it into "gone" would put a false and permanent-sounding
|
|
29
|
+
* sentence on screen for the one fault that clears itself.
|
|
30
|
+
*
|
|
31
|
+
* ── 🔴 Why a probe, and why only on the failure path ────────────────────────────────────
|
|
32
|
+
* `hls.js` hands us the status directly (`ErrorData.response.code`), so the ladder and its
|
|
33
|
+
* rungs cost nothing. An `<img>` and a `<video>` do NOT: both fire a bare `error` event that
|
|
34
|
+
* carries no status at all, so "the file is gone" and "the token went stale" and "the codec
|
|
35
|
+
* is unplayable" arrive as the same undifferentiated failure. {@link probeSourceFault} is the
|
|
36
|
+
* one way to tell them apart, and it runs ONLY after the element has already given up — so a
|
|
37
|
+
* gallery that is working costs exactly nothing, and a one-byte `Range` request is the whole
|
|
38
|
+
* price of a sentence that is true.
|
|
39
|
+
*
|
|
40
|
+
* (`bytes=0-0` is a CORS-safelisted range, so the probe is a simple request and never costs a
|
|
41
|
+
* preflight; the 404 in the report above answers `access-control-allow-origin: *`, which is
|
|
42
|
+
* what makes the status readable cross-origin at all. When it is not readable the fetch
|
|
43
|
+
* throws, and that is `unknown` — honest, still not a spinner.)
|
|
44
|
+
*
|
|
45
|
+
* ── 🔴 Why one module holds the reading, the wording AND the overlay ────────────────────
|
|
46
|
+
* Three surfaces have to agree about the same fault — the gallery's picture stage, its native
|
|
47
|
+
* video stage and the shared player — and the thing they must agree on is not the mechanism,
|
|
48
|
+
* it is the SENTENCE. Split across three files this becomes three wordings, and the owner
|
|
49
|
+
* meets whichever one his file happens to be behind.
|
|
50
|
+
*
|
|
51
|
+
* It is deliberately NOT a published subpath and nothing here is re-exported from
|
|
52
|
+
* `react/media/index.ts`. `publicSurface.baseline` charges for a permanent promise, and none
|
|
53
|
+
* of this is one: the wording is copy, the overlay is chrome, and a consumer that wanted to
|
|
54
|
+
* draw its own would be re-implementing the corner rather than importing it. (Same call the
|
|
55
|
+
* badge stack in `VideoPlayer.tsx` made — see that baseline entry's "what did NOT go on the
|
|
56
|
+
* surface".) A `.tsx` holding a component beside its helpers is `galleryItemMedia.tsx`'s
|
|
57
|
+
* shape, for the same reason.
|
|
58
|
+
*/
|
|
59
|
+
/** Which of the three answers came back. `expired` is the only one worth re-asking. */
|
|
60
|
+
export type SourceFaultKind =
|
|
61
|
+
/** The source said there is nothing here — `404`/`410`. Final. */
|
|
62
|
+
'gone'
|
|
63
|
+
/** The token went stale — `401`/`403`. A fresh URL from the app fixes it. */
|
|
64
|
+
| 'expired'
|
|
65
|
+
/** It answered something else, or did not answer readably. Not a hang either way. */
|
|
66
|
+
| 'unknown';
|
|
67
|
+
export interface SourceFault {
|
|
68
|
+
kind: SourceFaultKind;
|
|
69
|
+
/** The HTTP status that said so, when one was readable. Absent for an unreadable failure. */
|
|
70
|
+
status?: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Classify one HTTP status. `null` for anything below 400 — a source that answered `200` and
|
|
74
|
+
* still would not play is not a fault of the URL, and saying otherwise would blame the store
|
|
75
|
+
* for an unplayable codec.
|
|
76
|
+
*/
|
|
77
|
+
export declare function sourceFaultFromStatus(status: number): SourceFault | null;
|
|
78
|
+
/**
|
|
79
|
+
* Is this worth asking the app for a fresh URL? Exactly one kind is.
|
|
80
|
+
*
|
|
81
|
+
* 🔴 A caller that re-asks must BOUND it — see `useItemMedia`'s one-re-ask-per-item rule. An
|
|
82
|
+
* unbounded retry against a URL that is never going to be fresh is the same spinner with more
|
|
83
|
+
* requests in it, which is the thing this whole module exists to stop.
|
|
84
|
+
*/
|
|
85
|
+
export declare function isRecoverableFault(fault: SourceFault): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Ask the URL what it is, once, with a one-byte range.
|
|
88
|
+
*
|
|
89
|
+
* Only ever called after an element has already failed, so this is never on the happy path.
|
|
90
|
+
* Never throws: an unreadable failure (offline, CORS, DNS) resolves `unknown` rather than
|
|
91
|
+
* rejecting, because the caller's job at that point is to say SOMETHING instead of spinning.
|
|
92
|
+
*
|
|
93
|
+
* Reads `globalThis.fetch` at call time rather than closing over it, so a spec can install its
|
|
94
|
+
* own and the unit suite never puts a request on a real socket
|
|
95
|
+
* (`src/iframesMakeNoRealRequest.spec.ts` is the standing rule).
|
|
96
|
+
*/
|
|
97
|
+
export declare function probeSourceFault(url: string | undefined): Promise<SourceFault>;
|
|
98
|
+
/**
|
|
99
|
+
* The sentence a viewer reads.
|
|
100
|
+
*
|
|
101
|
+
* 🔴 One place, because the gallery's picture stage, its native video stage and the shared
|
|
102
|
+
* player all have to say the SAME thing about the same fault — three copies of this is three
|
|
103
|
+
* wordings, and the owner would meet whichever one his file happened to be behind. The specs
|
|
104
|
+
* spell the sentences out as literals rather than importing them, for the reason the badge
|
|
105
|
+
* copy in `VideoPlayer.tsx` gives: which words are on the picture IS the deliverable, so an
|
|
106
|
+
* assertion that reads the function asserts nothing.
|
|
107
|
+
*
|
|
108
|
+
* `subject` is the noun for the thing that failed — "This video", "This picture", the file's
|
|
109
|
+
* own name. It leads the sentence, so it is capitalised by the caller.
|
|
110
|
+
*/
|
|
111
|
+
export declare function sourceFaultMessage(fault: SourceFault, subject: string): string;
|
|
112
|
+
/**
|
|
113
|
+
* Did an `hls.js` error carry an ANSWER, or is the ladder still coming?
|
|
114
|
+
*
|
|
115
|
+
* 🔴 The whole of the owner's report is in this predicate. hls.js sets `response.code` only
|
|
116
|
+
* when the server actually replied — a timeout, an abort and a stalled fetch carry none — so a
|
|
117
|
+
* status here means the ladder is not on its way and never was, and the copy that always
|
|
118
|
+
* exists should take over NOW rather than after four retries and twelve seconds of backoff. A
|
|
119
|
+
* fatal error with no status is the case those retries exist for and must keep them.
|
|
120
|
+
*
|
|
121
|
+
* `unknown` rather than hls.js's `ErrorData`: the library is an OPTIONAL peer and a ~525 KB
|
|
122
|
+
* dynamic import in exactly one branch, so its types must not become a static dependency of
|
|
123
|
+
* every file that reads one of its payloads.
|
|
124
|
+
*/
|
|
125
|
+
export declare function hlsErrorIsAnswer(detail: unknown): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* What a video surface says once every source has ANSWERED.
|
|
128
|
+
*
|
|
129
|
+
* ── 🔴 Why it covers the picture instead of sitting beside it ───────────────────────────
|
|
130
|
+
* The thing being replaced is a buffering spinner drawn by Vidstack's own layout, which
|
|
131
|
+
* cannot be turned off from outside it — so a sentence in the corner would be a sentence NEXT
|
|
132
|
+
* TO a spinner, which is the owner's report ("I don't think it's going to eventually load")
|
|
133
|
+
* with extra words rather than without it. Opaque, `inset: 0`, over the whole surface: the
|
|
134
|
+
* spinner is gone because it is not visible, and that is the only lever there is.
|
|
135
|
+
*
|
|
136
|
+
* 🔴 The player is NOT unmounted by it. A `403` is recoverable and the app's fix is a fresh
|
|
137
|
+
* URL, which arrives as new props on the same mount; tearing the player down would throw away
|
|
138
|
+
* the position, the volume and the decoder to say one sentence that may be obsolete a second
|
|
139
|
+
* later. The gallery's stages do the opposite and REPLACE their element — there the `<video>`
|
|
140
|
+
* is the spinner, so nothing short of removing it would do.
|
|
141
|
+
*/
|
|
142
|
+
export declare function SourceFaultOverlay({ fault, name }: {
|
|
143
|
+
fault: SourceFault;
|
|
144
|
+
name: string;
|
|
145
|
+
}): import("react").JSX.Element;
|
|
146
|
+
//# sourceMappingURL=sourceFault.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sourceFault.d.ts","sourceRoot":"","sources":["../../../src/react/media/sourceFault.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH,uFAAuF;AACvF,MAAM,MAAM,eAAe;AACzB,kEAAkE;AAChE,MAAM;AACR,6EAA6E;GAC3E,SAAS;AACX,qFAAqF;GACnF,SAAS,CAAC;AAEd,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,eAAe,CAAC;IACtB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAKxE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAqBpF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAS9E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAKzD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,+BA4BvF"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Classify one HTTP status. `null` for anything below 400 — a source that answered `200` and
|
|
4
|
+
* still would not play is not a fault of the URL, and saying otherwise would blame the store
|
|
5
|
+
* for an unplayable codec.
|
|
6
|
+
*/
|
|
7
|
+
export function sourceFaultFromStatus(status) {
|
|
8
|
+
if (status === 404 || status === 410)
|
|
9
|
+
return { kind: 'gone', status };
|
|
10
|
+
if (status === 401 || status === 403)
|
|
11
|
+
return { kind: 'expired', status };
|
|
12
|
+
if (status >= 400)
|
|
13
|
+
return { kind: 'unknown', status };
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Is this worth asking the app for a fresh URL? Exactly one kind is.
|
|
18
|
+
*
|
|
19
|
+
* 🔴 A caller that re-asks must BOUND it — see `useItemMedia`'s one-re-ask-per-item rule. An
|
|
20
|
+
* unbounded retry against a URL that is never going to be fresh is the same spinner with more
|
|
21
|
+
* requests in it, which is the thing this whole module exists to stop.
|
|
22
|
+
*/
|
|
23
|
+
export function isRecoverableFault(fault) {
|
|
24
|
+
return fault.kind === 'expired';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Ask the URL what it is, once, with a one-byte range.
|
|
28
|
+
*
|
|
29
|
+
* Only ever called after an element has already failed, so this is never on the happy path.
|
|
30
|
+
* Never throws: an unreadable failure (offline, CORS, DNS) resolves `unknown` rather than
|
|
31
|
+
* rejecting, because the caller's job at that point is to say SOMETHING instead of spinning.
|
|
32
|
+
*
|
|
33
|
+
* Reads `globalThis.fetch` at call time rather than closing over it, so a spec can install its
|
|
34
|
+
* own and the unit suite never puts a request on a real socket
|
|
35
|
+
* (`src/iframesMakeNoRealRequest.spec.ts` is the standing rule).
|
|
36
|
+
*/
|
|
37
|
+
export async function probeSourceFault(url) {
|
|
38
|
+
const fetchImpl = globalThis.fetch;
|
|
39
|
+
if (!url || typeof fetchImpl !== 'function')
|
|
40
|
+
return { kind: 'unknown' };
|
|
41
|
+
try {
|
|
42
|
+
const res = await fetchImpl(url, {
|
|
43
|
+
method: 'GET',
|
|
44
|
+
// One byte. The status is the whole point; the body is not wanted and a media file is
|
|
45
|
+
// the last thing to download twice.
|
|
46
|
+
headers: { Range: 'bytes=0-0' },
|
|
47
|
+
cache: 'no-store',
|
|
48
|
+
});
|
|
49
|
+
// 🔴 A status BELOW 400 is deliberately dropped rather than reported: the URL is fine and
|
|
50
|
+
// the bytes are there, so the element failed for a reason that is not the store's — an
|
|
51
|
+
// unplayable codec, a decode stall. Printing "could not be loaded (HTTP 200)" would blame
|
|
52
|
+
// the wrong thing in the one case where the file is not actually missing.
|
|
53
|
+
return sourceFaultFromStatus(res.status) ?? { kind: 'unknown' };
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// No readable answer at all. Still not a hang — the element already stopped — so the
|
|
57
|
+
// caller states what it can rather than leaving the spinner up.
|
|
58
|
+
return { kind: 'unknown' };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The sentence a viewer reads.
|
|
63
|
+
*
|
|
64
|
+
* 🔴 One place, because the gallery's picture stage, its native video stage and the shared
|
|
65
|
+
* player all have to say the SAME thing about the same fault — three copies of this is three
|
|
66
|
+
* wordings, and the owner would meet whichever one his file happened to be behind. The specs
|
|
67
|
+
* spell the sentences out as literals rather than importing them, for the reason the badge
|
|
68
|
+
* copy in `VideoPlayer.tsx` gives: which words are on the picture IS the deliverable, so an
|
|
69
|
+
* assertion that reads the function asserts nothing.
|
|
70
|
+
*
|
|
71
|
+
* `subject` is the noun for the thing that failed — "This video", "This picture", the file's
|
|
72
|
+
* own name. It leads the sentence, so it is capitalised by the caller.
|
|
73
|
+
*/
|
|
74
|
+
export function sourceFaultMessage(fault, subject) {
|
|
75
|
+
const status = fault.status != null ? ` (HTTP ${fault.status})` : '';
|
|
76
|
+
if (fault.kind === 'gone') {
|
|
77
|
+
return `${subject} is no longer on the media store${status} — nothing is still loading.`;
|
|
78
|
+
}
|
|
79
|
+
if (fault.kind === 'expired') {
|
|
80
|
+
return `${subject}'s link has expired${status} — reopen it for a fresh one.`;
|
|
81
|
+
}
|
|
82
|
+
return `${subject} could not be loaded${status} — nothing is still loading.`;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Did an `hls.js` error carry an ANSWER, or is the ladder still coming?
|
|
86
|
+
*
|
|
87
|
+
* 🔴 The whole of the owner's report is in this predicate. hls.js sets `response.code` only
|
|
88
|
+
* when the server actually replied — a timeout, an abort and a stalled fetch carry none — so a
|
|
89
|
+
* status here means the ladder is not on its way and never was, and the copy that always
|
|
90
|
+
* exists should take over NOW rather than after four retries and twelve seconds of backoff. A
|
|
91
|
+
* fatal error with no status is the case those retries exist for and must keep them.
|
|
92
|
+
*
|
|
93
|
+
* `unknown` rather than hls.js's `ErrorData`: the library is an OPTIONAL peer and a ~525 KB
|
|
94
|
+
* dynamic import in exactly one branch, so its types must not become a static dependency of
|
|
95
|
+
* every file that reads one of its payloads.
|
|
96
|
+
*/
|
|
97
|
+
export function hlsErrorIsAnswer(detail) {
|
|
98
|
+
const data = detail;
|
|
99
|
+
const code = data?.response?.code;
|
|
100
|
+
if (!data?.fatal || typeof code !== 'number')
|
|
101
|
+
return false;
|
|
102
|
+
return sourceFaultFromStatus(code) !== null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* What a video surface says once every source has ANSWERED.
|
|
106
|
+
*
|
|
107
|
+
* ── 🔴 Why it covers the picture instead of sitting beside it ───────────────────────────
|
|
108
|
+
* The thing being replaced is a buffering spinner drawn by Vidstack's own layout, which
|
|
109
|
+
* cannot be turned off from outside it — so a sentence in the corner would be a sentence NEXT
|
|
110
|
+
* TO a spinner, which is the owner's report ("I don't think it's going to eventually load")
|
|
111
|
+
* with extra words rather than without it. Opaque, `inset: 0`, over the whole surface: the
|
|
112
|
+
* spinner is gone because it is not visible, and that is the only lever there is.
|
|
113
|
+
*
|
|
114
|
+
* 🔴 The player is NOT unmounted by it. A `403` is recoverable and the app's fix is a fresh
|
|
115
|
+
* URL, which arrives as new props on the same mount; tearing the player down would throw away
|
|
116
|
+
* the position, the volume and the decoder to say one sentence that may be obsolete a second
|
|
117
|
+
* later. The gallery's stages do the opposite and REPLACE their element — there the `<video>`
|
|
118
|
+
* is the spinner, so nothing short of removing it would do.
|
|
119
|
+
*/
|
|
120
|
+
export function SourceFaultOverlay({ fault, name }) {
|
|
121
|
+
return (_jsxs("div", { role: 'status', style: {
|
|
122
|
+
position: 'absolute',
|
|
123
|
+
inset: 0,
|
|
124
|
+
display: 'flex',
|
|
125
|
+
flexDirection: 'column',
|
|
126
|
+
alignItems: 'center',
|
|
127
|
+
justifyContent: 'center',
|
|
128
|
+
gap: 6,
|
|
129
|
+
padding: 16,
|
|
130
|
+
textAlign: 'center',
|
|
131
|
+
// Over VIDEO content, not app chrome — dark-on-video regardless of app theme, the same
|
|
132
|
+
// convention the player's corner badges use and for the same reason.
|
|
133
|
+
// guardrails-ignore no-hardcoded-colors: see comment above.
|
|
134
|
+
background: 'rgba(0, 0, 0, 0.82)',
|
|
135
|
+
// guardrails-ignore no-hardcoded-colors: see comment above.
|
|
136
|
+
color: 'rgba(255, 255, 255, 0.92)',
|
|
137
|
+
}, children: [_jsx("span", { style: { fontSize: 13, fontWeight: 600 }, children: name }), _jsx("span", { style: { fontSize: 13, lineHeight: 1.5, maxWidth: '42ch' }, children: sourceFaultMessage(fault, 'This video') })] }));
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=sourceFault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sourceFault.js","sourceRoot":"","sources":["../../../src/react/media/sourceFault.tsx"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,25 @@
|
|
|
17
17
|
border-radius: var(--radius-md, 8px);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/* Why there is no film, said IN the player's own place — the sibling of `.cbvc-nofilm` in
|
|
21
|
+
`videoCutEditor.css`, which documents both halves of the reasoning (why the panel wears the
|
|
22
|
+
video's own class, and why the turner's white-on-black note cannot be reused on a theme
|
|
23
|
+
surface). Restated here for the same reason every `.cbch-*` rule is a sibling of a `.cbvc-*`
|
|
24
|
+
one: these two sheets ride their own lazily-imported chunks and share nothing. */
|
|
25
|
+
.cbch-nofilm {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
min-block-size: 8rem;
|
|
30
|
+
margin: 0;
|
|
31
|
+
padding: 1.5rem;
|
|
32
|
+
text-align: center;
|
|
33
|
+
text-wrap: balance;
|
|
34
|
+
font-size: 13px;
|
|
35
|
+
line-height: 1.5;
|
|
36
|
+
color: var(--muted-foreground, var(--foreground));
|
|
37
|
+
}
|
|
38
|
+
|
|
20
39
|
/* The one authoring row: name the section, then mark it. In that order, because the button
|
|
21
40
|
is disabled until there is a name — see the component. */
|
|
22
41
|
.cbch-add {
|
|
@@ -17,6 +17,28 @@
|
|
|
17
17
|
border-radius: var(--radius-md, 8px);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/* Why there is no film, said IN the player's own place — the owner's *"I see a black screen"*,
|
|
21
|
+
which he could only report as a black screen because the dialog said nothing. It carries
|
|
22
|
+
`.cbvc-video` as well, so the panel is the same width, ground and corner as the element it
|
|
23
|
+
stands in for and the dialog does not jump when a source resolves.
|
|
24
|
+
|
|
25
|
+
🔴 Not `.cbpe-frame-note`, which the turner and the grabber share: that note is white on the
|
|
26
|
+
true black of a photograph's frame, and this sheet's ground is a theme surface — reusing it
|
|
27
|
+
here would be invisible text in the light theme. */
|
|
28
|
+
.cbvc-nofilm {
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
min-block-size: 8rem;
|
|
33
|
+
margin: 0;
|
|
34
|
+
padding: 1.5rem;
|
|
35
|
+
text-align: center;
|
|
36
|
+
text-wrap: balance;
|
|
37
|
+
font-size: 13px;
|
|
38
|
+
line-height: 1.5;
|
|
39
|
+
color: var(--muted-foreground, var(--foreground));
|
|
40
|
+
}
|
|
41
|
+
|
|
20
42
|
.cbvc-marks {
|
|
21
43
|
display: flex;
|
|
22
44
|
align-items: center;
|
|
@@ -44,8 +44,19 @@ export declare function galleryTileLine(item: MediaGalleryItem, options?: {
|
|
|
44
44
|
* listed here, so the feature was invisible with nothing anywhere reporting a fault. It is a
|
|
45
45
|
* pure function so a test can read it directly; the rendered player is a Vidstack custom
|
|
46
46
|
* element that happy-dom never brings to life, so no DOM assertion can see any of this.
|
|
47
|
+
*
|
|
48
|
+
* 🔴 The return type is spelled out rather than imported as `PlayerVideo` from
|
|
49
|
+
* `../media/VideoPlayer`, and the reason is BYTES, not taste. The player is reached from here
|
|
50
|
+
* through `React.lazy(() => import(…))` on purpose, and `scripts/styleAreas.ts`'s closure walk
|
|
51
|
+
* reads STATIC specifiers — an `import type` is one, and tsc erases it long after that walk has
|
|
52
|
+
* decided. Measured 2026-09-18: naming the type pulled the player's whole static closure into
|
|
53
|
+
* the `media-gallery` area stylesheet, 2023 candidates to 2190, for a line that emits nothing
|
|
54
|
+
* at runtime. The two definitions are structurally identical, so tsc still joins them at the
|
|
55
|
+
* one call site that matters (`<LazyVideoPlayer video={…}>` below).
|
|
47
56
|
*/
|
|
48
|
-
export declare function stagePlayableVideo(item: MediaGalleryItem, media: MediaGalleryItemMedia, streamUrl: string): ChapteredVideo
|
|
57
|
+
export declare function stagePlayableVideo(item: MediaGalleryItem, media: MediaGalleryItemMedia, streamUrl: string): ChapteredVideo & {
|
|
58
|
+
playbackDegraded?: boolean;
|
|
59
|
+
};
|
|
49
60
|
export interface MediaGalleryProps {
|
|
50
61
|
items: MediaGalleryItem[];
|
|
51
62
|
/** Header title. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaGallery.d.ts","sourceRoot":"","sources":["../../../src/react/media-gallery/MediaGallery.tsx"],"names":[],"mappings":"AAAA,OAAO,oBAAoB,CAAC;AA4D5B,OAAO,KAAK,EAAE,EACZ,KAAK,SAAS,EAEd,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"MediaGallery.d.ts","sourceRoot":"","sources":["../../../src/react/media-gallery/MediaGallery.tsx"],"names":[],"mappings":"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"}
|