@epic-web/workshop-app 5.4.1 → 5.6.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/build/client/assets/{_-BrkpfnBb.js → _-hAKYb2AG.js} +2 -2
- package/build/client/assets/{_-BrkpfnBb.js.map → _-hAKYb2AG.js.map} +1 -1
- package/build/client/assets/_exerciseNumber-PTdG9GGB.js +2 -0
- package/build/client/assets/_exerciseNumber-PTdG9GGB.js.map +1 -0
- package/build/client/assets/{_exerciseNumber_._stepNumber-BIMJh_sg.js → _exerciseNumber_._stepNumber-03erOIGo.js} +2 -2
- package/build/client/assets/{_exerciseNumber_._stepNumber-BIMJh_sg.js.map → _exerciseNumber_._stepNumber-03erOIGo.js.map} +1 -1
- package/build/client/assets/_exerciseNumber_.finished-DQg4F1NL.js +2 -0
- package/build/client/assets/_exerciseNumber_.finished-DQg4F1NL.js.map +1 -0
- package/build/client/assets/{_layout-88n0To1b.js → _layout-B4JGpA3A.js} +2 -2
- package/build/client/assets/{_layout-88n0To1b.js.map → _layout-B4JGpA3A.js.map} +1 -1
- package/build/client/assets/{_layout-Dfmv2zcn.js → _layout-BJbMl6SJ.js} +2 -2
- package/build/client/assets/{_layout-Dfmv2zcn.js.map → _layout-BJbMl6SJ.js.map} +1 -1
- package/build/client/assets/_layout-Bu0lel3p.js +6 -0
- package/build/client/assets/_layout-Bu0lel3p.js.map +1 -0
- package/build/client/assets/_layout-DHoH74NH.js +2 -0
- package/build/client/assets/_layout-DHoH74NH.js.map +1 -0
- package/build/client/assets/{accordion-D9-D-n9p.js → accordion-DLg7gJkp.js} +2 -2
- package/build/client/assets/{accordion-D9-D-n9p.js.map → accordion-DLg7gJkp.js.map} +1 -1
- package/build/client/assets/account-DLDPrc9J.js +2 -0
- package/build/client/assets/account-DLDPrc9J.js.map +1 -0
- package/build/client/assets/app-DJDjmdlu.js +2 -0
- package/build/client/assets/{app-DgTXXO8s.js.map → app-DJDjmdlu.js.map} +1 -1
- package/build/client/assets/{button-_qPvcoqR.js → button-39zQyNX6.js} +2 -2
- package/build/client/assets/{button-_qPvcoqR.js.map → button-39zQyNX6.js.map} +1 -1
- package/build/client/assets/{components-Be92gVxW.js → components-DUNtf72c.js} +2 -2
- package/build/client/assets/{components-Be92gVxW.js.map → components-DUNtf72c.js.map} +1 -1
- package/build/client/assets/diff-B3oaU_KB.js +2 -0
- package/build/client/assets/{diff-BhRAIPKc.js.map → diff-B3oaU_KB.js.map} +1 -1
- package/build/client/assets/{diff-8nlDkmpc.js → diff-BNCREJvf.js} +2 -2
- package/build/client/assets/{diff-8nlDkmpc.js.map → diff-BNCREJvf.js.map} +1 -1
- package/build/client/assets/{discord-BUWZUTEC.js → discord-CEOqKs_c.js} +2 -2
- package/build/client/assets/{discord-BUWZUTEC.js.map → discord-CEOqKs_c.js.map} +1 -1
- package/build/client/assets/discord-CpIgvYus.js +2 -0
- package/build/client/assets/discord-CpIgvYus.js.map +1 -0
- package/build/client/assets/{entry.client-DqIWuxf8.js → entry.client-CrlHhRMR.js} +2 -2
- package/build/client/assets/{entry.client-DqIWuxf8.js.map → entry.client-CrlHhRMR.js.map} +1 -1
- package/build/client/assets/epic-video-D8ex9vao.js +2 -0
- package/build/client/assets/epic-video-D8ex9vao.js.map +1 -0
- package/build/client/assets/error-boundary-3zItlMUO.js +2 -0
- package/build/client/assets/{error-boundary-BZA-ffa8.js.map → error-boundary-3zItlMUO.js.map} +1 -1
- package/build/client/assets/finished-rUzUjnEm.js +2 -0
- package/build/client/assets/finished-rUzUjnEm.js.map +1 -0
- package/build/client/assets/index-BajUQsFT.js +3053 -0
- package/build/client/assets/index-BajUQsFT.js.map +1 -0
- package/build/client/assets/{index-BCxBKsqT.js → index-CLNXC84j.js} +2 -2
- package/build/client/assets/{index-BCxBKsqT.js.map → index-CLNXC84j.js.map} +1 -1
- package/build/client/assets/{index-BCTr8uu6.js → index-CV3nxGFp.js} +2 -2
- package/build/client/assets/{index-BCTr8uu6.js.map → index-CV3nxGFp.js.map} +1 -1
- package/build/client/assets/{index-BFGhCX_U.js → index-C_B1-9rF.js} +2 -2
- package/build/client/assets/{index-BFGhCX_U.js.map → index-C_B1-9rF.js.map} +1 -1
- package/build/client/assets/{index-pkiQppkK.js → index-DDqzbGM2.js} +2 -2
- package/build/client/assets/{index-pkiQppkK.js.map → index-DDqzbGM2.js.map} +1 -1
- package/build/client/assets/index-DE-jwnOP.js +2 -0
- package/build/client/assets/index-DE-jwnOP.js.map +1 -0
- package/build/client/assets/{index-DZDhtMuq.js → index-DFqQCjCw.js} +2 -2
- package/build/client/assets/{index-DZDhtMuq.js.map → index-DFqQCjCw.js.map} +1 -1
- package/build/client/assets/{index-Bdg3v8tC.js → index-DH1w3QmP.js} +2 -2
- package/build/client/assets/{index-Bdg3v8tC.js.map → index-DH1w3QmP.js.map} +1 -1
- package/build/client/assets/{index-C9Hx0Dey.js → index-LjRZeU7x.js} +2 -2
- package/build/client/assets/{index-C9Hx0Dey.js.map → index-LjRZeU7x.js.map} +1 -1
- package/build/client/assets/index-mivnjq36.js +2 -0
- package/build/client/assets/index-mivnjq36.js.map +1 -0
- package/build/client/assets/{loading-XhMtj4mp.js → loading-DW_I206H.js} +2 -2
- package/build/client/assets/{loading-XhMtj4mp.js.map → loading-DW_I206H.js.map} +1 -1
- package/build/client/assets/{login-C1oOgi98.js → login-CdNej0Z7.js} +2 -2
- package/build/client/assets/{login-C1oOgi98.js.map → login-CdNej0Z7.js.map} +1 -1
- package/build/client/assets/manifest-62ea49c4.js +1 -0
- package/build/client/assets/{mdx-CEjzXoEx.js → mdx-C9dqA6IZ.js} +2 -2
- package/build/client/assets/{mdx-CEjzXoEx.js.map → mdx-C9dqA6IZ.js.map} +1 -1
- package/build/client/assets/{misc-DUy_whwE.js → misc-DIdEn_jt.js} +2 -2
- package/build/client/assets/{misc-DUy_whwE.js.map → misc-DIdEn_jt.js.map} +1 -1
- package/build/client/assets/{nav-chevrons-DnR25VLp.js → nav-chevrons-B3SvZV8B.js} +2 -2
- package/build/client/assets/{nav-chevrons-DnR25VLp.js.map → nav-chevrons-B3SvZV8B.js.map} +1 -1
- package/build/client/assets/onboarding-CC9zz4rl.js +2 -0
- package/build/client/assets/onboarding-CC9zz4rl.js.map +1 -0
- package/build/client/assets/{pe-ChIwTk8v.js → pe-D5h19vSo.js} +2 -2
- package/build/client/assets/{pe-ChIwTk8v.js.map → pe-D5h19vSo.js.map} +1 -1
- package/build/client/assets/presence-D1DPz__2.js +28 -0
- package/build/client/assets/presence-D1DPz__2.js.map +1 -0
- package/build/client/assets/{preview-DaZd0wMb.js → preview-BEtmdi0E.js} +2 -2
- package/build/client/assets/{preview-DaZd0wMb.js.map → preview-BEtmdi0E.js.map} +1 -1
- package/build/client/assets/{product-DIAmCwmZ.js → product-CYOFfeJM.js} +2 -2
- package/build/client/assets/{product-DIAmCwmZ.js.map → product-CYOFfeJM.js.map} +1 -1
- package/build/client/assets/{progress-DQt_Bn9o.js → progress-D6SP0Gec.js} +2 -2
- package/build/client/assets/{progress-DQt_Bn9o.js.map → progress-D6SP0Gec.js.map} +1 -1
- package/build/client/assets/{progress-bar-BaTU3Yx_.js → progress-bar-CBDBzRQ2.js} +2 -2
- package/build/client/assets/{progress-bar-BaTU3Yx_.js.map → progress-bar-CBDBzRQ2.js.map} +1 -1
- package/build/client/assets/{request-info-ByUEfOil.js → request-info-vBkaf3Rk.js} +2 -2
- package/build/client/assets/{request-info-ByUEfOil.js.map → request-info-vBkaf3Rk.js.map} +1 -1
- package/build/client/assets/{revalidation-ws-dUa9CAqr.js → revalidation-ws-DK5QOPlL.js} +2 -2
- package/build/client/assets/{revalidation-ws-dUa9CAqr.js.map → revalidation-ws-DK5QOPlL.js.map} +1 -1
- package/build/client/assets/{root-a3d3Qwip.js → root-Bg-hxaOK.js} +2 -2
- package/build/client/assets/{root-a3d3Qwip.js.map → root-Bg-hxaOK.js.map} +1 -1
- package/build/client/assets/{set-playground-CBHBA46B.js → set-playground-CMoUFgkO.js} +2 -2
- package/build/client/assets/{set-playground-CBHBA46B.js.map → set-playground-CMoUFgkO.js.map} +1 -1
- package/build/client/assets/{support-CIz02V_r.js → support-CPzYlWkd.js} +2 -2
- package/build/client/assets/{support-CIz02V_r.js.map → support-CPzYlWkd.js.map} +1 -1
- package/build/client/assets/test-C8wkLh9a.js +2 -0
- package/build/client/assets/{test-DoKJvNug.js.map → test-C8wkLh9a.js.map} +1 -1
- package/build/client/assets/{tests-DbuyD2cI.js → tests-CiM4RPOf.js} +2 -2
- package/build/client/assets/tests-CiM4RPOf.js.map +1 -0
- package/build/client/assets/{tooltip-DO9uwurQ.js → tooltip-BoVikCa-.js} +2 -2
- package/build/client/assets/{tooltip-DO9uwurQ.js.map → tooltip-BoVikCa-.js.map} +1 -1
- package/build/client/assets/{use-event-source-x59d4R2Z.js → use-event-source-M87p8Tme.js} +2 -2
- package/build/client/assets/{use-event-source-x59d4R2Z.js.map → use-event-source-M87p8Tme.js.map} +1 -1
- package/build/client/assets/{user-Bv6wYhQP.js → user-CbbIYEs8.js} +2 -2
- package/build/client/assets/{user-Bv6wYhQP.js.map → user-CbbIYEs8.js.map} +1 -1
- package/build/client/assets/{version-lxUUxt3s.js → version-CIF3cX3N.js} +2 -2
- package/build/client/assets/{version-lxUUxt3s.js.map → version-CIF3cX3N.js.map} +1 -1
- package/build/client/assets/{workshop-config-WVltG_BV.js → workshop-config-C5sYl312.js} +2 -2
- package/build/client/assets/{workshop-config-WVltG_BV.js.map → workshop-config-C5sYl312.js.map} +1 -1
- package/build/server/index.js +456 -782
- package/build/server/index.js.map +1 -1
- package/package.json +8 -8
- package/build/client/assets/_exerciseNumber-DCSM0NCG.js +0 -2
- package/build/client/assets/_exerciseNumber-DCSM0NCG.js.map +0 -1
- package/build/client/assets/_exerciseNumber_.finished-nbpk1ToO.js +0 -2
- package/build/client/assets/_exerciseNumber_.finished-nbpk1ToO.js.map +0 -1
- package/build/client/assets/_layout-Cbz7Qt-S.js +0 -6
- package/build/client/assets/_layout-Cbz7Qt-S.js.map +0 -1
- package/build/client/assets/_layout-DTAM9xh5.js +0 -2
- package/build/client/assets/_layout-DTAM9xh5.js.map +0 -1
- package/build/client/assets/account-C4Piztoz.js +0 -2
- package/build/client/assets/account-C4Piztoz.js.map +0 -1
- package/build/client/assets/app-DgTXXO8s.js +0 -2
- package/build/client/assets/diff-BhRAIPKc.js +0 -2
- package/build/client/assets/discord-Bdnx7fu-.js +0 -2
- package/build/client/assets/discord-Bdnx7fu-.js.map +0 -1
- package/build/client/assets/epic-video-Bp4BOD2R.js +0 -3053
- package/build/client/assets/epic-video-Bp4BOD2R.js.map +0 -1
- package/build/client/assets/error-boundary-BZA-ffa8.js +0 -2
- package/build/client/assets/finished-C0cpfAFL.js +0 -2
- package/build/client/assets/finished-C0cpfAFL.js.map +0 -1
- package/build/client/assets/index-Bi1TbRTj.js +0 -2
- package/build/client/assets/index-Bi1TbRTj.js.map +0 -1
- package/build/client/assets/index-Ca4vBON4.js +0 -2
- package/build/client/assets/index-Ca4vBON4.js.map +0 -1
- package/build/client/assets/manifest-e5b2a6e1.js +0 -1
- package/build/client/assets/onboarding-C2YNq60k.js +0 -2
- package/build/client/assets/onboarding-C2YNq60k.js.map +0 -1
- package/build/client/assets/presence-DJGFvdDh.js +0 -28
- package/build/client/assets/presence-DJGFvdDh.js.map +0 -1
- package/build/client/assets/test-DoKJvNug.js +0 -2
- package/build/client/assets/tests-DbuyD2cI.js.map +0 -1
- /package/build/client/assets/{epic-video-DUnRvy1A.css → index-DUnRvy1A.css} +0 -0
package/build/server/index.js
CHANGED
|
@@ -5,11 +5,13 @@ import { RemixServer, Link, useRouteError, useParams, isRouteErrorResponse, useN
|
|
|
5
5
|
import { isbot } from "isbot";
|
|
6
6
|
import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
|
|
7
7
|
import path from "node:path";
|
|
8
|
-
import { makeSingletonCache, cachified,
|
|
9
|
-
import { getPreferences, getAuthInfo, readOnboardingData, requireAuthInfo, deleteDb, setPresencePreferences, PlayerPreferencesSchema, setPlayerPreferences, setAuthInfo, markOnboardingVideoWatched } from "@epic-web/workshop-utils/db.server";
|
|
10
|
-
import { z } from "zod";
|
|
11
|
-
import { getWorkshopInstructions, getWorkshopFinished, getExercises, getApps, getPlaygroundAppName, extractNumbersAndTypeFromAppNameOrPath, getAppFromFile, getAppByName, isProblemApp, isPlaygroundApp, isExerciseStepApp, getExercise, isSolutionApp, isExampleApp, getRelativePath as getRelativePath$1, workshopRoot, modifiedTimes, getForceFreshForDir, setPlayground, requireExerciseApp, requireExercise, getExerciseApp, getAppDisplayName, getNextExerciseApp, getPrevExerciseApp, getAppPageRoute } from "@epic-web/workshop-utils/apps.server";
|
|
8
|
+
import { makeSingletonCache, cachified, deleteCache, compiledCodeCache, diffFilesCache, diffCodeCache, shouldForceFresh, fsCache, getAllFileCacheEntries, ogCache } from "@epic-web/workshop-utils/cache.server";
|
|
12
9
|
import { getWorkshopConfig } from "@epic-web/workshop-utils/config.server";
|
|
10
|
+
import { getAuthInfo, getPreferences, readOnboardingData, requireAuthInfo, PlayerPreferencesSchema, setPlayerPreferences, deleteDb, setPresencePreferences, setAuthInfo, markOnboardingVideoWatched } from "@epic-web/workshop-utils/db.server";
|
|
11
|
+
import { getUserInfo, userHasAccessToWorkshop, getProgress, updateProgress, getEpicVideoInfos } from "@epic-web/workshop-utils/epic-api.server";
|
|
12
|
+
import { getUserId, getSetClientIdCookieHeader } from "@epic-web/workshop-utils/user.server";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import { getApps, getExercises, getPlaygroundAppName, extractNumbersAndTypeFromAppNameOrPath, getAppFromFile, getAppByName, isProblemApp, isPlaygroundApp, isExerciseStepApp, getExercise, isSolutionApp, isExampleApp, getRelativePath as getRelativePath$1, workshopRoot, modifiedTimes, getForceFreshForDir, setPlayground, requireExerciseApp, requireExercise, getExerciseApp, getAppDisplayName, getNextExerciseApp, getPrevExerciseApp, getAppPageRoute, getWorkshopFinished, getWorkshopInstructions } from "@epic-web/workshop-utils/apps.server";
|
|
13
15
|
import { getEnv } from "@epic-web/workshop-utils/env.server";
|
|
14
16
|
import { makeTimings, getServerTimeHeader, combineServerTimings, time } from "@epic-web/workshop-utils/timing.server";
|
|
15
17
|
import { cssBundleHref } from "@remix-run/css-bundle";
|
|
@@ -20,7 +22,7 @@ import { ClientOnly } from "remix-utils/client-only";
|
|
|
20
22
|
import slugify from "@sindresorhus/slugify";
|
|
21
23
|
import clsx$1, { clsx } from "clsx";
|
|
22
24
|
import * as React from "react";
|
|
23
|
-
import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, useSyncExternalStore, forwardRef, useImperativeHandle, Suspense, useReducer } from "react";
|
|
25
|
+
import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, useCallback, useSyncExternalStore, forwardRef, useImperativeHandle, Suspense, useReducer } from "react";
|
|
24
26
|
import { extendTailwindMerge } from "tailwind-merge";
|
|
25
27
|
import { Toaster, toast } from "sonner";
|
|
26
28
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
@@ -33,14 +35,13 @@ import { clientHint as clientHint$1 } from "@epic-web/client-hints/time-zone";
|
|
|
33
35
|
import { safeRedirect } from "remix-utils/safe-redirect";
|
|
34
36
|
import { ServerOnly } from "remix-utils/server-only";
|
|
35
37
|
import * as cookie from "cookie";
|
|
36
|
-
import cookie__default from "cookie";
|
|
37
|
-
import md5 from "md5-hex";
|
|
38
|
-
import { createId } from "@paralleldrive/cuid2";
|
|
39
38
|
import { usePartySocket } from "partysocket/react";
|
|
39
|
+
import { createId } from "@paralleldrive/cuid2";
|
|
40
40
|
import { motion, useAnimationControls } from "framer-motion";
|
|
41
41
|
import { useHydrated } from "remix-utils/use-hydrated";
|
|
42
42
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
43
43
|
import { invariantResponse, invariant } from "@epic-web/invariant";
|
|
44
|
+
import RealMuxPlayer, { MinResolution, MaxResolution } from "@mux/mux-player-react";
|
|
44
45
|
import path$1 from "path";
|
|
45
46
|
import etag from "etag";
|
|
46
47
|
import fsExtra from "fs-extra";
|
|
@@ -49,7 +50,6 @@ import fs from "fs";
|
|
|
49
50
|
import { getDirModifiedTime, modifiedMoreRecentlyThan } from "@epic-web/workshop-utils/modified-time.server";
|
|
50
51
|
import * as esbuild from "esbuild";
|
|
51
52
|
import { ElementScrollRestoration } from "@epic-web/restore-scroll";
|
|
52
|
-
import RealMuxPlayer from "@mux/mux-player-react";
|
|
53
53
|
import child_process from "child_process";
|
|
54
54
|
import os from "os";
|
|
55
55
|
import shellQuote from "shell-quote";
|
|
@@ -74,6 +74,7 @@ import { useEventSource } from "remix-utils/sse/react";
|
|
|
74
74
|
import { eventStream } from "remix-utils/sse/server";
|
|
75
75
|
import { EventEmitter } from "events";
|
|
76
76
|
import { remember } from "@epic-web/remember";
|
|
77
|
+
import md5 from "md5-hex";
|
|
77
78
|
import { Issuer } from "openid-client";
|
|
78
79
|
import inspector from "node:inspector";
|
|
79
80
|
import { getCommitInfo, getLatestWorkshopAppVersion } from "@epic-web/workshop-utils/git.server";
|
|
@@ -148,15 +149,18 @@ const MessageSchema = z.object({
|
|
|
148
149
|
);
|
|
149
150
|
const PresenceSchema = z.object({ users: z.array(UserSchema) });
|
|
150
151
|
const presenceCache = makeSingletonCache("PresenceCache");
|
|
151
|
-
async function getPresentUsers(
|
|
152
|
-
|
|
152
|
+
async function getPresentUsers({
|
|
153
|
+
timings,
|
|
154
|
+
request
|
|
155
|
+
} = {}) {
|
|
156
|
+
const presence = await cachified({
|
|
153
157
|
key: "presence",
|
|
154
158
|
cache: presenceCache,
|
|
155
159
|
timings,
|
|
156
160
|
request,
|
|
157
|
-
ttl: 1e3 *
|
|
161
|
+
ttl: 1e3 * 2,
|
|
158
162
|
swr: 1e3 * 60 * 60 * 24,
|
|
159
|
-
checkValue:
|
|
163
|
+
checkValue: PresenceSchema,
|
|
160
164
|
async getFreshValue(context) {
|
|
161
165
|
try {
|
|
162
166
|
const response = await Promise.race([
|
|
@@ -175,20 +179,53 @@ async function getPresentUsers(user, { timings, request } = {}) {
|
|
|
175
179
|
`Unexpected response from partykit: ${response.status} ${response.statusText}`
|
|
176
180
|
);
|
|
177
181
|
}
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
const users = presence.users;
|
|
181
|
-
if ((preferences == null ? void 0 : preferences.presence.optOut) ?? !user) {
|
|
182
|
-
return uniqueUsers(users.filter((u) => u.id !== (user == null ? void 0 : user.id)));
|
|
183
|
-
} else {
|
|
184
|
-
return uniqueUsers([...users, user]);
|
|
185
|
-
}
|
|
182
|
+
const presence2 = PresenceSchema.parse(await response.json());
|
|
183
|
+
return presence2;
|
|
186
184
|
} catch {
|
|
187
185
|
context.metadata.ttl = 300;
|
|
188
|
-
return [];
|
|
186
|
+
return { users: [] };
|
|
189
187
|
}
|
|
190
188
|
}
|
|
191
189
|
});
|
|
190
|
+
const { users } = presence;
|
|
191
|
+
const authInfo = await getAuthInfo();
|
|
192
|
+
const userId = request ? (await getUserId({ request })).id : (authInfo == null ? void 0 : authInfo.id) ?? null;
|
|
193
|
+
const preferences = await getPreferences();
|
|
194
|
+
if ((preferences == null ? void 0 : preferences.presence.optOut) || !userId) {
|
|
195
|
+
return uniqueUsers(users.filter((u) => u.id !== userId));
|
|
196
|
+
} else {
|
|
197
|
+
const user = { id: userId };
|
|
198
|
+
const config = getWorkshopConfig();
|
|
199
|
+
const url = request ? new URL(request.url) : void 0;
|
|
200
|
+
user.location = {
|
|
201
|
+
workshopTitle: config.title,
|
|
202
|
+
origin: url ? url.origin : void 0
|
|
203
|
+
};
|
|
204
|
+
if (url) {
|
|
205
|
+
if (url.pathname.startsWith("/exercise/")) {
|
|
206
|
+
const [exerciseNumber, stepNumber, type] = url.pathname.split("/").slice(2);
|
|
207
|
+
user.location.exercise = {
|
|
208
|
+
exerciseNumber: isNaN(Number(exerciseNumber)) ? null : Number(exerciseNumber),
|
|
209
|
+
stepNumber: isNaN(Number(stepNumber)) ? null : Number(stepNumber),
|
|
210
|
+
type: type === "problem" ? "problem" : type === "solution" ? "solution" : null
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (authInfo) {
|
|
215
|
+
const [userInfo, hasAccess] = await Promise.all([
|
|
216
|
+
getUserInfo({ request, timings }),
|
|
217
|
+
userHasAccessToWorkshop({ request, timings })
|
|
218
|
+
]);
|
|
219
|
+
Object.assign(user, {
|
|
220
|
+
name: userInfo == null ? void 0 : userInfo.name,
|
|
221
|
+
avatarUrl: userInfo == null ? void 0 : userInfo.imageUrlLarge,
|
|
222
|
+
imageUrlSmall: userInfo == null ? void 0 : userInfo.imageUrlSmall,
|
|
223
|
+
imageUrlLarge: userInfo == null ? void 0 : userInfo.imageUrlLarge,
|
|
224
|
+
hasAccess
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return uniqueUsers([...users, user]);
|
|
228
|
+
}
|
|
192
229
|
}
|
|
193
230
|
function uniqueUsers(users) {
|
|
194
231
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -903,495 +940,6 @@ function createConfettiHeaders(value = String(Date.now())) {
|
|
|
903
940
|
})
|
|
904
941
|
});
|
|
905
942
|
}
|
|
906
|
-
const Transcript = z.string().nullable().optional().transform((s) => s ?? "Transcripts not available");
|
|
907
|
-
const EpicVideoInfoSchema = z.object({
|
|
908
|
-
transcript: Transcript,
|
|
909
|
-
muxPlaybackId: z.string()
|
|
910
|
-
});
|
|
911
|
-
const EpicVideoRegionRestrictedErrorSchema = z.object({
|
|
912
|
-
requestCountry: z.string(),
|
|
913
|
-
restrictedCountry: z.string(),
|
|
914
|
-
isRegionRestricted: z.literal(true)
|
|
915
|
-
});
|
|
916
|
-
const CachedEpicVideoInfoSchema = z.object({
|
|
917
|
-
transcript: Transcript,
|
|
918
|
-
muxPlaybackId: z.string(),
|
|
919
|
-
status: z.literal("success"),
|
|
920
|
-
statusCode: z.number(),
|
|
921
|
-
statusText: z.string()
|
|
922
|
-
}).or(
|
|
923
|
-
z.object({
|
|
924
|
-
status: z.literal("error"),
|
|
925
|
-
statusCode: z.number(),
|
|
926
|
-
statusText: z.string(),
|
|
927
|
-
type: z.literal("unknown")
|
|
928
|
-
})
|
|
929
|
-
).or(
|
|
930
|
-
z.object({
|
|
931
|
-
status: z.literal("error"),
|
|
932
|
-
statusCode: z.number(),
|
|
933
|
-
statusText: z.string(),
|
|
934
|
-
type: z.literal("region-restricted"),
|
|
935
|
-
requestCountry: z.string(),
|
|
936
|
-
restrictedCountry: z.string()
|
|
937
|
-
})
|
|
938
|
-
).or(z.null());
|
|
939
|
-
async function getEpicVideoInfos(epicWebUrls, { request, timings } = {}) {
|
|
940
|
-
if (!epicWebUrls) return {};
|
|
941
|
-
const authInfo = await getAuthInfo();
|
|
942
|
-
if (ENV.EPICSHOP_DEPLOYED) return {};
|
|
943
|
-
const epicVideoInfos = {};
|
|
944
|
-
for (const epicVideoEmbed of epicWebUrls) {
|
|
945
|
-
const epicVideoInfo = await getEpicVideoInfo({
|
|
946
|
-
epicVideoEmbed,
|
|
947
|
-
accessToken: authInfo == null ? void 0 : authInfo.tokenSet.access_token,
|
|
948
|
-
request,
|
|
949
|
-
timings
|
|
950
|
-
});
|
|
951
|
-
if (epicVideoInfo) {
|
|
952
|
-
epicVideoInfos[epicVideoEmbed] = epicVideoInfo;
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
return epicVideoInfos;
|
|
956
|
-
}
|
|
957
|
-
async function getEpicVideoInfo({
|
|
958
|
-
epicVideoEmbed,
|
|
959
|
-
accessToken,
|
|
960
|
-
request,
|
|
961
|
-
timings
|
|
962
|
-
}) {
|
|
963
|
-
const tokenPortion = accessToken ? md5(accessToken) : "unauthenticated";
|
|
964
|
-
const key = `epic-video-info:${tokenPortion}:${epicVideoEmbed}`;
|
|
965
|
-
return cachified({
|
|
966
|
-
key,
|
|
967
|
-
request,
|
|
968
|
-
cache: fsCache,
|
|
969
|
-
timings,
|
|
970
|
-
ttl: 1e3 * 60 * 60,
|
|
971
|
-
swr: 1e3 * 60 * 60 * 24 * 30,
|
|
972
|
-
checkValue: CachedEpicVideoInfoSchema,
|
|
973
|
-
async getFreshValue(context) {
|
|
974
|
-
const epicUrl = new URL(epicVideoEmbed);
|
|
975
|
-
if (epicUrl.host !== "www.epicweb.dev" && epicUrl.host !== "www.epicreact.dev") {
|
|
976
|
-
return null;
|
|
977
|
-
}
|
|
978
|
-
if (epicUrl.pathname.startsWith("/tutorials/")) {
|
|
979
|
-
epicUrl.pathname = epicUrl.pathname.replace(
|
|
980
|
-
/^\/tutorials\//,
|
|
981
|
-
"/workshops/"
|
|
982
|
-
);
|
|
983
|
-
}
|
|
984
|
-
const infoResponse = await fetch(
|
|
985
|
-
`https://${epicUrl.host}/api${epicUrl.pathname}`,
|
|
986
|
-
accessToken ? { headers: { authorization: `Bearer ${accessToken}` } } : void 0
|
|
987
|
-
);
|
|
988
|
-
const { status, statusText } = infoResponse;
|
|
989
|
-
if (infoResponse.status >= 200 && infoResponse.status < 300) {
|
|
990
|
-
const rawInfo = await infoResponse.json();
|
|
991
|
-
const infoResult = EpicVideoInfoSchema.safeParse(rawInfo);
|
|
992
|
-
if (infoResult.success) {
|
|
993
|
-
return {
|
|
994
|
-
status: "success",
|
|
995
|
-
statusCode: status,
|
|
996
|
-
statusText,
|
|
997
|
-
...infoResult.data
|
|
998
|
-
};
|
|
999
|
-
} else {
|
|
1000
|
-
context.metadata.ttl = 1e3 * 2;
|
|
1001
|
-
context.metadata.swr = 0;
|
|
1002
|
-
const restrictedResult = EpicVideoRegionRestrictedErrorSchema.safeParse(rawInfo);
|
|
1003
|
-
if (restrictedResult.success) {
|
|
1004
|
-
return {
|
|
1005
|
-
status: "error",
|
|
1006
|
-
statusCode: status,
|
|
1007
|
-
statusText,
|
|
1008
|
-
type: "region-restricted",
|
|
1009
|
-
...restrictedResult.data
|
|
1010
|
-
};
|
|
1011
|
-
} else {
|
|
1012
|
-
console.warn(
|
|
1013
|
-
`Response from EpicWeb for "${epicUrl.pathname}" does not match expectation`,
|
|
1014
|
-
infoResult.error
|
|
1015
|
-
);
|
|
1016
|
-
return {
|
|
1017
|
-
status: "error",
|
|
1018
|
-
statusCode: 500,
|
|
1019
|
-
statusText: "API Data Type Mismatch",
|
|
1020
|
-
type: "unknown"
|
|
1021
|
-
};
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
} else {
|
|
1025
|
-
context.metadata.ttl = 1e3 * 2;
|
|
1026
|
-
context.metadata.swr = 0;
|
|
1027
|
-
return {
|
|
1028
|
-
status: "error",
|
|
1029
|
-
statusCode: status,
|
|
1030
|
-
statusText,
|
|
1031
|
-
type: "unknown"
|
|
1032
|
-
};
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
}).catch((e) => {
|
|
1036
|
-
console.error(`Failed to fetch epic video info for ${epicVideoEmbed}`, e);
|
|
1037
|
-
throw e;
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
async function getEpicProgress({
|
|
1041
|
-
timings,
|
|
1042
|
-
request,
|
|
1043
|
-
forceFresh
|
|
1044
|
-
} = {}) {
|
|
1045
|
-
if (ENV.EPICSHOP_DEPLOYED) return [];
|
|
1046
|
-
const authInfo = await getAuthInfo();
|
|
1047
|
-
const {
|
|
1048
|
-
product: { host }
|
|
1049
|
-
} = getWorkshopConfig();
|
|
1050
|
-
if (!authInfo) return [];
|
|
1051
|
-
const tokenPart = md5(authInfo.tokenSet.access_token);
|
|
1052
|
-
const EpicProgressSchema = z.array(
|
|
1053
|
-
z.object({
|
|
1054
|
-
lessonId: z.string(),
|
|
1055
|
-
completedAt: z.string().nullable()
|
|
1056
|
-
})
|
|
1057
|
-
);
|
|
1058
|
-
return cachified({
|
|
1059
|
-
key: `epic-progress:${host}:${tokenPart}`,
|
|
1060
|
-
cache: fsCache,
|
|
1061
|
-
request,
|
|
1062
|
-
timings,
|
|
1063
|
-
forceFresh,
|
|
1064
|
-
ttl: 1e3 * 2,
|
|
1065
|
-
swr: 1e3 * 60 * 60 * 24 * 30,
|
|
1066
|
-
checkValue: EpicProgressSchema,
|
|
1067
|
-
async getFreshValue(context) {
|
|
1068
|
-
const response = await fetch(`https://${host}/api/progress`, {
|
|
1069
|
-
headers: {
|
|
1070
|
-
authorization: `Bearer ${authInfo.tokenSet.access_token}`
|
|
1071
|
-
}
|
|
1072
|
-
}).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
|
|
1073
|
-
if (response.status < 200 || response.status >= 300) {
|
|
1074
|
-
console.error(
|
|
1075
|
-
`Failed to fetch progress from EpicWeb: ${response.status} ${response.statusText}`
|
|
1076
|
-
);
|
|
1077
|
-
context.metadata.ttl = 1e3 * 2;
|
|
1078
|
-
context.metadata.swr = 0;
|
|
1079
|
-
return [];
|
|
1080
|
-
}
|
|
1081
|
-
return EpicProgressSchema.parse(await response.json());
|
|
1082
|
-
}
|
|
1083
|
-
});
|
|
1084
|
-
}
|
|
1085
|
-
async function getProgress({
|
|
1086
|
-
timings,
|
|
1087
|
-
request
|
|
1088
|
-
} = {}) {
|
|
1089
|
-
if (ENV.EPICSHOP_DEPLOYED) return [];
|
|
1090
|
-
const authInfo = await getAuthInfo();
|
|
1091
|
-
if (!authInfo) return [];
|
|
1092
|
-
const {
|
|
1093
|
-
product: { slug, host }
|
|
1094
|
-
} = getWorkshopConfig();
|
|
1095
|
-
if (!slug) return [];
|
|
1096
|
-
const [
|
|
1097
|
-
workshopData,
|
|
1098
|
-
epicProgress,
|
|
1099
|
-
workshopInstructions,
|
|
1100
|
-
workshopFinished,
|
|
1101
|
-
exercises
|
|
1102
|
-
] = await Promise.all([
|
|
1103
|
-
getWorkshopData(slug, { request, timings }),
|
|
1104
|
-
getEpicProgress({ request, timings }),
|
|
1105
|
-
getWorkshopInstructions({ request }),
|
|
1106
|
-
getWorkshopFinished({ request }),
|
|
1107
|
-
getExercises({ request, timings })
|
|
1108
|
-
]);
|
|
1109
|
-
const progress = [];
|
|
1110
|
-
for (const resource of workshopData.resources) {
|
|
1111
|
-
const lessons = resource._type === "section" ? resource.lessons : [resource];
|
|
1112
|
-
for (const lesson of lessons) {
|
|
1113
|
-
const epicLessonSlug = lesson.slug;
|
|
1114
|
-
const lessonProgress = epicProgress.find(
|
|
1115
|
-
({ lessonId }) => lessonId === lesson._id
|
|
1116
|
-
);
|
|
1117
|
-
const epicCompletedAt = lessonProgress ? lessonProgress.completedAt : null;
|
|
1118
|
-
const progressForLesson = getProgressForLesson(epicLessonSlug, {
|
|
1119
|
-
workshopInstructions,
|
|
1120
|
-
workshopFinished,
|
|
1121
|
-
exercises
|
|
1122
|
-
});
|
|
1123
|
-
const epicLessonUrl = `https://${host}/workshops/${slug}/${epicLessonSlug}`;
|
|
1124
|
-
if (progressForLesson) {
|
|
1125
|
-
progress.push({
|
|
1126
|
-
...progressForLesson,
|
|
1127
|
-
epicLessonUrl,
|
|
1128
|
-
epicLessonSlug,
|
|
1129
|
-
epicCompletedAt
|
|
1130
|
-
});
|
|
1131
|
-
} else {
|
|
1132
|
-
progress.push({
|
|
1133
|
-
type: "unknown",
|
|
1134
|
-
epicLessonUrl,
|
|
1135
|
-
epicLessonSlug,
|
|
1136
|
-
epicCompletedAt
|
|
1137
|
-
});
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
return progress;
|
|
1142
|
-
}
|
|
1143
|
-
function getProgressForLesson(epicLessonSlug, {
|
|
1144
|
-
workshopInstructions,
|
|
1145
|
-
workshopFinished,
|
|
1146
|
-
exercises
|
|
1147
|
-
}) {
|
|
1148
|
-
var _a;
|
|
1149
|
-
const hasEmbed = (embed) => embed == null ? void 0 : embed.some((e) => e.split("/").at(-1) === epicLessonSlug);
|
|
1150
|
-
if (workshopInstructions.compiled.status === "success" && hasEmbed(workshopInstructions.compiled.epicVideoEmbeds)) {
|
|
1151
|
-
return { type: "workshop-instructions" };
|
|
1152
|
-
}
|
|
1153
|
-
if (workshopFinished.compiled.status === "success" && hasEmbed(workshopFinished.compiled.epicVideoEmbeds)) {
|
|
1154
|
-
return { type: "workshop-finished" };
|
|
1155
|
-
}
|
|
1156
|
-
for (const exercise of exercises) {
|
|
1157
|
-
if (hasEmbed(exercise.instructionsEpicVideoEmbeds)) {
|
|
1158
|
-
return {
|
|
1159
|
-
type: "instructions",
|
|
1160
|
-
exerciseNumber: exercise.exerciseNumber
|
|
1161
|
-
};
|
|
1162
|
-
}
|
|
1163
|
-
if (hasEmbed(exercise.finishedEpicVideoEmbeds)) {
|
|
1164
|
-
return {
|
|
1165
|
-
type: "finished",
|
|
1166
|
-
exerciseNumber: exercise.exerciseNumber
|
|
1167
|
-
};
|
|
1168
|
-
}
|
|
1169
|
-
for (const step of exercise.steps.filter(Boolean)) {
|
|
1170
|
-
if (hasEmbed((_a = step.problem) == null ? void 0 : _a.epicVideoEmbeds)) {
|
|
1171
|
-
return {
|
|
1172
|
-
type: "step",
|
|
1173
|
-
exerciseNumber: exercise.exerciseNumber,
|
|
1174
|
-
stepNumber: step.stepNumber
|
|
1175
|
-
};
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
async function updateProgress({ lessonSlug, complete }, {
|
|
1181
|
-
timings,
|
|
1182
|
-
request
|
|
1183
|
-
} = {}) {
|
|
1184
|
-
if (ENV.EPICSHOP_DEPLOYED) {
|
|
1185
|
-
return {
|
|
1186
|
-
status: "error",
|
|
1187
|
-
error: "cannot update progress when deployed"
|
|
1188
|
-
};
|
|
1189
|
-
}
|
|
1190
|
-
const authInfo = await getAuthInfo();
|
|
1191
|
-
if (!authInfo) {
|
|
1192
|
-
return { status: "error", error: "not authenticated" };
|
|
1193
|
-
}
|
|
1194
|
-
const {
|
|
1195
|
-
product: { host }
|
|
1196
|
-
} = getWorkshopConfig();
|
|
1197
|
-
const response = await fetch(`https://${host}/api/progress`, {
|
|
1198
|
-
method: "POST",
|
|
1199
|
-
headers: {
|
|
1200
|
-
authorization: `Bearer ${authInfo.tokenSet.access_token}`,
|
|
1201
|
-
"content-type": "application/json"
|
|
1202
|
-
},
|
|
1203
|
-
body: JSON.stringify(
|
|
1204
|
-
complete ? { lessonSlug } : { lessonSlug, remove: true }
|
|
1205
|
-
)
|
|
1206
|
-
}).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
|
|
1207
|
-
await getEpicProgress({ forceFresh: true, request, timings });
|
|
1208
|
-
if (response.status < 200 || response.status >= 300) {
|
|
1209
|
-
return {
|
|
1210
|
-
status: "error",
|
|
1211
|
-
error: `${response.status} ${response.statusText}`
|
|
1212
|
-
};
|
|
1213
|
-
}
|
|
1214
|
-
return { status: "success" };
|
|
1215
|
-
}
|
|
1216
|
-
const ModuleSchema = z.object({
|
|
1217
|
-
resources: z.array(
|
|
1218
|
-
z.union([
|
|
1219
|
-
z.object({
|
|
1220
|
-
_type: z.literal("lesson"),
|
|
1221
|
-
_id: z.string(),
|
|
1222
|
-
slug: z.string()
|
|
1223
|
-
}),
|
|
1224
|
-
z.object({
|
|
1225
|
-
_type: z.literal("section"),
|
|
1226
|
-
lessons: z.array(z.object({ _id: z.string(), slug: z.string() }))
|
|
1227
|
-
})
|
|
1228
|
-
])
|
|
1229
|
-
)
|
|
1230
|
-
});
|
|
1231
|
-
async function getWorkshopData(slug, {
|
|
1232
|
-
timings,
|
|
1233
|
-
request,
|
|
1234
|
-
forceFresh
|
|
1235
|
-
} = {}) {
|
|
1236
|
-
if (ENV.EPICSHOP_DEPLOYED) return { resources: [] };
|
|
1237
|
-
const authInfo = await getAuthInfo();
|
|
1238
|
-
if (!authInfo) return { resources: [] };
|
|
1239
|
-
const {
|
|
1240
|
-
product: { host }
|
|
1241
|
-
} = getWorkshopConfig();
|
|
1242
|
-
return cachified({
|
|
1243
|
-
key: `epic-workshop-data:${host}:${slug}`,
|
|
1244
|
-
cache: fsCache,
|
|
1245
|
-
request,
|
|
1246
|
-
forceFresh,
|
|
1247
|
-
timings,
|
|
1248
|
-
checkValue: ModuleSchema,
|
|
1249
|
-
async getFreshValue() {
|
|
1250
|
-
const response = await fetch(
|
|
1251
|
-
`https://${host}/api/workshops/${encodeURIComponent(slug)}`
|
|
1252
|
-
).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
|
|
1253
|
-
if (response.status < 200 || response.status >= 300) {
|
|
1254
|
-
console.error(
|
|
1255
|
-
`Failed to fetch workshop data from EpicWeb for ${slug}: ${response.status} ${response.statusText}`
|
|
1256
|
-
);
|
|
1257
|
-
return { resources: [] };
|
|
1258
|
-
}
|
|
1259
|
-
return ModuleSchema.parse(await response.json());
|
|
1260
|
-
}
|
|
1261
|
-
});
|
|
1262
|
-
}
|
|
1263
|
-
async function userHasAccessToWorkshop({
|
|
1264
|
-
timings,
|
|
1265
|
-
request,
|
|
1266
|
-
forceFresh
|
|
1267
|
-
}) {
|
|
1268
|
-
var _a;
|
|
1269
|
-
const config = getWorkshopConfig();
|
|
1270
|
-
const {
|
|
1271
|
-
product: { host, slug }
|
|
1272
|
-
} = config;
|
|
1273
|
-
if (!slug) return true;
|
|
1274
|
-
if (ENV.EPICSHOP_DEPLOYED) {
|
|
1275
|
-
const cookieHeader = request.headers.get("Cookie");
|
|
1276
|
-
if (!cookieHeader) return false;
|
|
1277
|
-
const cookies = cookie__default.parse(cookieHeader);
|
|
1278
|
-
return ((_a = cookies.skill) == null ? void 0 : _a.split(",").includes(slug)) ?? false;
|
|
1279
|
-
}
|
|
1280
|
-
const authInfo = await getAuthInfo();
|
|
1281
|
-
if (!authInfo) return false;
|
|
1282
|
-
return cachified({
|
|
1283
|
-
key: `user-has-access-to-workshop:${host}:${slug}`,
|
|
1284
|
-
cache: fsCache,
|
|
1285
|
-
request,
|
|
1286
|
-
forceFresh,
|
|
1287
|
-
timings,
|
|
1288
|
-
ttl: 1e3 * 5,
|
|
1289
|
-
checkValue: z.boolean(),
|
|
1290
|
-
async getFreshValue(context) {
|
|
1291
|
-
const response = await fetch(
|
|
1292
|
-
`https://${host}/api/workshops/${encodeURIComponent(slug)}/access`,
|
|
1293
|
-
{
|
|
1294
|
-
headers: {
|
|
1295
|
-
authorization: `Bearer ${authInfo.tokenSet.access_token}`
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
|
|
1299
|
-
const hasAccess = response.ok ? await response.json() === true : false;
|
|
1300
|
-
if (hasAccess) {
|
|
1301
|
-
context.metadata.ttl = 1e3 * 60 * 60 * 24 * 30;
|
|
1302
|
-
context.metadata.swr = 1e3 * 60 * 60 * 24 * 30;
|
|
1303
|
-
}
|
|
1304
|
-
return hasAccess;
|
|
1305
|
-
}
|
|
1306
|
-
});
|
|
1307
|
-
}
|
|
1308
|
-
const UserInfoSchema = z.object({
|
|
1309
|
-
id: z.string(),
|
|
1310
|
-
name: z.string().nullable(),
|
|
1311
|
-
email: z.string().email(),
|
|
1312
|
-
image: z.string().nullable(),
|
|
1313
|
-
discordProfile: z.object({
|
|
1314
|
-
nick: z.string().nullable(),
|
|
1315
|
-
user: z.object({
|
|
1316
|
-
id: z.string(),
|
|
1317
|
-
username: z.string(),
|
|
1318
|
-
avatar: z.string().nullable().optional(),
|
|
1319
|
-
global_name: z.string().nullable().optional()
|
|
1320
|
-
})
|
|
1321
|
-
}).nullable().optional()
|
|
1322
|
-
}).transform((data) => {
|
|
1323
|
-
var _a, _b;
|
|
1324
|
-
return {
|
|
1325
|
-
...data,
|
|
1326
|
-
imageUrlSmall: resizeImageUrl(data.image, { size: 64 }) ?? resolveDiscordAvatar((_a = data.discordProfile) == null ? void 0 : _a.user, {
|
|
1327
|
-
size: 64
|
|
1328
|
-
}) ?? resolveGravatarUrl(data.email, { size: 64 }),
|
|
1329
|
-
imageUrlLarge: resizeImageUrl(data.image, { size: 512 }) ?? resolveDiscordAvatar((_b = data.discordProfile) == null ? void 0 : _b.user, {
|
|
1330
|
-
size: 512
|
|
1331
|
-
}) ?? resolveGravatarUrl(data.email, { size: 512 })
|
|
1332
|
-
};
|
|
1333
|
-
});
|
|
1334
|
-
function resizeImageUrl(url, { size }) {
|
|
1335
|
-
if (!url) return null;
|
|
1336
|
-
const urlObj = new URL(url);
|
|
1337
|
-
urlObj.searchParams.set("size", size.toString());
|
|
1338
|
-
return urlObj.toString();
|
|
1339
|
-
}
|
|
1340
|
-
function resolveGravatarUrl(email, { size }) {
|
|
1341
|
-
if (!email) return null;
|
|
1342
|
-
const hash = md5(email.toLowerCase());
|
|
1343
|
-
const gravatarOptions = new URLSearchParams({
|
|
1344
|
-
size: size.toString(),
|
|
1345
|
-
default: "identicon"
|
|
1346
|
-
});
|
|
1347
|
-
return `https://www.gravatar.com/avatar/${hash}?${gravatarOptions.toString()}`;
|
|
1348
|
-
}
|
|
1349
|
-
function resolveDiscordAvatar(user, { size }) {
|
|
1350
|
-
if (!user) return null;
|
|
1351
|
-
const { avatar, id: userId } = user;
|
|
1352
|
-
if (!avatar) return null;
|
|
1353
|
-
const isGif = avatar.startsWith("a_");
|
|
1354
|
-
const url = new URL(
|
|
1355
|
-
`/avatars/${userId}/${avatar}.${isGif ? "gif" : "png"}`,
|
|
1356
|
-
"https://cdn.discordapp.com"
|
|
1357
|
-
);
|
|
1358
|
-
url.searchParams.set("size", size.toString());
|
|
1359
|
-
return url.toString();
|
|
1360
|
-
}
|
|
1361
|
-
async function getUserInfo({
|
|
1362
|
-
timings,
|
|
1363
|
-
request,
|
|
1364
|
-
forceFresh
|
|
1365
|
-
} = {}) {
|
|
1366
|
-
const authInfo = await getAuthInfo();
|
|
1367
|
-
if (!authInfo) return null;
|
|
1368
|
-
const { tokenSet } = authInfo;
|
|
1369
|
-
const {
|
|
1370
|
-
product: { host }
|
|
1371
|
-
} = getWorkshopConfig();
|
|
1372
|
-
const accessToken = tokenSet.access_token;
|
|
1373
|
-
const url = `https://${host}/oauth/userinfo`;
|
|
1374
|
-
return cachified({
|
|
1375
|
-
key: `${url}:${md5(accessToken)}`,
|
|
1376
|
-
cache: fsCache,
|
|
1377
|
-
request,
|
|
1378
|
-
forceFresh,
|
|
1379
|
-
timings,
|
|
1380
|
-
ttl: 1e3 * 60 * 1,
|
|
1381
|
-
swr: 1e3 * 60 * 60 * 24 * 365,
|
|
1382
|
-
checkValue: UserInfoSchema,
|
|
1383
|
-
async getFreshValue() {
|
|
1384
|
-
const response = await fetch(url, {
|
|
1385
|
-
headers: { authorization: `Bearer ${accessToken}` }
|
|
1386
|
-
});
|
|
1387
|
-
if (!response.ok) {
|
|
1388
|
-
throw new Error(`Failed to fetch user info: ${response.statusText}`);
|
|
1389
|
-
}
|
|
1390
|
-
const data = await response.json();
|
|
1391
|
-
return UserInfoSchema.parse(data);
|
|
1392
|
-
}
|
|
1393
|
-
});
|
|
1394
|
-
}
|
|
1395
943
|
const PresenceContext = createContext(null);
|
|
1396
944
|
function usePresencePreferences() {
|
|
1397
945
|
var _a;
|
|
@@ -1407,35 +955,51 @@ const ExerciseAppParamsSchema = z.object({
|
|
|
1407
955
|
exerciseNumber: z.coerce.number().finite(),
|
|
1408
956
|
stepNumber: z.coerce.number().finite().optional()
|
|
1409
957
|
});
|
|
958
|
+
function useFirstCallDelayedCallback(cb, delay) {
|
|
959
|
+
const [timedPromise] = useState(
|
|
960
|
+
() => new Promise((resolve) => setTimeout(resolve, delay))
|
|
961
|
+
);
|
|
962
|
+
const mounted = useRef(true);
|
|
963
|
+
const currentCallRef = useRef(null);
|
|
964
|
+
const lastCbRef = useRef(cb);
|
|
965
|
+
useEffect(() => {
|
|
966
|
+
lastCbRef.current = cb;
|
|
967
|
+
}, [cb]);
|
|
968
|
+
const delayedCb = useCallback(
|
|
969
|
+
(...args) => {
|
|
970
|
+
const thisOne = Symbol();
|
|
971
|
+
currentCallRef.current = thisOne;
|
|
972
|
+
void timedPromise.then(() => {
|
|
973
|
+
if (!mounted.current) return;
|
|
974
|
+
if (currentCallRef.current !== thisOne) {
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
lastCbRef.current(...args);
|
|
978
|
+
});
|
|
979
|
+
},
|
|
980
|
+
[timedPromise]
|
|
981
|
+
);
|
|
982
|
+
return delayedCb;
|
|
983
|
+
}
|
|
1410
984
|
function usePresenceSocket(user) {
|
|
1411
985
|
const workshopTitle = useOptionalWorkshopTitle();
|
|
1412
|
-
const { userHasAccess = false } = useRouteLoaderData("root") ?? {};
|
|
986
|
+
const { userHasAccess = false, userId } = useRouteLoaderData("root") ?? {};
|
|
1413
987
|
const requestInfo = useRequestInfo();
|
|
1414
988
|
const rawParams = useParams();
|
|
1415
989
|
const prefs = usePresencePreferences();
|
|
1416
990
|
const data = useRouteLoaderData("root");
|
|
1417
991
|
const [users, setUsers] = useState((data == null ? void 0 : data.presence.users) ?? []);
|
|
1418
|
-
const
|
|
1419
|
-
|
|
1420
|
-
if (
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
return newClientId;
|
|
1426
|
-
});
|
|
992
|
+
const handleMessage = useFirstCallDelayedCallback((evt) => {
|
|
993
|
+
const messageResult = MessageSchema.safeParse(JSON.parse(String(evt.data)));
|
|
994
|
+
if (!messageResult.success) return;
|
|
995
|
+
if (messageResult.data.type === "presence") {
|
|
996
|
+
setUsers(messageResult.data.payload.users);
|
|
997
|
+
}
|
|
998
|
+
}, 2e3);
|
|
1427
999
|
const socket = usePartySocket({
|
|
1428
1000
|
host: new URL(partykitBaseUrl).host,
|
|
1429
1001
|
room: partykitRoom,
|
|
1430
|
-
onMessage
|
|
1431
|
-
const messageResult = MessageSchema.safeParse(
|
|
1432
|
-
JSON.parse(String(evt.data))
|
|
1433
|
-
);
|
|
1434
|
-
if (!messageResult.success) return;
|
|
1435
|
-
if (messageResult.data.type === "presence") {
|
|
1436
|
-
setUsers(messageResult.data.payload.users);
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1002
|
+
onMessage: handleMessage
|
|
1439
1003
|
});
|
|
1440
1004
|
const paramsResult = ExerciseAppParamsSchema.safeParse(rawParams);
|
|
1441
1005
|
const params = paramsResult.success ? paramsResult.data : null;
|
|
@@ -1451,54 +1015,58 @@ function usePresenceSocket(user) {
|
|
|
1451
1015
|
} : null
|
|
1452
1016
|
};
|
|
1453
1017
|
let message = null;
|
|
1454
|
-
if (
|
|
1455
|
-
if (
|
|
1018
|
+
if (user) {
|
|
1019
|
+
if (prefs == null ? void 0 : prefs.optOut) {
|
|
1456
1020
|
message = { type: "remove-user", payload: { id: user.id } };
|
|
1021
|
+
} else {
|
|
1022
|
+
message = {
|
|
1023
|
+
type: "add-user",
|
|
1024
|
+
payload: {
|
|
1025
|
+
id: user.id,
|
|
1026
|
+
name: user.name,
|
|
1027
|
+
hasAccess: userHasAccess,
|
|
1028
|
+
imageUrlSmall: user.imageUrlSmall,
|
|
1029
|
+
imageUrlLarge: user.imageUrlLarge,
|
|
1030
|
+
location
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1457
1033
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
message = {
|
|
1461
|
-
type: "add-user",
|
|
1462
|
-
payload: {
|
|
1463
|
-
id: user.id,
|
|
1464
|
-
name: user.name,
|
|
1465
|
-
hasAccess: userHasAccess,
|
|
1466
|
-
imageUrlSmall: user.imageUrlSmall,
|
|
1467
|
-
imageUrlLarge: user.imageUrlLarge,
|
|
1468
|
-
location
|
|
1469
|
-
}
|
|
1470
|
-
};
|
|
1034
|
+
} else if (userId == null ? void 0 : userId.id) {
|
|
1035
|
+
message = { type: "add-user", payload: { id: userId.id, location } };
|
|
1471
1036
|
}
|
|
1472
1037
|
const messageJson = message ? JSON.stringify(message) : null;
|
|
1473
1038
|
useEffect(() => {
|
|
1474
1039
|
if (messageJson) socket.send(messageJson);
|
|
1475
1040
|
}, [messageJson, socket]);
|
|
1476
|
-
const scoredUsers = scoreUsers(location, users);
|
|
1041
|
+
const scoredUsers = scoreUsers({ id: userId == null ? void 0 : userId.id, location }, users);
|
|
1477
1042
|
return { users: scoredUsers };
|
|
1478
1043
|
}
|
|
1479
|
-
function scoreUsers(
|
|
1480
|
-
const
|
|
1044
|
+
function scoreUsers(user, users) {
|
|
1045
|
+
const { location } = user;
|
|
1046
|
+
const scoredUsers = users.map((user2) => {
|
|
1481
1047
|
var _a, _b, _c, _d;
|
|
1482
1048
|
let score = 0;
|
|
1483
1049
|
const available = 5;
|
|
1484
|
-
if (
|
|
1050
|
+
if (user2.hasAccess) {
|
|
1485
1051
|
score += 1;
|
|
1486
1052
|
}
|
|
1487
|
-
if ((location == null ? void 0 : location.workshopTitle) === ((_a =
|
|
1053
|
+
if ((location == null ? void 0 : location.workshopTitle) === ((_a = user2.location) == null ? void 0 : _a.workshopTitle)) {
|
|
1488
1054
|
score += 1;
|
|
1489
|
-
if (((_b = location == null ? void 0 : location.exercise) == null ? void 0 : _b.exerciseNumber) && location.exercise.exerciseNumber === ((_d = (_c =
|
|
1055
|
+
if (((_b = location == null ? void 0 : location.exercise) == null ? void 0 : _b.exerciseNumber) && location.exercise.exerciseNumber === ((_d = (_c = user2.location) == null ? void 0 : _c.exercise) == null ? void 0 : _d.exerciseNumber)) {
|
|
1490
1056
|
score += 1;
|
|
1491
|
-
if (location.exercise.stepNumber && location.exercise.stepNumber ===
|
|
1057
|
+
if (location.exercise.stepNumber && location.exercise.stepNumber === user2.location.exercise.stepNumber) {
|
|
1492
1058
|
score += 1;
|
|
1493
|
-
if (location.exercise.type && location.exercise.type ===
|
|
1059
|
+
if (location.exercise.type && location.exercise.type === user2.location.exercise.type) {
|
|
1494
1060
|
score += 1;
|
|
1495
1061
|
}
|
|
1496
1062
|
}
|
|
1497
1063
|
}
|
|
1498
1064
|
}
|
|
1499
|
-
return { user, score: Math.floor(score / available * 10) / 10 };
|
|
1065
|
+
return { user: user2, score: Math.floor(score / available * 10) / 10 };
|
|
1500
1066
|
});
|
|
1501
1067
|
return scoredUsers.sort((a, b) => {
|
|
1068
|
+
if (a.user.id === (user == null ? void 0 : user.id)) return -1;
|
|
1069
|
+
if (b.user.id === (user == null ? void 0 : user.id)) return 1;
|
|
1502
1070
|
if (a.score === b.score) return 0;
|
|
1503
1071
|
return a.score > b.score ? -1 : 1;
|
|
1504
1072
|
});
|
|
@@ -1622,6 +1190,7 @@ const meta$6 = ({ data: data2 }) => {
|
|
|
1622
1190
|
});
|
|
1623
1191
|
};
|
|
1624
1192
|
async function loader$x({ request }) {
|
|
1193
|
+
var _a;
|
|
1625
1194
|
const timings = makeTimings("rootLoader");
|
|
1626
1195
|
const workshopConfig = getWorkshopConfig();
|
|
1627
1196
|
const {
|
|
@@ -1640,6 +1209,7 @@ async function loader$x({ request }) {
|
|
|
1640
1209
|
const { confettiId, headers: confettiHeaders } = getConfetti(request);
|
|
1641
1210
|
const { toast: toast2, headers: toastHeaders } = await getToast(request);
|
|
1642
1211
|
const asyncStuff = await promiseHash({
|
|
1212
|
+
userId: getUserId({ request }),
|
|
1643
1213
|
preferences: getPreferences(),
|
|
1644
1214
|
progress: getProgress({ timings }).catch((e) => {
|
|
1645
1215
|
console.error("Failed to get progress", e);
|
|
@@ -1650,7 +1220,7 @@ async function loader$x({ request }) {
|
|
|
1650
1220
|
userHasAccess: userHasAccessToWorkshop({ request, timings }),
|
|
1651
1221
|
apps: getApps({ request, timings })
|
|
1652
1222
|
});
|
|
1653
|
-
const presentUsers = await getPresentUsers(
|
|
1223
|
+
const presentUsers = await getPresentUsers({
|
|
1654
1224
|
request,
|
|
1655
1225
|
timings
|
|
1656
1226
|
});
|
|
@@ -1685,19 +1255,15 @@ async function loader$x({ request }) {
|
|
|
1685
1255
|
}
|
|
1686
1256
|
},
|
|
1687
1257
|
{
|
|
1688
|
-
headers: combineHeaders(
|
|
1689
|
-
|
|
1690
|
-
|
|
1258
|
+
headers: combineHeaders(
|
|
1259
|
+
toastHeaders,
|
|
1260
|
+
confettiHeaders,
|
|
1261
|
+
{ "Server-Timing": timings.toString() },
|
|
1262
|
+
((_a = asyncStuff.userId) == null ? void 0 : _a.type) === "cookie.randomId" ? { "Set-Cookie": getSetClientIdCookieHeader(asyncStuff.userId.id) } : void 0
|
|
1263
|
+
)
|
|
1691
1264
|
}
|
|
1692
1265
|
);
|
|
1693
1266
|
}
|
|
1694
|
-
const headers$c = ({ loaderHeaders }) => {
|
|
1695
|
-
const headers2 = {
|
|
1696
|
-
"Cache-Control": loaderHeaders.get("Cache-Control") ?? "",
|
|
1697
|
-
"Server-Timing": loaderHeaders.get("Server-Timing") ?? ""
|
|
1698
|
-
};
|
|
1699
|
-
return headers2;
|
|
1700
|
-
};
|
|
1701
1267
|
function Document({
|
|
1702
1268
|
children,
|
|
1703
1269
|
env = {},
|
|
@@ -1765,7 +1331,6 @@ const route0 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
1765
1331
|
__proto__: null,
|
|
1766
1332
|
ErrorBoundary: ErrorBoundary$6,
|
|
1767
1333
|
default: AppWithProviders,
|
|
1768
|
-
headers: headers$c,
|
|
1769
1334
|
links,
|
|
1770
1335
|
loader: loader$x,
|
|
1771
1336
|
meta: meta$6
|
|
@@ -2359,7 +1924,7 @@ const route38 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
2359
1924
|
useRequireEpicProgress
|
|
2360
1925
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2361
1926
|
async function loader$v({ request }) {
|
|
2362
|
-
var _a;
|
|
1927
|
+
var _a, _b;
|
|
2363
1928
|
const timings = makeTimings("appLayoutLoader");
|
|
2364
1929
|
const { title: workshopTitle } = getWorkshopConfig();
|
|
2365
1930
|
const [exercises, playgroundAppName] = await Promise.all([
|
|
@@ -2394,7 +1959,8 @@ async function loader$v({ request }) {
|
|
|
2394
1959
|
name: (problem == null ? void 0 : problem.name) ?? (solution == null ? void 0 : solution.name) ?? "Unknown"
|
|
2395
1960
|
}))
|
|
2396
1961
|
})),
|
|
2397
|
-
playground
|
|
1962
|
+
playground,
|
|
1963
|
+
isMenuOpened: ((_b = request.headers.get("cookie")) == null ? void 0 : _b.includes("es_menu_open=true")) ?? false
|
|
2398
1964
|
},
|
|
2399
1965
|
{
|
|
2400
1966
|
headers: {
|
|
@@ -2540,11 +2106,16 @@ function FacePile({ isMenuOpened }) {
|
|
|
2540
2106
|
}
|
|
2541
2107
|
const useIsWide = makeMediaQueryStore("(min-width: 640px)", true);
|
|
2542
2108
|
function App() {
|
|
2109
|
+
const data2 = useLoaderData();
|
|
2543
2110
|
const user = useOptionalUser();
|
|
2544
2111
|
const isWide = useIsWide();
|
|
2545
2112
|
const isHydrated = useHydrated();
|
|
2546
|
-
const [isMenuOpened,
|
|
2113
|
+
const [isMenuOpened, setMenuOpenedState] = React.useState(data2.isMenuOpened);
|
|
2547
2114
|
useRevalidationWS({ watchPaths: ["./exercises/README.mdx"] });
|
|
2115
|
+
function setMenuOpened(value) {
|
|
2116
|
+
setMenuOpenedState(value);
|
|
2117
|
+
document.cookie = `es_menu_open=${value.toString()}; path=/; SameSite=Lax;`;
|
|
2118
|
+
}
|
|
2548
2119
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
2549
2120
|
user ? null : /* @__PURE__ */ jsx(NoUserBanner, {}),
|
|
2550
2121
|
isHydrated && isWide ? null : /* @__PURE__ */ jsx(
|
|
@@ -2599,6 +2170,7 @@ function NoUserBanner() {
|
|
|
2599
2170
|
const {
|
|
2600
2171
|
product: { host, displayName }
|
|
2601
2172
|
} = useWorkshopConfig();
|
|
2173
|
+
const userHasAccess = useUserHasAccess();
|
|
2602
2174
|
const details = /* @__PURE__ */ jsx("div", { children: ENV.EPICSHOP_DEPLOYED ? /* @__PURE__ */ jsxs("div", { children: [
|
|
2603
2175
|
`This is the deployed version. `,
|
|
2604
2176
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -2646,7 +2218,7 @@ function NoUserBanner() {
|
|
|
2646
2218
|
details
|
|
2647
2219
|
] })
|
|
2648
2220
|
] }),
|
|
2649
|
-
/* @__PURE__ */ jsxs("div", { className: "hidden h-full flex-col items-center sm:flex md:flex-row", children: [
|
|
2221
|
+
userHasAccess ? null : /* @__PURE__ */ jsxs("div", { className: "hidden h-full flex-col items-center sm:flex md:flex-row", children: [
|
|
2650
2222
|
/* @__PURE__ */ jsxs(
|
|
2651
2223
|
Link,
|
|
2652
2224
|
{
|
|
@@ -3353,6 +2925,7 @@ function NavToggle({
|
|
|
3353
2925
|
setMenuOpened,
|
|
3354
2926
|
menuControls
|
|
3355
2927
|
}) {
|
|
2928
|
+
const initialOpenRef = React.useRef(isMenuOpened);
|
|
3356
2929
|
const menuButtonRef = React.useRef(null);
|
|
3357
2930
|
const path01Variants = {
|
|
3358
2931
|
open: { d: "M3.06061 2.99999L21.0606 21" },
|
|
@@ -3410,7 +2983,7 @@ function NavToggle({
|
|
|
3410
2983
|
/* @__PURE__ */ jsx(
|
|
3411
2984
|
motion.path,
|
|
3412
2985
|
{
|
|
3413
|
-
...path01Variants.closed,
|
|
2986
|
+
...path01Variants[initialOpenRef.current ? "open" : "closed"],
|
|
3414
2987
|
animate: path01Controls,
|
|
3415
2988
|
transition: { duration: 0.2 },
|
|
3416
2989
|
stroke: "currentColor",
|
|
@@ -3420,7 +2993,7 @@ function NavToggle({
|
|
|
3420
2993
|
/* @__PURE__ */ jsx(
|
|
3421
2994
|
motion.path,
|
|
3422
2995
|
{
|
|
3423
|
-
...path02Variants.closed,
|
|
2996
|
+
...path02Variants[initialOpenRef.current ? "open" : "closed"],
|
|
3424
2997
|
animate: path02Controls,
|
|
3425
2998
|
transition: { duration: 0.2 },
|
|
3426
2999
|
stroke: "currentColor",
|
|
@@ -3514,6 +3087,228 @@ function ButtonLink({
|
|
|
3514
3087
|
}
|
|
3515
3088
|
) });
|
|
3516
3089
|
}
|
|
3090
|
+
const PlaybackTimeSchema = z.object({
|
|
3091
|
+
time: z.number(),
|
|
3092
|
+
expiresAt: z.string()
|
|
3093
|
+
}).transform((data2) => {
|
|
3094
|
+
return { time: Number(data2.time), expiresAt: new Date(data2.expiresAt) };
|
|
3095
|
+
});
|
|
3096
|
+
function usePlayerPreferences() {
|
|
3097
|
+
var _a;
|
|
3098
|
+
const data2 = useRouteLoaderData("root");
|
|
3099
|
+
return ((_a = data2 == null ? void 0 : data2.preferences) == null ? void 0 : _a.player) ?? null;
|
|
3100
|
+
}
|
|
3101
|
+
const ignoredInputs = [
|
|
3102
|
+
"INPUT",
|
|
3103
|
+
"SELECT",
|
|
3104
|
+
"BUTTON",
|
|
3105
|
+
"TEXTAREA",
|
|
3106
|
+
"MUX-PLAYER",
|
|
3107
|
+
"SUMMARY"
|
|
3108
|
+
];
|
|
3109
|
+
const ignoredRoles = ["button", "option", "combobox", "tab", "tablist"];
|
|
3110
|
+
function shouldIgnoreHotkey(el) {
|
|
3111
|
+
let current = el;
|
|
3112
|
+
while (current) {
|
|
3113
|
+
if (!(current instanceof HTMLElement)) return false;
|
|
3114
|
+
const isIgnored = ignoredInputs.includes(current.tagName) || ignoredRoles.includes(current.getAttribute("role") || "") || current.isContentEditable;
|
|
3115
|
+
if (isIgnored) return true;
|
|
3116
|
+
current = current.parentElement;
|
|
3117
|
+
}
|
|
3118
|
+
return false;
|
|
3119
|
+
}
|
|
3120
|
+
async function action$9({ request }) {
|
|
3121
|
+
const result = PlayerPreferencesSchema.safeParse(await request.json());
|
|
3122
|
+
if (!result.success) {
|
|
3123
|
+
return unstable_data$1({ status: "error", error: result.error.flatten() }, {
|
|
3124
|
+
status: 400
|
|
3125
|
+
});
|
|
3126
|
+
}
|
|
3127
|
+
await setPlayerPreferences(result.data);
|
|
3128
|
+
return { status: "success" };
|
|
3129
|
+
}
|
|
3130
|
+
function useLatest(value) {
|
|
3131
|
+
const ref = React.useRef(value);
|
|
3132
|
+
React.useEffect(() => {
|
|
3133
|
+
ref.current = value;
|
|
3134
|
+
}, [value]);
|
|
3135
|
+
return ref;
|
|
3136
|
+
}
|
|
3137
|
+
function MuxPlayer({
|
|
3138
|
+
muxPlayerRef,
|
|
3139
|
+
...props
|
|
3140
|
+
}) {
|
|
3141
|
+
const playerPreferences = usePlayerPreferences();
|
|
3142
|
+
const playerPreferencesFetcher = useFetcher();
|
|
3143
|
+
const [metadataLoaded, setMetadataLoaded] = React.useState(false);
|
|
3144
|
+
const currentTimeSessionKey = `${props.playbackId}:currentTime`;
|
|
3145
|
+
const [currentTime, setCurrentTime] = React.useState(0);
|
|
3146
|
+
const fetcherRef = useLatest(playerPreferencesFetcher);
|
|
3147
|
+
const playerPreferencesRef = useLatest(playerPreferences);
|
|
3148
|
+
React.useEffect(() => {
|
|
3149
|
+
if (typeof document === "undefined") return;
|
|
3150
|
+
const stored = sessionStorage.getItem(currentTimeSessionKey);
|
|
3151
|
+
if (!stored) return;
|
|
3152
|
+
try {
|
|
3153
|
+
const { time: time2, expiresAt } = PlaybackTimeSchema.parse(JSON.parse(stored));
|
|
3154
|
+
if (expiresAt.getTime() < Date.now()) throw new Error("Time expired");
|
|
3155
|
+
setCurrentTime(time2);
|
|
3156
|
+
} catch {
|
|
3157
|
+
sessionStorage.removeItem(currentTimeSessionKey);
|
|
3158
|
+
}
|
|
3159
|
+
}, [currentTimeSessionKey]);
|
|
3160
|
+
React.useEffect(() => {
|
|
3161
|
+
function handleUserKeyPress(e) {
|
|
3162
|
+
if (!muxPlayerRef.current) return;
|
|
3163
|
+
const activeElement = document.activeElement;
|
|
3164
|
+
if (shouldIgnoreHotkey(activeElement)) return;
|
|
3165
|
+
if (shouldIgnoreHotkey(e.target)) return;
|
|
3166
|
+
if (e.key === " ") {
|
|
3167
|
+
e.preventDefault();
|
|
3168
|
+
void (muxPlayerRef.current.paused ? muxPlayerRef.current.play() : muxPlayerRef.current.pause());
|
|
3169
|
+
}
|
|
3170
|
+
if (e.key === "ArrowRight") {
|
|
3171
|
+
e.preventDefault();
|
|
3172
|
+
muxPlayerRef.current.currentTime = muxPlayerRef.current.currentTime + (muxPlayerRef.current.forwardSeekOffset || 10);
|
|
3173
|
+
}
|
|
3174
|
+
if (e.key === "ArrowLeft") {
|
|
3175
|
+
e.preventDefault();
|
|
3176
|
+
muxPlayerRef.current.currentTime = muxPlayerRef.current.currentTime - (muxPlayerRef.current.forwardSeekOffset || 10);
|
|
3177
|
+
}
|
|
3178
|
+
if (e.key === "f" && !e.metaKey && !e.ctrlKey) {
|
|
3179
|
+
e.preventDefault();
|
|
3180
|
+
void (document.fullscreenElement ? document.exitFullscreen() : muxPlayerRef.current.requestFullscreen());
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
window.document.addEventListener("keydown", handleUserKeyPress);
|
|
3184
|
+
return () => {
|
|
3185
|
+
window.document.removeEventListener("keydown", handleUserKeyPress);
|
|
3186
|
+
};
|
|
3187
|
+
}, [muxPlayerRef]);
|
|
3188
|
+
const updatePreferences = useDebounce(() => {
|
|
3189
|
+
const player = muxPlayerRef.current;
|
|
3190
|
+
if (!player) return;
|
|
3191
|
+
const subs = Array.from(player.textTracks ?? []).find(
|
|
3192
|
+
(t) => t.kind === "subtitles"
|
|
3193
|
+
);
|
|
3194
|
+
const newPrefs = {
|
|
3195
|
+
playbackRate: player.playbackRate,
|
|
3196
|
+
volumeRate: player.volume,
|
|
3197
|
+
subtitle: subs ? { id: subs.id, mode: subs.mode } : { id: null, mode: "disabled" }
|
|
3198
|
+
};
|
|
3199
|
+
if (isDeepEqual(newPrefs, playerPreferencesRef.current)) return;
|
|
3200
|
+
fetcherRef.current.submit(newPrefs, {
|
|
3201
|
+
method: "POST",
|
|
3202
|
+
action: "/video-player",
|
|
3203
|
+
encType: "application/json"
|
|
3204
|
+
});
|
|
3205
|
+
}, 300);
|
|
3206
|
+
React.useEffect(() => {
|
|
3207
|
+
var _a, _b;
|
|
3208
|
+
if (!metadataLoaded) return;
|
|
3209
|
+
const textTracks = (_a = muxPlayerRef.current) == null ? void 0 : _a.textTracks;
|
|
3210
|
+
if (!textTracks) return;
|
|
3211
|
+
const subtitlePref = (_b = playerPreferencesRef.current) == null ? void 0 : _b.subtitle;
|
|
3212
|
+
if (subtitlePref == null ? void 0 : subtitlePref.id) {
|
|
3213
|
+
const preferredTextTrack = textTracks.getTrackById(subtitlePref.id);
|
|
3214
|
+
if (preferredTextTrack) {
|
|
3215
|
+
preferredTextTrack.mode = subtitlePref.mode ?? "hidden";
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
textTracks.addEventListener("change", updatePreferences);
|
|
3219
|
+
return () => {
|
|
3220
|
+
textTracks.removeEventListener("change", updatePreferences);
|
|
3221
|
+
};
|
|
3222
|
+
}, [metadataLoaded, muxPlayerRef, playerPreferencesRef, updatePreferences]);
|
|
3223
|
+
return /* @__PURE__ */ jsx("div", { className: "flex aspect-video flex-col", children: /* @__PURE__ */ jsx(
|
|
3224
|
+
RealMuxPlayer,
|
|
3225
|
+
{
|
|
3226
|
+
ref: muxPlayerRef,
|
|
3227
|
+
playbackRates: [
|
|
3228
|
+
0.5,
|
|
3229
|
+
0.75,
|
|
3230
|
+
1,
|
|
3231
|
+
1.25,
|
|
3232
|
+
1.5,
|
|
3233
|
+
1.75,
|
|
3234
|
+
2,
|
|
3235
|
+
2.5,
|
|
3236
|
+
3,
|
|
3237
|
+
3.5,
|
|
3238
|
+
// lol, someone really asked for this and I think it's funny so let's do it
|
|
3239
|
+
// https://twitter.com/zackerydev/status/1710840197879918840
|
|
3240
|
+
4
|
|
3241
|
+
],
|
|
3242
|
+
volume: (playerPreferences == null ? void 0 : playerPreferences.volumeRate) ?? 1,
|
|
3243
|
+
playbackRate: (playerPreferences == null ? void 0 : playerPreferences.playbackRate) ?? 1,
|
|
3244
|
+
thumbnailTime: currentTime,
|
|
3245
|
+
onRateChange: updatePreferences,
|
|
3246
|
+
onVolumeChange: updatePreferences,
|
|
3247
|
+
streamType: "on-demand",
|
|
3248
|
+
defaultHiddenCaptions: true,
|
|
3249
|
+
currentTime,
|
|
3250
|
+
onTimeUpdate: () => {
|
|
3251
|
+
var _a;
|
|
3252
|
+
return sessionStorage.setItem(
|
|
3253
|
+
currentTimeSessionKey,
|
|
3254
|
+
JSON.stringify({
|
|
3255
|
+
time: (_a = muxPlayerRef.current) == null ? void 0 : _a.currentTime,
|
|
3256
|
+
expiresAt: new Date(Date.now() + 1e3 * 60 * 30).toISOString()
|
|
3257
|
+
})
|
|
3258
|
+
);
|
|
3259
|
+
},
|
|
3260
|
+
accentColor: "#427cf0",
|
|
3261
|
+
targetLiveWindow: NaN,
|
|
3262
|
+
onLoadedMetadata: () => setMetadataLoaded(true),
|
|
3263
|
+
minResolution: getMinResolutionValue(playerPreferences == null ? void 0 : playerPreferences.minResolution),
|
|
3264
|
+
maxResolution: getMaxResolutionValue(playerPreferences == null ? void 0 : playerPreferences.maxResolution),
|
|
3265
|
+
...props
|
|
3266
|
+
}
|
|
3267
|
+
) });
|
|
3268
|
+
}
|
|
3269
|
+
function isDeepEqual(obj1, obj2) {
|
|
3270
|
+
if (obj1 === obj2) return true;
|
|
3271
|
+
if (typeof obj1 !== typeof obj2) return false;
|
|
3272
|
+
if (typeof obj1 !== "object" || typeof obj2 !== "object") return false;
|
|
3273
|
+
if (obj1 === null || obj2 === null) return false;
|
|
3274
|
+
if (Array.isArray(obj1) !== Array.isArray(obj2)) return false;
|
|
3275
|
+
if (Array.isArray(obj1) && Array.isArray(obj2)) {
|
|
3276
|
+
if (obj1.length !== obj2.length) return false;
|
|
3277
|
+
for (let i = 0; i < obj1.length; i++) {
|
|
3278
|
+
if (!isDeepEqual(obj1[i], obj2[i])) return false;
|
|
3279
|
+
}
|
|
3280
|
+
return true;
|
|
3281
|
+
}
|
|
3282
|
+
const keys1 = Object.keys(obj1);
|
|
3283
|
+
const keys2 = Object.keys(obj2);
|
|
3284
|
+
if (keys1.length !== keys2.length) return false;
|
|
3285
|
+
for (const key of keys1) {
|
|
3286
|
+
if (!isDeepEqual(obj1[key], obj2[key])) return false;
|
|
3287
|
+
}
|
|
3288
|
+
return true;
|
|
3289
|
+
}
|
|
3290
|
+
function getMinResolutionValue(resolution) {
|
|
3291
|
+
if (!resolution) return void 0;
|
|
3292
|
+
if (resolution <= 480) return MinResolution.noLessThan480p;
|
|
3293
|
+
if (resolution <= 540) return MinResolution.noLessThan540p;
|
|
3294
|
+
if (resolution <= 720) return MinResolution.noLessThan720p;
|
|
3295
|
+
if (resolution <= 1080) return MinResolution.noLessThan1080p;
|
|
3296
|
+
if (resolution <= 1440) return MinResolution.noLessThan1440p;
|
|
3297
|
+
return MinResolution.noLessThan2160p;
|
|
3298
|
+
}
|
|
3299
|
+
function getMaxResolutionValue(resolution) {
|
|
3300
|
+
if (!resolution) return void 0;
|
|
3301
|
+
if (resolution <= 720) return MaxResolution.upTo720p;
|
|
3302
|
+
if (resolution <= 1080) return MaxResolution.upTo1080p;
|
|
3303
|
+
if (resolution <= 1440) return MaxResolution.upTo1440p;
|
|
3304
|
+
return MaxResolution.upTo2160p;
|
|
3305
|
+
}
|
|
3306
|
+
const route45 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3307
|
+
__proto__: null,
|
|
3308
|
+
MuxPlayer,
|
|
3309
|
+
action: action$9,
|
|
3310
|
+
usePlayerPreferences
|
|
3311
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
3517
3312
|
const handle$9 = {
|
|
3518
3313
|
getSitemapEntries: () => null
|
|
3519
3314
|
};
|
|
@@ -3522,7 +3317,7 @@ async function loader$u({ request }) {
|
|
|
3522
3317
|
await requireAuthInfo({ request });
|
|
3523
3318
|
return {};
|
|
3524
3319
|
}
|
|
3525
|
-
async function action$
|
|
3320
|
+
async function action$8({ request }) {
|
|
3526
3321
|
ensureUndeployed();
|
|
3527
3322
|
const formData = await request.formData();
|
|
3528
3323
|
const intent = formData.get("intent");
|
|
@@ -3542,6 +3337,18 @@ async function action$9({ request }) {
|
|
|
3542
3337
|
description: `You are now ${optOut ? "invisible" : "visible"}.`,
|
|
3543
3338
|
type: "success"
|
|
3544
3339
|
});
|
|
3340
|
+
} else if (intent === "update-player-preferences") {
|
|
3341
|
+
const minResolution = formData.get("minResolution");
|
|
3342
|
+
const maxResolution = formData.get("maxResolution");
|
|
3343
|
+
await setPlayerPreferences({
|
|
3344
|
+
minResolution: minResolution ? Number(minResolution) : void 0,
|
|
3345
|
+
maxResolution: maxResolution ? Number(maxResolution) : void 0
|
|
3346
|
+
});
|
|
3347
|
+
return redirectWithToast("/account", {
|
|
3348
|
+
title: "Preferences updated",
|
|
3349
|
+
description: "Your video player preferences have been updated.",
|
|
3350
|
+
type: "success"
|
|
3351
|
+
});
|
|
3545
3352
|
}
|
|
3546
3353
|
return redirect$1("/account");
|
|
3547
3354
|
}
|
|
@@ -3555,7 +3362,10 @@ function Account() {
|
|
|
3555
3362
|
const user = useUser();
|
|
3556
3363
|
const discordMember = useOptionalDiscordMember();
|
|
3557
3364
|
const presencePreferences = usePresencePreferences();
|
|
3365
|
+
const playerPreferences = usePlayerPreferences();
|
|
3558
3366
|
const connectDiscordURL = useConnectDiscordURL$1();
|
|
3367
|
+
const navigation = useNavigation();
|
|
3368
|
+
const isSubmitting = navigation.state === "submitting";
|
|
3559
3369
|
return /* @__PURE__ */ jsxs("main", { className: "container flex h-full w-full max-w-3xl flex-grow flex-col items-center justify-center gap-4", children: [
|
|
3560
3370
|
user.imageUrlLarge ? /* @__PURE__ */ jsx(
|
|
3561
3371
|
"img",
|
|
@@ -3628,6 +3438,61 @@ function Account() {
|
|
|
3628
3438
|
}
|
|
3629
3439
|
)
|
|
3630
3440
|
] }),
|
|
3441
|
+
/* @__PURE__ */ jsx("hr", { className: "w-full" }),
|
|
3442
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
3443
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-2 text-xl", children: "Video Player Preferences" }),
|
|
3444
|
+
/* @__PURE__ */ jsxs(Form, { method: "post", className: "flex flex-col gap-4", children: [
|
|
3445
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3446
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "minResolution", children: "Minimum Resolution:" }),
|
|
3447
|
+
/* @__PURE__ */ jsxs(
|
|
3448
|
+
"select",
|
|
3449
|
+
{
|
|
3450
|
+
id: "minResolution",
|
|
3451
|
+
name: "minResolution",
|
|
3452
|
+
defaultValue: playerPreferences == null ? void 0 : playerPreferences.minResolution,
|
|
3453
|
+
children: [
|
|
3454
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Auto" }),
|
|
3455
|
+
/* @__PURE__ */ jsx("option", { value: "480", children: "480p" }),
|
|
3456
|
+
/* @__PURE__ */ jsx("option", { value: "720", children: "720p" }),
|
|
3457
|
+
/* @__PURE__ */ jsx("option", { value: "1080", children: "1080p" }),
|
|
3458
|
+
/* @__PURE__ */ jsx("option", { value: "1440", children: "1440p" }),
|
|
3459
|
+
/* @__PURE__ */ jsx("option", { value: "2160", children: "2160p (4K)" })
|
|
3460
|
+
]
|
|
3461
|
+
}
|
|
3462
|
+
)
|
|
3463
|
+
] }),
|
|
3464
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3465
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "maxResolution", children: "Maximum Resolution:" }),
|
|
3466
|
+
/* @__PURE__ */ jsxs(
|
|
3467
|
+
"select",
|
|
3468
|
+
{
|
|
3469
|
+
id: "maxResolution",
|
|
3470
|
+
name: "maxResolution",
|
|
3471
|
+
defaultValue: playerPreferences == null ? void 0 : playerPreferences.maxResolution,
|
|
3472
|
+
children: [
|
|
3473
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Auto" }),
|
|
3474
|
+
/* @__PURE__ */ jsx("option", { value: "720", children: "720p" }),
|
|
3475
|
+
/* @__PURE__ */ jsx("option", { value: "1080", children: "1080p" }),
|
|
3476
|
+
/* @__PURE__ */ jsx("option", { value: "1440", children: "1440p" }),
|
|
3477
|
+
/* @__PURE__ */ jsx("option", { value: "2160", children: "2160p (4K)" })
|
|
3478
|
+
]
|
|
3479
|
+
}
|
|
3480
|
+
)
|
|
3481
|
+
] }),
|
|
3482
|
+
/* @__PURE__ */ jsx(
|
|
3483
|
+
Button,
|
|
3484
|
+
{
|
|
3485
|
+
varient: "mono",
|
|
3486
|
+
type: "submit",
|
|
3487
|
+
name: "intent",
|
|
3488
|
+
value: "update-player-preferences",
|
|
3489
|
+
disabled: isSubmitting,
|
|
3490
|
+
children: isSubmitting ? "Updating..." : "Update Player Preferences"
|
|
3491
|
+
}
|
|
3492
|
+
)
|
|
3493
|
+
] })
|
|
3494
|
+
] }),
|
|
3495
|
+
/* @__PURE__ */ jsx("hr", { className: "w-full" }),
|
|
3631
3496
|
/* @__PURE__ */ jsxs("p", { children: [
|
|
3632
3497
|
"Check",
|
|
3633
3498
|
" ",
|
|
@@ -3646,7 +3511,7 @@ function Account() {
|
|
|
3646
3511
|
}
|
|
3647
3512
|
const route3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3648
3513
|
__proto__: null,
|
|
3649
|
-
action: action$
|
|
3514
|
+
action: action$8,
|
|
3650
3515
|
default: Account,
|
|
3651
3516
|
handle: handle$9,
|
|
3652
3517
|
loader: loader$u
|
|
@@ -3813,7 +3678,7 @@ async function loader$s(args) {
|
|
|
3813
3678
|
api.cleanupError(error);
|
|
3814
3679
|
}
|
|
3815
3680
|
}
|
|
3816
|
-
async function action$
|
|
3681
|
+
async function action$7(args) {
|
|
3817
3682
|
const api = await getApiModule(args);
|
|
3818
3683
|
invariantResponse(
|
|
3819
3684
|
api.mod.action,
|
|
@@ -3901,7 +3766,7 @@ async function getApiModule({ request, params }) {
|
|
|
3901
3766
|
}
|
|
3902
3767
|
const route5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3903
3768
|
__proto__: null,
|
|
3904
|
-
action: action$
|
|
3769
|
+
action: action$7,
|
|
3905
3770
|
loader: loader$s
|
|
3906
3771
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
3907
3772
|
async function loader$r({ request, params }) {
|
|
@@ -4353,210 +4218,6 @@ const route12 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
4353
4218
|
default: ExercisesLayout,
|
|
4354
4219
|
handle: handle$7
|
|
4355
4220
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
4356
|
-
const PlaybackTimeSchema = z.object({
|
|
4357
|
-
time: z.number(),
|
|
4358
|
-
expiresAt: z.string()
|
|
4359
|
-
}).transform((data2) => {
|
|
4360
|
-
return { time: Number(data2.time), expiresAt: new Date(data2.expiresAt) };
|
|
4361
|
-
});
|
|
4362
|
-
function usePlayerPreferences() {
|
|
4363
|
-
var _a;
|
|
4364
|
-
const data2 = useRouteLoaderData("root");
|
|
4365
|
-
return ((_a = data2 == null ? void 0 : data2.preferences) == null ? void 0 : _a.player) ?? null;
|
|
4366
|
-
}
|
|
4367
|
-
const ignoredInputs = [
|
|
4368
|
-
"INPUT",
|
|
4369
|
-
"SELECT",
|
|
4370
|
-
"BUTTON",
|
|
4371
|
-
"TEXTAREA",
|
|
4372
|
-
"MUX-PLAYER",
|
|
4373
|
-
"SUMMARY"
|
|
4374
|
-
];
|
|
4375
|
-
const ignoredRoles = ["button", "option", "combobox", "tab", "tablist"];
|
|
4376
|
-
function shouldIgnoreHotkey(el) {
|
|
4377
|
-
let current = el;
|
|
4378
|
-
while (current) {
|
|
4379
|
-
if (!(current instanceof HTMLElement)) return false;
|
|
4380
|
-
const isIgnored = ignoredInputs.includes(current.tagName) || ignoredRoles.includes(current.getAttribute("role") || "") || current.isContentEditable;
|
|
4381
|
-
if (isIgnored) return true;
|
|
4382
|
-
current = current.parentElement;
|
|
4383
|
-
}
|
|
4384
|
-
return false;
|
|
4385
|
-
}
|
|
4386
|
-
async function action$7({ request }) {
|
|
4387
|
-
const result = PlayerPreferencesSchema.safeParse(await request.json());
|
|
4388
|
-
if (!result.success) {
|
|
4389
|
-
return unstable_data$1({ status: "error", error: result.error.flatten() }, {
|
|
4390
|
-
status: 400
|
|
4391
|
-
});
|
|
4392
|
-
}
|
|
4393
|
-
await setPlayerPreferences(result.data);
|
|
4394
|
-
return { status: "success" };
|
|
4395
|
-
}
|
|
4396
|
-
function useLatest(value) {
|
|
4397
|
-
const ref = React.useRef(value);
|
|
4398
|
-
React.useEffect(() => {
|
|
4399
|
-
ref.current = value;
|
|
4400
|
-
}, [value]);
|
|
4401
|
-
return ref;
|
|
4402
|
-
}
|
|
4403
|
-
function MuxPlayer({
|
|
4404
|
-
muxPlayerRef,
|
|
4405
|
-
...props
|
|
4406
|
-
}) {
|
|
4407
|
-
const playerPreferences = usePlayerPreferences();
|
|
4408
|
-
const playerPreferencesFetcher = useFetcher();
|
|
4409
|
-
const [metadataLoaded, setMetadataLoaded] = React.useState(false);
|
|
4410
|
-
const currentTimeSessionKey = `${props.playbackId}:currentTime`;
|
|
4411
|
-
const [currentTime, setCurrentTime] = React.useState(0);
|
|
4412
|
-
const fetcherRef = useLatest(playerPreferencesFetcher);
|
|
4413
|
-
const playerPreferencesRef = useLatest(playerPreferences);
|
|
4414
|
-
React.useEffect(() => {
|
|
4415
|
-
if (typeof document === "undefined") return;
|
|
4416
|
-
const stored = sessionStorage.getItem(currentTimeSessionKey);
|
|
4417
|
-
if (!stored) return;
|
|
4418
|
-
try {
|
|
4419
|
-
const { time: time2, expiresAt } = PlaybackTimeSchema.parse(JSON.parse(stored));
|
|
4420
|
-
if (expiresAt.getTime() < Date.now()) throw new Error("Time expired");
|
|
4421
|
-
setCurrentTime(time2);
|
|
4422
|
-
} catch {
|
|
4423
|
-
sessionStorage.removeItem(currentTimeSessionKey);
|
|
4424
|
-
}
|
|
4425
|
-
}, [currentTimeSessionKey]);
|
|
4426
|
-
React.useEffect(() => {
|
|
4427
|
-
function handleUserKeyPress(e) {
|
|
4428
|
-
if (!muxPlayerRef.current) return;
|
|
4429
|
-
const activeElement = document.activeElement;
|
|
4430
|
-
if (shouldIgnoreHotkey(activeElement)) return;
|
|
4431
|
-
if (shouldIgnoreHotkey(e.target)) return;
|
|
4432
|
-
if (e.key === " ") {
|
|
4433
|
-
e.preventDefault();
|
|
4434
|
-
void (muxPlayerRef.current.paused ? muxPlayerRef.current.play() : muxPlayerRef.current.pause());
|
|
4435
|
-
}
|
|
4436
|
-
if (e.key === "ArrowRight") {
|
|
4437
|
-
e.preventDefault();
|
|
4438
|
-
muxPlayerRef.current.currentTime = muxPlayerRef.current.currentTime + (muxPlayerRef.current.forwardSeekOffset || 10);
|
|
4439
|
-
}
|
|
4440
|
-
if (e.key === "ArrowLeft") {
|
|
4441
|
-
e.preventDefault();
|
|
4442
|
-
muxPlayerRef.current.currentTime = muxPlayerRef.current.currentTime - (muxPlayerRef.current.forwardSeekOffset || 10);
|
|
4443
|
-
}
|
|
4444
|
-
if (e.key === "f" && !e.metaKey && !e.ctrlKey) {
|
|
4445
|
-
e.preventDefault();
|
|
4446
|
-
void (document.fullscreenElement ? document.exitFullscreen() : muxPlayerRef.current.requestFullscreen());
|
|
4447
|
-
}
|
|
4448
|
-
}
|
|
4449
|
-
window.document.addEventListener("keydown", handleUserKeyPress);
|
|
4450
|
-
return () => {
|
|
4451
|
-
window.document.removeEventListener("keydown", handleUserKeyPress);
|
|
4452
|
-
};
|
|
4453
|
-
}, [muxPlayerRef]);
|
|
4454
|
-
const updatePreferences = useDebounce(() => {
|
|
4455
|
-
const player = muxPlayerRef.current;
|
|
4456
|
-
if (!player) return;
|
|
4457
|
-
const subs = Array.from(player.textTracks ?? []).find(
|
|
4458
|
-
(t) => t.kind === "subtitles"
|
|
4459
|
-
);
|
|
4460
|
-
const newPrefs = {
|
|
4461
|
-
playbackRate: player.playbackRate,
|
|
4462
|
-
volumeRate: player.volume,
|
|
4463
|
-
subtitle: subs ? { id: subs.id, mode: subs.mode } : { id: null, mode: "disabled" }
|
|
4464
|
-
};
|
|
4465
|
-
if (isDeepEqual(newPrefs, playerPreferencesRef.current)) return;
|
|
4466
|
-
fetcherRef.current.submit(newPrefs, {
|
|
4467
|
-
method: "POST",
|
|
4468
|
-
action: "/video-player",
|
|
4469
|
-
encType: "application/json"
|
|
4470
|
-
});
|
|
4471
|
-
}, 300);
|
|
4472
|
-
React.useEffect(() => {
|
|
4473
|
-
var _a, _b;
|
|
4474
|
-
if (!metadataLoaded) return;
|
|
4475
|
-
const textTracks = (_a = muxPlayerRef.current) == null ? void 0 : _a.textTracks;
|
|
4476
|
-
if (!textTracks) return;
|
|
4477
|
-
const subtitlePref = (_b = playerPreferencesRef.current) == null ? void 0 : _b.subtitle;
|
|
4478
|
-
if (subtitlePref == null ? void 0 : subtitlePref.id) {
|
|
4479
|
-
const preferredTextTrack = textTracks.getTrackById(subtitlePref.id);
|
|
4480
|
-
if (preferredTextTrack) {
|
|
4481
|
-
preferredTextTrack.mode = subtitlePref.mode ?? "hidden";
|
|
4482
|
-
}
|
|
4483
|
-
}
|
|
4484
|
-
textTracks.addEventListener("change", updatePreferences);
|
|
4485
|
-
return () => {
|
|
4486
|
-
textTracks.removeEventListener("change", updatePreferences);
|
|
4487
|
-
};
|
|
4488
|
-
}, [metadataLoaded, muxPlayerRef, playerPreferencesRef, updatePreferences]);
|
|
4489
|
-
return /* @__PURE__ */ jsx("div", { className: "flex aspect-video flex-col", children: /* @__PURE__ */ jsx(
|
|
4490
|
-
RealMuxPlayer,
|
|
4491
|
-
{
|
|
4492
|
-
ref: muxPlayerRef,
|
|
4493
|
-
playbackRates: [
|
|
4494
|
-
0.5,
|
|
4495
|
-
0.75,
|
|
4496
|
-
1,
|
|
4497
|
-
1.25,
|
|
4498
|
-
1.5,
|
|
4499
|
-
1.75,
|
|
4500
|
-
2,
|
|
4501
|
-
2.5,
|
|
4502
|
-
3,
|
|
4503
|
-
3.5,
|
|
4504
|
-
// lol, someone really asked for this and I think it's funny so let's do it
|
|
4505
|
-
// https://twitter.com/zackerydev/status/1710840197879918840
|
|
4506
|
-
4
|
|
4507
|
-
],
|
|
4508
|
-
volume: (playerPreferences == null ? void 0 : playerPreferences.volumeRate) ?? 1,
|
|
4509
|
-
playbackRate: (playerPreferences == null ? void 0 : playerPreferences.playbackRate) ?? 1,
|
|
4510
|
-
thumbnailTime: currentTime,
|
|
4511
|
-
onRateChange: updatePreferences,
|
|
4512
|
-
onVolumeChange: updatePreferences,
|
|
4513
|
-
streamType: "on-demand",
|
|
4514
|
-
defaultHiddenCaptions: true,
|
|
4515
|
-
currentTime,
|
|
4516
|
-
onTimeUpdate: () => {
|
|
4517
|
-
var _a;
|
|
4518
|
-
return sessionStorage.setItem(
|
|
4519
|
-
currentTimeSessionKey,
|
|
4520
|
-
JSON.stringify({
|
|
4521
|
-
time: (_a = muxPlayerRef.current) == null ? void 0 : _a.currentTime,
|
|
4522
|
-
expiresAt: new Date(Date.now() + 1e3 * 60 * 30).toISOString()
|
|
4523
|
-
})
|
|
4524
|
-
);
|
|
4525
|
-
},
|
|
4526
|
-
accentColor: "#427cf0",
|
|
4527
|
-
targetLiveWindow: NaN,
|
|
4528
|
-
onLoadedMetadata: () => setMetadataLoaded(true),
|
|
4529
|
-
...props
|
|
4530
|
-
}
|
|
4531
|
-
) });
|
|
4532
|
-
}
|
|
4533
|
-
function isDeepEqual(obj1, obj2) {
|
|
4534
|
-
if (obj1 === obj2) return true;
|
|
4535
|
-
if (typeof obj1 !== typeof obj2) return false;
|
|
4536
|
-
if (typeof obj1 !== "object" || typeof obj2 !== "object") return false;
|
|
4537
|
-
if (obj1 === null || obj2 === null) return false;
|
|
4538
|
-
if (Array.isArray(obj1) !== Array.isArray(obj2)) return false;
|
|
4539
|
-
if (Array.isArray(obj1) && Array.isArray(obj2)) {
|
|
4540
|
-
if (obj1.length !== obj2.length) return false;
|
|
4541
|
-
for (let i = 0; i < obj1.length; i++) {
|
|
4542
|
-
if (!isDeepEqual(obj1[i], obj2[i])) return false;
|
|
4543
|
-
}
|
|
4544
|
-
return true;
|
|
4545
|
-
}
|
|
4546
|
-
const keys1 = Object.keys(obj1);
|
|
4547
|
-
const keys2 = Object.keys(obj2);
|
|
4548
|
-
if (keys1.length !== keys2.length) return false;
|
|
4549
|
-
for (const key of keys1) {
|
|
4550
|
-
if (!isDeepEqual(obj1[key], obj2[key])) return false;
|
|
4551
|
-
}
|
|
4552
|
-
return true;
|
|
4553
|
-
}
|
|
4554
|
-
const route45 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
4555
|
-
__proto__: null,
|
|
4556
|
-
MuxPlayer,
|
|
4557
|
-
action: action$7,
|
|
4558
|
-
usePlayerPreferences
|
|
4559
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
4560
4221
|
function Loading({
|
|
4561
4222
|
className,
|
|
4562
4223
|
children = "Loading"
|
|
@@ -10110,7 +9771,20 @@ async function registerDevice() {
|
|
|
10110
9771
|
return;
|
|
10111
9772
|
}
|
|
10112
9773
|
const userinfo = await client.userinfo(tokenSet);
|
|
10113
|
-
|
|
9774
|
+
let id;
|
|
9775
|
+
if (typeof userinfo.id === "string") {
|
|
9776
|
+
id = userinfo.id;
|
|
9777
|
+
} else {
|
|
9778
|
+
console.warn("[UNEXPECTED] User ID is not a string:", userinfo.id);
|
|
9779
|
+
id = userinfo.email ? md5(userinfo.email) : createId();
|
|
9780
|
+
}
|
|
9781
|
+
await setAuthInfo({
|
|
9782
|
+
id,
|
|
9783
|
+
tokenSet,
|
|
9784
|
+
email: userinfo.email,
|
|
9785
|
+
name: userinfo.name
|
|
9786
|
+
});
|
|
9787
|
+
await getUserInfo({ forceFresh: true });
|
|
10114
9788
|
authEmitter.emit(EVENTS.AUTH_RESOLVED);
|
|
10115
9789
|
} catch (error) {
|
|
10116
9790
|
authEmitter.emit(EVENTS.AUTH_REJECTED, {
|
|
@@ -11299,7 +10973,7 @@ const route41 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
11299
10973
|
__proto__: null,
|
|
11300
10974
|
loader
|
|
11301
10975
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
11302
|
-
const serverManifest = { "entry": { "module": "/assets/entry.client-DqIWuxf8.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/root-a3d3Qwip.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/index-C9Hx0Dey.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-Bdg3v8tC.js", "/assets/presence-DJGFvdDh.js", "/assets/seo-pBpFCWsy.js", "/assets/request-info-ByUEfOil.js"], "css": [] }, "routes/$": { "id": "routes/$", "parentId": "root", "path": "*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_-BrkpfnBb.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/_app+/_layout": { "id": "routes/_app+/_layout", "parentId": "root", "path": void 0, "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-Cbz7Qt-S.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/product-DIAmCwmZ.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-BCTr8uu6.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-DJGFvdDh.js", "/assets/progress-DQt_Bn9o.js", "/assets/index-Bdg3v8tC.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.js"], "css": [] }, "routes/_app+/account": { "id": "routes/_app+/account", "parentId": "routes/_app+/_layout", "path": "account", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/account-C4Piztoz.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-DJGFvdDh.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.js"], "css": [] }, "routes/_app+/app.$appName+/$": { "id": "routes/_app+/app.$appName+/$", "parentId": "routes/_app+/_layout", "path": "app/:appName/*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/api.$": { "id": "routes/_app+/app.$appName+/api.$", "parentId": "routes/_app+/_layout", "path": "app/:appName/api/*", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/api._-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/epic_ws[.js]": { "id": "routes/_app+/app.$appName+/epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/index": { "id": "routes/_app+/app.$appName+/index", "parentId": "routes/_app+/_layout", "path": "app/:appName/", "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.$testName": { "id": "routes/_app+/app.$appName+/test.$testName", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/:testName", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test._testName-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.epic_ws[.js]": { "id": "routes/_app+/app.$appName+/test.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.epic_ws[.js]": { "id": "routes/_app+/app.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/discord": { "id": "routes/_app+/discord", "parentId": "routes/_app+/_layout", "path": "discord", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-Bdnx7fu-.js", "imports": ["/assets/discord-BUWZUTEC.js", "/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js"], "css": [] }, "routes/_app+/exercise+/_layout": { "id": "routes/_app+/exercise+/_layout", "parentId": "routes/_app+/_layout", "path": "exercise", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-88n0To1b.js", "imports": ["/assets/index-BFGhCX_U.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber": { "id": "routes/_app+/exercise+/$exerciseNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber-DCSM0NCG.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/:stepNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber_._stepNumber-BIMJh_sg.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": ":type", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_layout-DTAM9xh5.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/set-playground-CBHBA46B.js", "/assets/seo-pBpFCWsy.js", "/assets/misc-DUy_whwE.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/tooltip-DO9uwurQ.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/index-BCTr8uu6.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/pe-ChIwTk8v.js", "/assets/index-DZDhtMuq.js", "/assets/index-Bdg3v8tC.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "app", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app-DgTXXO8s.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/preview-DaZd0wMb.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/request-info-ByUEfOil.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-Bi1TbRTj.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/loading-XhMtj4mp.js", "/assets/discord-BUWZUTEC.js", "/assets/components-Be92gVxW.js", "/assets/index-C9Hx0Dey.js", "/assets/set-playground-CBHBA46B.js", "/assets/tests-DbuyD2cI.js", "/assets/preview-DaZd0wMb.js", "/assets/index-BCTr8uu6.js", "/assets/accordion-D9-D-n9p.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-DoKJvNug.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tests-DbuyD2cI.js", "/assets/components-Be92gVxW.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/accordion-D9-D-n9p.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/set-playground-CBHBA46B.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_._stepNumber.index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.finished": { "id": "routes/_app+/exercise+/$exerciseNumber_.finished", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_.finished-nbpk1ToO.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/finished": { "id": "routes/_app+/finished", "parentId": "routes/_app+/_layout", "path": "finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/finished-C0cpfAFL.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/index": { "id": "routes/_app+/index", "parentId": "routes/_app+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-Ca4vBON4.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/login": { "id": "routes/_app+/login", "parentId": "routes/_app+/_layout", "path": "login", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-C1oOgi98.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/product-DIAmCwmZ.js", "/assets/workshop-config-WVltG_BV.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js"], "css": [] }, "routes/_app+/support": { "id": "routes/_app+/support", "parentId": "routes/_app+/_layout", "path": "support", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/support-CIz02V_r.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-Dfmv2zcn.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/admin+/apps": { "id": "routes/admin+/apps", "parentId": "routes/admin+/_layout", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/admin+/cache": { "id": "routes/admin+/cache", "parentId": "routes/admin+/_layout", "path": "cache", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/cache-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/admin+/index": { "id": "routes/admin+/index", "parentId": "routes/admin+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-pkiQppkK.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/pe-ChIwTk8v.js"], "css": [] }, "routes/admin+/version": { "id": "routes/admin+/version", "parentId": "routes/admin+/_layout", "path": "version", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/version-lxUUxt3s.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/workshop-config-WVltG_BV.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/apps": { "id": "routes/apps", "parentId": "root", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-DP2rzg_V.js", "imports": [], "css": [] }, "routes/diff": { "id": "routes/diff", "parentId": "root", "path": "diff", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/diff-BhRAIPKc.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/components-Be92gVxW.js", "/assets/accordion-D9-D-n9p.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/exercises": { "id": "routes/exercises", "parentId": "root", "path": "exercises", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/exercises-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/launch-editor": { "id": "routes/launch-editor", "parentId": "root", "path": "launch-editor", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/launch-editor-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/login-sse": { "id": "routes/login-sse", "parentId": "root", "path": "login-sse", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-sse-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/og": { "id": "routes/og", "parentId": "root", "path": "og", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/og-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/onboarding": { "id": "routes/onboarding", "parentId": "root", "path": "onboarding", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/onboarding-C2YNq60k.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/processes": { "id": "routes/processes", "parentId": "root", "path": "processes", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/processes-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/progress": { "id": "routes/progress", "parentId": "root", "path": "progress", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/progress-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/robots[.]txt": { "id": "routes/robots[.]txt", "parentId": "root", "path": "robots.txt", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/robots_._txt-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/set-playground": { "id": "routes/set-playground", "parentId": "root", "path": "set-playground", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/set-playground-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/sitemap[.]xml": { "id": "routes/sitemap[.]xml", "parentId": "root", "path": "sitemap.xml", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/sitemap_._xml-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/start": { "id": "routes/start", "parentId": "root", "path": "start", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/start-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/test": { "id": "routes/test", "parentId": "root", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/theme/index": { "id": "routes/theme/index", "parentId": "root", "path": "theme", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-DP2rzg_V.js", "imports": [], "css": [] }, "routes/video-player/index": { "id": "routes/video-player/index", "parentId": "root", "path": "video-player", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-K6Dvbx-E.js", "imports": [], "css": [] } }, "url": "/assets/manifest-e5b2a6e1.js", "version": "e5b2a6e1" };
|
|
10976
|
+
const serverManifest = { "entry": { "module": "/assets/entry.client-CrlHhRMR.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/components-DUNtf72c.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/root-Bg-hxaOK.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/components-DUNtf72c.js", "/assets/misc-DIdEn_jt.js", "/assets/pe-D5h19vSo.js", "/assets/error-boundary-3zItlMUO.js", "/assets/progress-bar-CBDBzRQ2.js", "/assets/index-LjRZeU7x.js", "/assets/tooltip-BoVikCa-.js", "/assets/index-DH1w3QmP.js", "/assets/presence-D1DPz__2.js", "/assets/seo-pBpFCWsy.js", "/assets/request-info-vBkaf3Rk.js"], "css": [] }, "routes/$": { "id": "routes/$", "parentId": "root", "path": "*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_-hAKYb2AG.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/error-boundary-3zItlMUO.js", "/assets/misc-DIdEn_jt.js", "/assets/components-DUNtf72c.js"], "css": [] }, "routes/_app+/_layout": { "id": "routes/_app+/_layout", "parentId": "root", "path": void 0, "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-Bu0lel3p.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/misc-DIdEn_jt.js", "/assets/pe-D5h19vSo.js", "/assets/product-CYOFfeJM.js", "/assets/revalidation-ws-DK5QOPlL.js", "/assets/tooltip-BoVikCa-.js", "/assets/index-CV3nxGFp.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js", "/assets/presence-D1DPz__2.js", "/assets/progress-D6SP0Gec.js", "/assets/index-DH1w3QmP.js", "/assets/components-DUNtf72c.js", "/assets/request-info-vBkaf3Rk.js"], "css": [] }, "routes/_app+/account": { "id": "routes/_app+/account", "parentId": "routes/_app+/_layout", "path": "account", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/account-DLDPrc9J.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/button-39zQyNX6.js", "/assets/misc-DIdEn_jt.js", "/assets/tooltip-BoVikCa-.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js", "/assets/presence-D1DPz__2.js", "/assets/index-BajUQsFT.js", "/assets/components-DUNtf72c.js", "/assets/request-info-vBkaf3Rk.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/_app+/app.$appName+/$": { "id": "routes/_app+/app.$appName+/$", "parentId": "routes/_app+/_layout", "path": "app/:appName/*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/api.$": { "id": "routes/_app+/app.$appName+/api.$", "parentId": "routes/_app+/_layout", "path": "app/:appName/api/*", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/api._-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/epic_ws[.js]": { "id": "routes/_app+/app.$appName+/epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/index": { "id": "routes/_app+/app.$appName+/index", "parentId": "routes/_app+/_layout", "path": "app/:appName/", "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.$testName": { "id": "routes/_app+/app.$appName+/test.$testName", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/:testName", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test._testName-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.epic_ws[.js]": { "id": "routes/_app+/app.$appName+/test.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.epic_ws[.js]": { "id": "routes/_app+/app.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/discord": { "id": "routes/_app+/discord", "parentId": "routes/_app+/_layout", "path": "discord", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-CpIgvYus.js", "imports": ["/assets/discord-CEOqKs_c.js", "/assets/index-C_B1-9rF.js", "/assets/misc-DIdEn_jt.js", "/assets/components-DUNtf72c.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js"], "css": [] }, "routes/_app+/exercise+/_layout": { "id": "routes/_app+/exercise+/_layout", "parentId": "routes/_app+/_layout", "path": "exercise", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-B4JGpA3A.js", "imports": ["/assets/index-C_B1-9rF.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber": { "id": "routes/_app+/exercise+/$exerciseNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber-PTdG9GGB.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/index-CLNXC84j.js", "/assets/epic-video-D8ex9vao.js", "/assets/revalidation-ws-DK5QOPlL.js", "/assets/mdx-C9dqA6IZ.js", "/assets/progress-D6SP0Gec.js", "/assets/misc-DIdEn_jt.js", "/assets/seo-pBpFCWsy.js", "/assets/components-DUNtf72c.js", "/assets/index-DH1w3QmP.js", "/assets/request-info-vBkaf3Rk.js", "/assets/tooltip-BoVikCa-.js", "/assets/pe-D5h19vSo.js", "/assets/index-BajUQsFT.js", "/assets/loading-DW_I206H.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js", "/assets/progress-bar-CBDBzRQ2.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/:stepNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber_._stepNumber-03erOIGo.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/misc-DIdEn_jt.js", "/assets/components-DUNtf72c.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": ":type", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_layout-DHoH74NH.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/index-CLNXC84j.js", "/assets/error-boundary-3zItlMUO.js", "/assets/nav-chevrons-B3SvZV8B.js", "/assets/revalidation-ws-DK5QOPlL.js", "/assets/mdx-C9dqA6IZ.js", "/assets/progress-D6SP0Gec.js", "/assets/set-playground-CMoUFgkO.js", "/assets/seo-pBpFCWsy.js", "/assets/misc-DIdEn_jt.js", "/assets/epic-video-D8ex9vao.js", "/assets/tooltip-BoVikCa-.js", "/assets/request-info-vBkaf3Rk.js", "/assets/components-DUNtf72c.js", "/assets/index-CV3nxGFp.js", "/assets/progress-bar-CBDBzRQ2.js", "/assets/pe-D5h19vSo.js", "/assets/index-DFqQCjCw.js", "/assets/index-DH1w3QmP.js", "/assets/index-BajUQsFT.js", "/assets/loading-DW_I206H.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "app", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app-DJDjmdlu.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/preview-BEtmdi0E.js", "/assets/components-DUNtf72c.js", "/assets/misc-DIdEn_jt.js", "/assets/request-info-vBkaf3Rk.js", "/assets/button-39zQyNX6.js", "/assets/loading-DW_I206H.js", "/assets/index-DH1w3QmP.js", "/assets/tooltip-BoVikCa-.js", "/assets/pe-D5h19vSo.js", "/assets/progress-bar-CBDBzRQ2.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-DE-jwnOP.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/tooltip-BoVikCa-.js", "/assets/index-DFqQCjCw.js", "/assets/misc-DIdEn_jt.js", "/assets/diff-BNCREJvf.js", "/assets/error-boundary-3zItlMUO.js", "/assets/loading-DW_I206H.js", "/assets/discord-CEOqKs_c.js", "/assets/components-DUNtf72c.js", "/assets/index-LjRZeU7x.js", "/assets/set-playground-CMoUFgkO.js", "/assets/tests-CiM4RPOf.js", "/assets/preview-BEtmdi0E.js", "/assets/index-CV3nxGFp.js", "/assets/accordion-DLg7gJkp.js", "/assets/mdx-C9dqA6IZ.js", "/assets/epic-video-D8ex9vao.js", "/assets/index-DH1w3QmP.js", "/assets/request-info-vBkaf3Rk.js", "/assets/pe-D5h19vSo.js", "/assets/index-BajUQsFT.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js", "/assets/progress-bar-CBDBzRQ2.js", "/assets/revalidation-ws-DK5QOPlL.js", "/assets/use-event-source-M87p8Tme.js", "/assets/button-39zQyNX6.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-C8wkLh9a.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/tests-CiM4RPOf.js", "/assets/components-DUNtf72c.js", "/assets/epic-video-D8ex9vao.js", "/assets/index-DH1w3QmP.js", "/assets/request-info-vBkaf3Rk.js", "/assets/misc-DIdEn_jt.js", "/assets/tooltip-BoVikCa-.js", "/assets/pe-D5h19vSo.js", "/assets/index-BajUQsFT.js", "/assets/loading-DW_I206H.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js", "/assets/accordion-DLg7gJkp.js", "/assets/index-DFqQCjCw.js", "/assets/index-CV3nxGFp.js", "/assets/use-event-source-M87p8Tme.js", "/assets/set-playground-CMoUFgkO.js", "/assets/progress-bar-CBDBzRQ2.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_._stepNumber.index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.finished": { "id": "routes/_app+/exercise+/$exerciseNumber_.finished", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_.finished-DQg4F1NL.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/index-CLNXC84j.js", "/assets/epic-video-D8ex9vao.js", "/assets/loading-DW_I206H.js", "/assets/nav-chevrons-B3SvZV8B.js", "/assets/revalidation-ws-DK5QOPlL.js", "/assets/mdx-C9dqA6IZ.js", "/assets/progress-D6SP0Gec.js", "/assets/misc-DIdEn_jt.js", "/assets/seo-pBpFCWsy.js", "/assets/components-DUNtf72c.js", "/assets/index-DH1w3QmP.js", "/assets/request-info-vBkaf3Rk.js", "/assets/tooltip-BoVikCa-.js", "/assets/pe-D5h19vSo.js", "/assets/index-BajUQsFT.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js", "/assets/progress-bar-CBDBzRQ2.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/_app+/finished": { "id": "routes/_app+/finished", "parentId": "routes/_app+/_layout", "path": "finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/finished-rUzUjnEm.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/index-CLNXC84j.js", "/assets/epic-video-D8ex9vao.js", "/assets/loading-DW_I206H.js", "/assets/nav-chevrons-B3SvZV8B.js", "/assets/revalidation-ws-DK5QOPlL.js", "/assets/mdx-C9dqA6IZ.js", "/assets/misc-DIdEn_jt.js", "/assets/seo-pBpFCWsy.js", "/assets/progress-D6SP0Gec.js", "/assets/components-DUNtf72c.js", "/assets/index-DH1w3QmP.js", "/assets/request-info-vBkaf3Rk.js", "/assets/tooltip-BoVikCa-.js", "/assets/pe-D5h19vSo.js", "/assets/index-BajUQsFT.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js", "/assets/progress-bar-CBDBzRQ2.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/_app+/index": { "id": "routes/_app+/index", "parentId": "routes/_app+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-mivnjq36.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/index-CLNXC84j.js", "/assets/epic-video-D8ex9vao.js", "/assets/error-boundary-3zItlMUO.js", "/assets/mdx-C9dqA6IZ.js", "/assets/misc-DIdEn_jt.js", "/assets/progress-D6SP0Gec.js", "/assets/components-DUNtf72c.js", "/assets/index-DH1w3QmP.js", "/assets/request-info-vBkaf3Rk.js", "/assets/tooltip-BoVikCa-.js", "/assets/pe-D5h19vSo.js", "/assets/index-BajUQsFT.js", "/assets/loading-DW_I206H.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js", "/assets/progress-bar-CBDBzRQ2.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/_app+/login": { "id": "routes/_app+/login", "parentId": "routes/_app+/_layout", "path": "login", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-CdNej0Z7.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/use-event-source-M87p8Tme.js", "/assets/button-39zQyNX6.js", "/assets/loading-DW_I206H.js", "/assets/product-CYOFfeJM.js", "/assets/workshop-config-C5sYl312.js", "/assets/request-info-vBkaf3Rk.js", "/assets/components-DUNtf72c.js", "/assets/misc-DIdEn_jt.js", "/assets/index-DH1w3QmP.js", "/assets/tooltip-BoVikCa-.js", "/assets/pe-D5h19vSo.js"], "css": [] }, "routes/_app+/support": { "id": "routes/_app+/support", "parentId": "routes/_app+/_layout", "path": "support", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/support-CPzYlWkd.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/components-DUNtf72c.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-BJbMl6SJ.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/components-DUNtf72c.js"], "css": [] }, "routes/admin+/apps": { "id": "routes/admin+/apps", "parentId": "routes/admin+/_layout", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/admin+/cache": { "id": "routes/admin+/cache", "parentId": "routes/admin+/_layout", "path": "cache", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/cache-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/admin+/index": { "id": "routes/admin+/index", "parentId": "routes/admin+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-DDqzbGM2.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/misc-DIdEn_jt.js", "/assets/tooltip-BoVikCa-.js", "/assets/progress-D6SP0Gec.js", "/assets/components-DUNtf72c.js", "/assets/pe-D5h19vSo.js"], "css": [] }, "routes/admin+/version": { "id": "routes/admin+/version", "parentId": "routes/admin+/_layout", "path": "version", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/version-CIF3cX3N.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/workshop-config-C5sYl312.js", "/assets/components-DUNtf72c.js"], "css": [] }, "routes/apps": { "id": "routes/apps", "parentId": "root", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-DP2rzg_V.js", "imports": [], "css": [] }, "routes/diff": { "id": "routes/diff", "parentId": "root", "path": "diff", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/diff-B3oaU_KB.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/misc-DIdEn_jt.js", "/assets/diff-BNCREJvf.js", "/assets/nav-chevrons-B3SvZV8B.js", "/assets/components-DUNtf72c.js", "/assets/accordion-DLg7gJkp.js", "/assets/tooltip-BoVikCa-.js", "/assets/index-DFqQCjCw.js", "/assets/index-CV3nxGFp.js", "/assets/mdx-C9dqA6IZ.js", "/assets/epic-video-D8ex9vao.js", "/assets/index-DH1w3QmP.js", "/assets/request-info-vBkaf3Rk.js", "/assets/pe-D5h19vSo.js", "/assets/index-BajUQsFT.js", "/assets/loading-DW_I206H.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js", "/assets/progress-bar-CBDBzRQ2.js", "/assets/revalidation-ws-DK5QOPlL.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/exercises": { "id": "routes/exercises", "parentId": "root", "path": "exercises", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/exercises-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/launch-editor": { "id": "routes/launch-editor", "parentId": "root", "path": "launch-editor", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/launch-editor-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/login-sse": { "id": "routes/login-sse", "parentId": "root", "path": "login-sse", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-sse-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/og": { "id": "routes/og", "parentId": "root", "path": "og", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/og-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/onboarding": { "id": "routes/onboarding", "parentId": "root", "path": "onboarding", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/onboarding-CC9zz4rl.js", "imports": ["/assets/index-C_B1-9rF.js", "/assets/button-39zQyNX6.js", "/assets/epic-video-D8ex9vao.js", "/assets/components-DUNtf72c.js", "/assets/misc-DIdEn_jt.js", "/assets/index-DH1w3QmP.js", "/assets/request-info-vBkaf3Rk.js", "/assets/tooltip-BoVikCa-.js", "/assets/pe-D5h19vSo.js", "/assets/index-BajUQsFT.js", "/assets/loading-DW_I206H.js", "/assets/user-CbbIYEs8.js", "/assets/workshop-config-C5sYl312.js"], "css": ["/assets/index-DUnRvy1A.css"] }, "routes/processes": { "id": "routes/processes", "parentId": "root", "path": "processes", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/processes-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/progress": { "id": "routes/progress", "parentId": "root", "path": "progress", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/progress-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/robots[.]txt": { "id": "routes/robots[.]txt", "parentId": "root", "path": "robots.txt", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/robots_._txt-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/set-playground": { "id": "routes/set-playground", "parentId": "root", "path": "set-playground", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/set-playground-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/sitemap[.]xml": { "id": "routes/sitemap[.]xml", "parentId": "root", "path": "sitemap.xml", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/sitemap_._xml-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/start": { "id": "routes/start", "parentId": "root", "path": "start", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/start-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/test": { "id": "routes/test", "parentId": "root", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/theme/index": { "id": "routes/theme/index", "parentId": "root", "path": "theme", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-DP2rzg_V.js", "imports": [], "css": [] }, "routes/video-player/index": { "id": "routes/video-player/index", "parentId": "root", "path": "video-player", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-K6Dvbx-E.js", "imports": [], "css": [] } }, "url": "/assets/manifest-62ea49c4.js", "version": "62ea49c4" };
|
|
11303
10977
|
const mode = "production";
|
|
11304
10978
|
const assetsBuildDirectory = "build/client";
|
|
11305
10979
|
const basename = "/";
|