@openrails/contentkit-ui 0.86.0 → 0.87.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/README.md +39 -14
- package/dist/client/beacons.js +5 -1
- package/dist/client/beacons.js.map +1 -1
- package/dist/client/content/types.d.ts +4 -2
- package/dist/client/content/types.js.map +1 -1
- package/dist/client/contents.d.ts +8 -6
- package/dist/client/contents.js +10 -7
- package/dist/client/contents.js.map +1 -1
- package/dist/client/discovery.js +3 -0
- package/dist/client/discovery.js.map +1 -1
- package/dist/client/errors.d.ts +21 -3
- package/dist/client/errors.js +44 -14
- package/dist/client/errors.js.map +1 -1
- package/dist/client/gallery.d.ts +3 -5
- package/dist/client/gallery.js +16 -20
- package/dist/client/gallery.js.map +1 -1
- package/dist/client/generated/error-codes.d.ts +1 -1
- package/dist/client/generated/error-codes.js +8 -0
- package/dist/client/generated/error-codes.js.map +1 -1
- package/dist/client/generated/routes.d.ts +16 -3
- package/dist/client/generated/routes.js +28 -3
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +43 -14
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/http.js +27 -27
- package/dist/client/http.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/media/client.d.ts +10 -4
- package/dist/client/media/client.js +33 -7
- package/dist/client/media/client.js.map +1 -1
- package/dist/client/media/rules.d.ts +1 -1
- package/dist/client/media/rules.js +6 -6
- package/dist/client/media/rules.js.map +1 -1
- package/dist/client/media/transport.d.ts +1 -1
- package/dist/client/media/transport.js +16 -16
- package/dist/client/media/transport.js.map +1 -1
- package/dist/client/media/windows.js +1 -1
- package/dist/client/media/windows.js.map +1 -1
- package/dist/client/public.d.ts +2 -2
- package/dist/client/public.js +2 -2
- package/dist/client/public.js.map +1 -1
- package/dist/client/versions.d.ts +6 -4
- package/dist/client/versions.js +24 -26
- package/dist/client/versions.js.map +1 -1
- package/dist/client.js +25 -25
- package/dist/components/admin/content-manager.js +233 -232
- package/dist/components/admin/content-manager.js.map +1 -1
- package/dist/components/content/card.d.ts +5 -3
- package/dist/components/content/card.js +131 -109
- package/dist/components/content/card.js.map +1 -1
- package/dist/components/content/download-button.d.ts +26 -0
- package/dist/components/content/download-button.js +51 -0
- package/dist/components/content/download-button.js.map +1 -0
- package/dist/components/content/editors.d.ts +8 -0
- package/dist/components/content/editors.js +299 -229
- package/dist/components/content/editors.js.map +1 -1
- package/dist/components/content/grid.d.ts +8 -1
- package/dist/components/content/grid.js +125 -76
- package/dist/components/content/grid.js.map +1 -1
- package/dist/components/content/index.d.ts +3 -2
- package/dist/components/content/listing.d.ts +3 -1
- package/dist/components/content/listing.js.map +1 -1
- package/dist/components/content/paywall.js +61 -61
- package/dist/components/content/paywall.js.map +1 -1
- package/dist/components/media-gallery.d.ts +1 -4
- package/dist/components/media-gallery.js +19 -34
- package/dist/components/media-gallery.js.map +1 -1
- package/dist/components/social/comments.js +1 -1
- package/dist/components/social/comments.js.map +1 -1
- package/dist/components/social/engagement.d.ts +2 -1
- package/dist/components/social/engagement.js +5 -3
- package/dist/components/social/engagement.js.map +1 -1
- package/dist/i18n/messages.js +49 -46
- package/dist/i18n/messages.js.map +1 -1
- package/dist/index.js +12 -11
- package/dist/locales/de.js +15 -3
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/discovery/de.js +3 -0
- package/dist/locales/discovery/de.js.map +1 -1
- package/dist/locales/discovery/en.d.ts +3 -0
- package/dist/locales/discovery/en.js +3 -0
- package/dist/locales/discovery/en.js.map +1 -1
- package/dist/locales/discovery/es.js +3 -0
- package/dist/locales/discovery/es.js.map +1 -1
- package/dist/locales/discovery/ja.js +3 -0
- package/dist/locales/discovery/ja.js.map +1 -1
- package/dist/locales/discovery/ko.js +3 -0
- package/dist/locales/discovery/ko.js.map +1 -1
- package/dist/locales/discovery/zh.js +3 -0
- package/dist/locales/discovery/zh.js.map +1 -1
- package/dist/locales/en.d.ts +17 -2
- package/dist/locales/en.js +15 -3
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +15 -3
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/ja.js +15 -3
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +15 -3
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/zh.js +15 -3
- package/dist/locales/zh.js.map +1 -1
- package/dist/react/comments.d.ts +1 -1
- package/dist/react/comments.js +3 -2
- package/dist/react/comments.js.map +1 -1
- package/dist/react/contents.d.ts +13 -5
- package/dist/react/contents.js +163 -149
- package/dist/react/contents.js.map +1 -1
- package/dist/react/context.d.ts +1 -1
- package/dist/react/context.js.map +1 -1
- package/dist/react/detail.d.ts +7 -1
- package/dist/react/detail.js +9 -6
- package/dist/react/detail.js.map +1 -1
- package/dist/react/discovery.d.ts +11 -0
- package/dist/react/discovery.js +49 -30
- package/dist/react/discovery.js.map +1 -1
- package/dist/react/engagement.d.ts +6 -2
- package/dist/react/engagement.js +2 -6
- package/dist/react/engagement.js.map +1 -1
- package/dist/react/index.d.ts +3 -3
- package/dist/react/public.js +17 -16
- package/dist/react/public.js.map +1 -1
- package/dist/react/versions.d.ts +25 -5
- package/dist/react/versions.js +58 -37
- package/dist/react/versions.js.map +1 -1
- package/dist/react.js +9 -9
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/react/versions.js
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import { toContentKitError as e } from "../client/errors.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { useMessages as t } from "../i18n/context.js";
|
|
3
|
+
import { keyOf as n, useContentScope as r, useResource as i } from "./use-resource.js";
|
|
4
|
+
import { useMediaRead as a } from "./read.js";
|
|
5
|
+
import { isPending as o } from "../client/versions.js";
|
|
6
|
+
import { useCallback as s, useEffect as c, useMemo as l, useState as u } from "react";
|
|
6
7
|
//#region src/react/versions.ts
|
|
7
|
-
var
|
|
8
|
-
function
|
|
8
|
+
var d = 2 ** 31 - 1;
|
|
9
|
+
function f(e, t = Date.now()) {
|
|
9
10
|
let n = (e?.segments ?? []).flatMap((e) => !e.released && e.release_at ? [Date.parse(e.release_at)] : []).filter((e) => e > t);
|
|
10
11
|
return n.length ? Math.min(...n) : null;
|
|
11
12
|
}
|
|
12
|
-
function
|
|
13
|
-
let { client:
|
|
13
|
+
function p(e, t, a = {}) {
|
|
14
|
+
let { client: s, store: l, scope: u } = r(a.client), p = e && t ? n("reader-plan", u, e, t) : null, m = i(l, p, {
|
|
14
15
|
type: "reader-plan",
|
|
15
|
-
id:
|
|
16
|
-
}, (
|
|
17
|
-
return
|
|
18
|
-
let e =
|
|
16
|
+
id: t ?? void 0
|
|
17
|
+
}, (n) => s.versions.reader(e, t, n)), h = o(m.data), g = m.data && !h ? m.data : null, { data: _, reload: v } = m;
|
|
18
|
+
return c(() => {
|
|
19
|
+
let e = o(_) ? Date.now() + (a.poll ?? 5e3) : f(_ || null);
|
|
19
20
|
if (e === null) return;
|
|
20
|
-
let t = setTimeout(v, Math.min(
|
|
21
|
+
let t = setTimeout(v, Math.min(d, Math.max(0, e - Date.now()) + 500));
|
|
21
22
|
return () => clearTimeout(t);
|
|
22
23
|
}, [
|
|
23
24
|
_,
|
|
24
25
|
v,
|
|
25
|
-
|
|
26
|
+
a.poll
|
|
26
27
|
]), {
|
|
27
28
|
plan: g,
|
|
28
29
|
pending: h,
|
|
@@ -31,8 +32,8 @@ function f(e, i, o = {}) {
|
|
|
31
32
|
reload: v
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
|
-
function
|
|
35
|
-
let r = e?.item ?? null,
|
|
35
|
+
function m(e, t, n = {}) {
|
|
36
|
+
let r = e?.item ?? null, i = a(r ?? {
|
|
36
37
|
kind: "",
|
|
37
38
|
id: ""
|
|
38
39
|
}, {
|
|
@@ -41,8 +42,8 @@ function p(e, t, n = {}) {
|
|
|
41
42
|
client: n.client
|
|
42
43
|
});
|
|
43
44
|
return {
|
|
44
|
-
pages:
|
|
45
|
-
let n = new Map((
|
|
45
|
+
pages: l(() => {
|
|
46
|
+
let n = new Map((i.read?.files ?? []).flatMap((e) => e.url ? [[e.path, e.url]] : []));
|
|
46
47
|
return (e?.pages ?? []).map((e) => {
|
|
47
48
|
let r = e.files[t];
|
|
48
49
|
return {
|
|
@@ -55,40 +56,60 @@ function p(e, t, n = {}) {
|
|
|
55
56
|
}, [
|
|
56
57
|
e,
|
|
57
58
|
t,
|
|
58
|
-
|
|
59
|
+
i.read
|
|
59
60
|
]),
|
|
60
|
-
loading: !!r &&
|
|
61
|
-
error:
|
|
61
|
+
loading: !!r && i.loading,
|
|
62
|
+
error: i.error
|
|
62
63
|
};
|
|
63
64
|
}
|
|
64
|
-
function
|
|
65
|
-
let
|
|
65
|
+
function h(e) {
|
|
66
|
+
let t = document.createElement("a");
|
|
67
|
+
t.href = e.url, t.download = e.name, t.rel = "noopener", t.style.display = "none", document.body.appendChild(t), t.click(), t.remove();
|
|
68
|
+
}
|
|
69
|
+
function g(e, t, n = Date.now()) {
|
|
70
|
+
switch (t?.code) {
|
|
71
|
+
case void 0: return;
|
|
72
|
+
case "rate_limited": return e.t("versionDownload.limited", { minutes: Math.max(1, Math.ceil((t.retryAfter ?? 60) / 60)) });
|
|
73
|
+
case "download_unavailable": {
|
|
74
|
+
let r = t.availableAt ? Date.parse(t.availableAt) - n : NaN;
|
|
75
|
+
return r > 0 ? e.plural("versionDownload.availableIn", Math.max(1, Math.ceil(r / 864e5))) : e.t("versionDownload.unavailable");
|
|
76
|
+
}
|
|
77
|
+
case "forbidden": return e.t("versionDownload.locked");
|
|
78
|
+
case "no_download": return e.error(t);
|
|
79
|
+
default: return e.t("versionDownload.failed");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function _(n, i, a = {}) {
|
|
83
|
+
let { client: c } = r(a.client), l = t(), [d, f] = u(!1), [p, m] = u(), [_, v] = u(), y = a.start ?? h;
|
|
66
84
|
return {
|
|
67
|
-
download:
|
|
68
|
-
|
|
85
|
+
download: s(async () => {
|
|
86
|
+
m(void 0), v(void 0), f(!0);
|
|
69
87
|
try {
|
|
70
88
|
for (;;) {
|
|
71
|
-
let e = await
|
|
72
|
-
if (!
|
|
73
|
-
await new Promise((e) => setTimeout(e,
|
|
89
|
+
let e = await c.versions.download(n, i);
|
|
90
|
+
if (!o(e)) return y(e), e;
|
|
91
|
+
await new Promise((e) => setTimeout(e, a.poll ?? 3e3));
|
|
74
92
|
}
|
|
75
93
|
} catch (t) {
|
|
76
94
|
let n = e(t);
|
|
77
|
-
throw
|
|
95
|
+
throw m(n), n.code === "rate_limited" && v(Date.now() + (n.retryAfter ?? 60) * 1e3), n;
|
|
78
96
|
} finally {
|
|
79
|
-
|
|
97
|
+
f(!1);
|
|
80
98
|
}
|
|
81
99
|
}, [
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
100
|
+
c,
|
|
101
|
+
n,
|
|
102
|
+
i,
|
|
103
|
+
a.poll,
|
|
104
|
+
y
|
|
86
105
|
]),
|
|
87
|
-
preparing:
|
|
88
|
-
error:
|
|
106
|
+
preparing: d,
|
|
107
|
+
error: p,
|
|
108
|
+
retryAt: _,
|
|
109
|
+
message: g(l, p)
|
|
89
110
|
};
|
|
90
111
|
}
|
|
91
112
|
//#endregion
|
|
92
|
-
export {
|
|
113
|
+
export { g as downloadMessage, f as nextRelease, h as startDownload, p as useReaderPlan, m as useSegmentPages, _ as useVersionDownload };
|
|
93
114
|
|
|
94
115
|
//# sourceMappingURL=versions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versions.js","names":[],"sources":["../../src/react/versions.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport { toContentKitError, type ContentKitError } from \"../client/errors.js\";\nimport type { Pending, PlanSegment, ReaderPlan } from \"../client/generated/wire.js\";\nimport { isPending } from \"../client/versions.js\";\nimport { useMediaRead, type ReadWindow } from \"./read.js\";\nimport { keyOf, useContentScope, useResource } from \"./use-resource.js\";\n\nexport interface UseReaderPlan {\n /** null while loading, pending or failed. */\n plan: ReaderPlan | null;\n /** The version has no current publication yet; the hook asks again. */\n pending: boolean;\n loading: boolean;\n error?: ContentKitError;\n reload: () => void;\n}\n\n// setTimeout's longest delay.\nconst MAX_DELAY = 2 ** 31 - 1;\n\n/** When the plan changes by itself: its next scheduled segment's release. */\nexport function nextRelease(plan: ReaderPlan | null, now = Date.now()): number | null {\n const at = (plan?.segments ?? []).flatMap((s) => (!s.released && s.release_at ? [Date.parse(s.release_at)] : [])).filter((t) => t > now);\n return at.length ? Math.min(...at) : null;\n}\n\n/**\n * A version's reader plan for this viewer: its segments (released or not,\n * open or locked), previews, playback item and reader metadata. It asks again\n * while the version is being published and when its next segment is released.\n */\nexport function useReaderPlan(content: string | null | undefined, version: string | null | undefined, o: { poll?: number; client?: ContentKitClient } = {}): UseReaderPlan {\n const { client, store, scope } = useContentScope(o.client);\n const key = content && version ? keyOf(\"reader-plan\", scope, content, version) : null;\n const r = useResource<ReaderPlan | Pending>(store, key, { type: \"reader-plan\", id: version ?? undefined }, (s) => client.versions.reader(content!, version!, s));\n const pending = isPending(r.data);\n const plan = r.data && !pending ? (r.data as ReaderPlan) : null;\n const { data, reload } = r;\n // Every answer schedules the next look: a pending one polls, a plan waits for its next release.\n useEffect(() => {\n const at = isPending(data) ? Date.now() + (o.poll ?? 5000) : nextRelease(data ? (data as ReaderPlan) : null);\n if (at === null) return;\n const t = setTimeout(reload, Math.min(MAX_DELAY, Math.max(0, at - Date.now()) + 500));\n return () => clearTimeout(t);\n }, [data, reload, o.poll]);\n return { plan, pending, loading: !!key && (r.loading || !r.loaded), error: r.error, reload };\n}\n\n/** A segment's page with the URL of one rendition, once its item's read signed it. */\nexport interface ReaderPage {\n name: string;\n w: number;\n h: number;\n /** undefined until read, or when the page lacks the rendition. */\n url?: string;\n}\n\nexport interface UseSegmentPages {\n pages: ReaderPage[];\n loading: boolean;\n error?: ContentKitError;\n}\n\n/**\n * An open segment's pages with URLs of one rendition, read through its\n * published item (windowed for long segments, refreshed before the URLs expire).\n */\nexport function useSegmentPages(segment: PlanSegment | null | undefined, rendition: string, o: { window?: ReadWindow; client?: ContentKitClient } = {}): UseSegmentPages {\n const item = segment?.item ?? null;\n const read = useMediaRead(item ?? { kind: \"\", id: \"\" }, { window: o.window, read: item ? undefined : null, client: o.client });\n const pages = useMemo(() => {\n const urls = new Map((read.read?.files ?? []).flatMap((f) => (f.url ? [[f.path, f.url] as const] : [])));\n return (segment?.pages ?? []).map((p) => {\n const path = p.files[rendition];\n return { name: p.name, w: p.w, h: p.h, url: path ? urls.get(path) : undefined };\n });\n }, [segment, rendition, read.read]);\n return { pages, loading: !!item && read.loading, error: read.error };\n}\n\nexport interface UseVersionDownload {\n /** Prepares the zip (asking again while it is prepared) and resolves with it. */\n download: () => Promise<Blob>;\n /** Prepared by the server, waiting. */\n preparing: boolean;\n error?: ContentKitError;\n}\n\n/** A version's pages as a zip, charged to the viewer's download quota. */\nexport function useVersionDownload(content: string, version: string, o: { poll?: number; client?: ContentKitClient } = {}): UseVersionDownload {\n const { client } = useContentScope(o.client);\n const [preparing, setPreparing] = useState(false);\n const [error, setError] = useState<ContentKitError>();\n const download = useCallback(async () => {\n setError(undefined);\n setPreparing(true);\n try {\n for (;;) {\n const out = await client.versions.download(content, version);\n if (!isPending(out)) return out;\n await new Promise((r) => setTimeout(r, o.poll ?? 3000));\n }\n } catch (e) {\n const err = toContentKitError(e);\n setError(err);\n throw err;\n } finally {\n setPreparing(false);\n }\n }, [client, content, version, o.poll]);\n return { download, preparing, error };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"versions.js","names":[],"sources":["../../src/react/versions.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport { toContentKitError, type ContentKitError } from \"../client/errors.js\";\nimport type { FileDownload, Pending, PlanSegment, ReaderPlan } from \"../client/generated/wire.js\";\nimport { isPending } from \"../client/versions.js\";\nimport { useMessages } from \"../i18n/context.js\";\nimport type { Translator } from \"../i18n/messages.js\";\nimport { useMediaRead, type ReadWindow } from \"./read.js\";\nimport { keyOf, useContentScope, useResource } from \"./use-resource.js\";\n\nexport interface UseReaderPlan {\n /** null while loading, pending or failed. */\n plan: ReaderPlan | null;\n /** The version has no current publication yet; the hook asks again. */\n pending: boolean;\n loading: boolean;\n error?: ContentKitError;\n reload: () => void;\n}\n\n// setTimeout's longest delay.\nconst MAX_DELAY = 2 ** 31 - 1;\n\n/** When the plan changes by itself: its next scheduled segment's release. */\nexport function nextRelease(plan: ReaderPlan | null, now = Date.now()): number | null {\n const at = (plan?.segments ?? []).flatMap((s) => (!s.released && s.release_at ? [Date.parse(s.release_at)] : [])).filter((t) => t > now);\n return at.length ? Math.min(...at) : null;\n}\n\n/**\n * A version's reader plan for this viewer: its segments (released or not,\n * open or locked), previews, playback item and reader metadata. It asks again\n * while the version is being published and when its next segment is released.\n */\nexport function useReaderPlan(content: string | null | undefined, version: string | null | undefined, o: { poll?: number; client?: ContentKitClient } = {}): UseReaderPlan {\n const { client, store, scope } = useContentScope(o.client);\n const key = content && version ? keyOf(\"reader-plan\", scope, content, version) : null;\n const r = useResource<ReaderPlan | Pending>(store, key, { type: \"reader-plan\", id: version ?? undefined }, (s) => client.versions.reader(content!, version!, s));\n const pending = isPending(r.data);\n const plan = r.data && !pending ? (r.data as ReaderPlan) : null;\n const { data, reload } = r;\n // Every answer schedules the next look: a pending one polls, a plan waits for its next release.\n useEffect(() => {\n const at = isPending(data) ? Date.now() + (o.poll ?? 5000) : nextRelease(data ? (data as ReaderPlan) : null);\n if (at === null) return;\n const t = setTimeout(reload, Math.min(MAX_DELAY, Math.max(0, at - Date.now()) + 500));\n return () => clearTimeout(t);\n }, [data, reload, o.poll]);\n return { plan, pending, loading: !!key && (r.loading || !r.loaded), error: r.error, reload };\n}\n\n/** A segment's page with the URL of one rendition, once its item's read signed it. */\nexport interface ReaderPage {\n name: string;\n w: number;\n h: number;\n /** undefined until read, or when the page lacks the rendition. */\n url?: string;\n}\n\nexport interface UseSegmentPages {\n pages: ReaderPage[];\n loading: boolean;\n error?: ContentKitError;\n}\n\n/**\n * An open segment's pages with URLs of one rendition, read through its\n * published item (windowed for long segments, refreshed before the URLs expire).\n */\nexport function useSegmentPages(segment: PlanSegment | null | undefined, rendition: string, o: { window?: ReadWindow; client?: ContentKitClient } = {}): UseSegmentPages {\n const item = segment?.item ?? null;\n const read = useMediaRead(item ?? { kind: \"\", id: \"\" }, { window: o.window, read: item ? undefined : null, client: o.client });\n const pages = useMemo(() => {\n const urls = new Map((read.read?.files ?? []).flatMap((f) => (f.url ? [[f.path, f.url] as const] : [])));\n return (segment?.pages ?? []).map((p) => {\n const path = p.files[rendition];\n return { name: p.name, w: p.w, h: p.h, url: path ? urls.get(path) : undefined };\n });\n }, [segment, rendition, read.read]);\n return { pages, loading: !!item && read.loading, error: read.error };\n}\n\nexport interface UseVersionDownload {\n /**\n * Grants the download (asking again while it is prepared), starts it in the\n * browser and resolves with the grant.\n */\n download: () => Promise<FileDownload>;\n /** Being prepared by the server, or granted and starting. */\n preparing: boolean;\n error?: ContentKitError;\n /** While a quota refused: when the viewer may download again (ms). */\n retryAt?: number;\n /**\n * What to tell the viewer about the last refusal: when a quota frees, when\n * a download the site holds back opens (\"available to download in N\n * days\"), a locked version, nothing to download, or a failure.\n */\n message?: string;\n}\n\n/** Starts a granted download: the browser fetches its URL, an attachment. */\nexport function startDownload(d: FileDownload): void {\n const a = document.createElement(\"a\");\n a.href = d.url;\n a.download = d.name;\n a.rel = \"noopener\";\n a.style.display = \"none\";\n document.body.appendChild(a);\n a.click();\n a.remove();\n}\n\n/** The viewer's line for a download refusal at now. */\nexport function downloadMessage(m: Translator, err: ContentKitError | undefined, now = Date.now()): string | undefined {\n switch (err?.code) {\n case undefined:\n return undefined;\n case \"rate_limited\":\n return m.t(\"versionDownload.limited\", { minutes: Math.max(1, Math.ceil((err.retryAfter ?? 60) / 60)) });\n case \"download_unavailable\": {\n const ms = err.availableAt ? Date.parse(err.availableAt) - now : NaN;\n return ms > 0 ? m.plural(\"versionDownload.availableIn\", Math.max(1, Math.ceil(ms / 86_400_000))) : m.t(\"versionDownload.unavailable\");\n }\n case \"forbidden\":\n return m.t(\"versionDownload.locked\");\n case \"no_download\":\n return m.error(err);\n default:\n return m.t(\"versionDownload.failed\");\n }\n}\n\n/**\n * A version's download, charged to the viewer's download quota: the\n * original or rendition its kind serves, or its pages as a zip.\n */\nexport function useVersionDownload(\n content: string,\n version: string,\n o: { poll?: number; client?: ContentKitClient; start?: (d: FileDownload) => void } = {},\n): UseVersionDownload {\n const { client } = useContentScope(o.client);\n const m = useMessages();\n const [preparing, setPreparing] = useState(false);\n const [error, setError] = useState<ContentKitError>();\n const [retryAt, setRetryAt] = useState<number>();\n const start = o.start ?? startDownload;\n const download = useCallback(async () => {\n setError(undefined);\n setRetryAt(undefined);\n setPreparing(true);\n try {\n for (;;) {\n const out = await client.versions.download(content, version);\n if (!isPending(out)) {\n start(out);\n return out;\n }\n await new Promise((r) => setTimeout(r, o.poll ?? 3000));\n }\n } catch (e) {\n const err = toContentKitError(e);\n setError(err);\n if (err.code === \"rate_limited\") setRetryAt(Date.now() + (err.retryAfter ?? 60) * 1000);\n throw err;\n } finally {\n setPreparing(false);\n }\n }, [client, content, version, o.poll, start]);\n return { download, preparing, error, retryAt, message: downloadMessage(m, error) };\n}\n"],"mappings":"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"}
|
package/dist/react.js
CHANGED
|
@@ -18,12 +18,12 @@ import { useFavorite as se, useReaction as ce } from "./react/engagement.js";
|
|
|
18
18
|
import { usePoll as le, usePollEditor as ue, usePolls as de, withVote as fe } from "./react/polls.js";
|
|
19
19
|
import { useVersionParam as pe } from "./react/location.js";
|
|
20
20
|
import { useAdminLocation as me, useFlowClient as he, useStaffAccess as ge } from "./react/admin.js";
|
|
21
|
-
import { beaconsFor as _e, useBeacons as ve, useContentFilters as ye, useContents as be, useExposure as xe, useHistory as Se,
|
|
22
|
-
import { defaultVersion as
|
|
23
|
-
import { nextRelease as
|
|
24
|
-
import { useActivity as
|
|
25
|
-
import { useContent as
|
|
26
|
-
import { useNotificationUnread as
|
|
27
|
-
import { ContentKitProvider as
|
|
28
|
-
import { useCanonicalContent as
|
|
29
|
-
export {
|
|
21
|
+
import { beaconsFor as _e, useBeacons as ve, useContentFilters as ye, useContents as be, useExposure as xe, useHistory as Se, useLockedCount as Ce, useMyFavorites as we, useMyReactions as Te, useRecentSearches as Ee, useRecommendations as De, useReleaseDates as Oe, useSearch as ke, useSimilar as Ae, useTypeahead as je, useViewSignal as Me } from "./react/discovery.js";
|
|
22
|
+
import { defaultVersion as Ne, editionOf as Pe, findVersion as Fe, liveVersions as Ie, useContentDetail as Le } from "./react/detail.js";
|
|
23
|
+
import { downloadMessage as Re, nextRelease as ze, startDownload as Be, useReaderPlan as Ve, useSegmentPages as He, useVersionDownload as Ue } from "./react/versions.js";
|
|
24
|
+
import { useActivity as We, useMyStats as Ge, useTopContents as Ke } from "./react/stats.js";
|
|
25
|
+
import { useContent as qe, useManagedContents as Je } from "./react/contents.js";
|
|
26
|
+
import { useNotificationUnread as Ye, useNotifications as Xe } from "./react/notifications.js";
|
|
27
|
+
import { ContentKitProvider as Ze } from "./react/provider.js";
|
|
28
|
+
import { useCanonicalContent as Qe } from "./react/canonical.js";
|
|
29
|
+
export { Ze as ContentKitProvider, R as GALLERY_VIEW_KEY, i as GuardContext, e as HOVER_DELAY, t as InlinePreviewContext, z as PLAYER_QUALITY_KEY, h as ResourceStore, _e as beaconsFor, Ne as defaultVersion, Re as downloadMessage, A as editOutput, Pe as editionOf, Fe as findVersion, Ie as liveVersions, y as memberId, G as nameIn, ze as nextRelease, g as resourcesFor, N as round3, Be as startDownload, K as thumbnailOf, We as useActivity, Y as useAdminComments, me as useAdminLocation, D as useAvatar, X as useBannedWords, ve as useBeacons, Z as useCanComment, Qe as useCanonicalContent, B as useCarousel, Q as useCommentBans, $ as useCommentReplies, ee as useComments, qe as useContent, oe as useContentConfig, Le as useContentDetail, ye as useContentFilters, b as useContentGroups, a as useContentKit, o as useContentKitClient, _ as useContentScope, s as useContentURLs, be as useContents, d as useCrop, W as useEditorCrop, f as useEncodeProgress, c as useErrorReporter, xe as useExposure, se as useFavorite, he as useFlowClient, P as useFrameStrip, V as useGalleryView, te as useGlobalCommentBan, x as useGroup, S as useGroupMembers, C as useGroups, l as useGuarded, Se as useHistory, H as useHlsPlayer, ne as useIPBans, n as useInlinePreview, w as useKinds, re as useLatestComments, Ce as useLockedCount, Je as useManagedContents, q as useMediaFolder, E as useMediaRead, ie as useModerationQueue, we as useMyFavorites, T as useMyGroups, Te as useMyReactions, Ge as useMyStats, J as useNearViewport, Ye as useNotificationUnread, Xe as useNotifications, u as useOptionalContentKitClient, v as usePaged, le as usePoll, ue as usePollEditor, de as usePolls, O as usePresets, k as usePublicImage, ce as useReaction, Ve as useReaderPlan, Ee as useRecentSearches, De as useRecommendations, r as useReducedMotion, U as useRefreshBeforeExpiry, Oe as useReleaseDates, ke as useSearch, He as useSegmentPages, Ae as useSimilar, j as useSlotCrop, M as useSlotImage, ge as useStaffAccess, Ke as useTopContents, je as useTypeahead, p as useUpload, m as useUploadQueue, Ue as useVersionDownload, pe as useVersionParam, F as useVideoFrame, I as useVideoImages, L as useVideoPoster, Me as useViewSignal, ae as withReaction, fe as withVote };
|