1 line
26 KiB
Plaintext
1 line
26 KiB
Plaintext
{"version":3,"mappings":"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","names":["isPublicShare","loadState","getSharingToken","logger","args","App","lazy","__vitePreload","n","ReadOnlyViewer","normalizeVersionSource","source","resolved","matchesComparisonRequest","versionSource","fileVersion","compareInfo","normalizedSource","compareSource","compareVersion","shouldRenderComparison","props","context","renderWhiteboardView","rootElement","root","createRoot","isComparisonView","componentProps","comparisonMode","ComponentToRender","React","StrictMode","Suspense","linkTo","VIEWER_REGISTRATION_ATTEMPTS","VIEWER_REGISTRATION_DELAY_MS","bootstrapWhiteboardRuntime","runtime","detectRuntime","runRecordingRuntime","runPublicShareRuntime","runDefaultViewerRuntime","fileId","normalizeNumericState","collabBackendUrl","runWhenDomReady","primeRecordingJwt","whiteboardElement","createWhiteboardElement","viewerContext","hasOpenedInViewer","isWhiteboardPublicShare","mimetypeElmt","ensurePublicShareLayout","openInViewer","viewerApi","getViewerApi","error","openEmbeddedFallback","previewHost","registerViewerHandler","createWhiteboardComponent","options","createElement","containerId","generateWhiteboardElementId","event","normalizedFileId","isEmbedded","rawVersionSource","rawFileVersion","isVersionsDavSource","shouldUseVersionPreview","fileName","component","attempt","afterRegister","callback","handler","jwt","useJWTStore","payload","state","value","normalized","id","element"],"ignoreList":[0],"sources":["../node_modules/@nextcloud/sharing/dist/public.js","../src/utils/logger.ts","../src/utils/renderWhiteboardView.tsx","../src/main.ts"],"sourcesContent":["/*!\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: GPL-3.0-or-later\n */\n/**\n * @module public\n */\nimport { loadState } from '@nextcloud/initial-state';\n/**\n * Check if the current page is on a public share\n */\nexport function isPublicShare() {\n // check both the new initial state version and fallback to legacy input\n return (loadState('files_sharing', 'isPublic', null)\n ?? document.querySelector('input#isPublic[type=\"hidden\"][name=\"isPublic\"][value=\"1\"]') !== null);\n}\n/**\n * Get the sharing token for the current public share\n */\nexport function getSharingToken() {\n return (loadState('files_sharing', 'sharingToken', null)\n ?? document.querySelector('input#sharingToken[type=\"hidden\"]')?.value\n ?? null);\n}\n","/**\n * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\n/* eslint-disable no-console */\n\n/**\n * Centralized logging utility for Nextcloud Whiteboard\n * Only logs in development mode to avoid performance impact and noise in production\n */\n\nconst isDevelopment = process.env.NODE_ENV === 'development' || import.meta.env?.DEV === true\n\ntype LogArgs = unknown[]\n\nconst logger = {\n\t/**\n\t * Log debug information - only in development\n\t * @param {unknown[]} args - Arguments to log\n\t */\n\tdebug: (...args: LogArgs) => {\n\t\tif (isDevelopment) {\n\t\t\tconsole.log(...args)\n\t\t}\n\t},\n\n\t/**\n\t * Log warnings - always enabled as they indicate potential issues\n\t * @param {unknown[]} args - Arguments to log\n\t */\n\twarn: (...args: LogArgs) => {\n\t\tconsole.warn(...args)\n\t},\n\n\t/**\n\t * Log errors - always enabled as they need to be tracked\n\t * @param {unknown[]} args - Arguments to log\n\t */\n\terror: (...args: LogArgs) => {\n\t\tconsole.error(...args)\n\t},\n\n\t/**\n\t * Log info - only in development\n\t * @param {unknown[]} args - Arguments to log\n\t */\n\tinfo: (...args: LogArgs) => {\n\t\tif (isDevelopment) {\n\t\t\tconsole.info(...args)\n\t\t}\n\t},\n\n\t/**\n\t * Silent no-op function for completely removing logs\n\t */\n\tnoop: () => {},\n}\n\nexport default logger\n","/**\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { StrictMode, Suspense, lazy } from 'react'\nimport { createRoot } from 'react-dom'\n\nimport type { WhiteboardAppProps } from '../App'\n\nconst App = lazy(() => import('../App'))\nconst ReadOnlyViewer = lazy(() => import('../components/ReadOnlyViewer'))\n\ntype ViewerFileInfo = {\n source?: string\n fileVersion?: string | null\n}\n\ntype ComparisonMatchContext = {\n isViewerContext: boolean\n}\n\nconst normalizeVersionSource = (source: string | null): string | null => {\n\tif (!source) {\n\t\treturn null\n\t}\n\ttry {\n\t\tconst resolved = new URL(source, window.location.origin)\n\t\treturn resolved.pathname + resolved.search\n\t} catch {\n\t\treturn source\n\t}\n}\n\nexport const matchesComparisonRequest = (versionSource: string | null, fileVersion: string | null): boolean => {\n\tconst compareInfo = window?.OCA?.Viewer?.compareFileInfo as ViewerFileInfo | undefined\n\tif (!compareInfo || typeof compareInfo !== 'object') {\n\t\treturn false\n\t}\n\n\tconst normalizedSource = normalizeVersionSource(versionSource)\n\tconst compareSource = normalizeVersionSource(compareInfo.source ?? null)\n\tif (normalizedSource && compareSource && normalizedSource === compareSource) {\n\t\treturn true\n\t}\n\n\tconst compareVersion = compareInfo.fileVersion ?? null\n\tif (\n\t\tfileVersion\n && compareVersion\n && String(compareVersion) === String(fileVersion)\n\t) {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\nexport type RenderWhiteboardViewOptions = WhiteboardAppProps & {\n isComparisonView?: boolean\n}\n\nexport type WhiteboardRootHandle = {\n unmount: () => void\n}\n\nconst shouldRenderComparison = (\n\tprops: Pick<RenderWhiteboardViewOptions, 'isComparisonView' | 'versionSource' | 'fileVersion'>,\n\tcontext: ComparisonMatchContext,\n): boolean => {\n\tif (props.isComparisonView) {\n\t\treturn true\n\t}\n\tif (!context.isViewerContext) {\n\t\treturn false\n\t}\n\treturn matchesComparisonRequest(props.versionSource, props.fileVersion ?? null)\n}\n\nexport const renderWhiteboardView = (rootElement: HTMLElement, props: RenderWhiteboardViewOptions): WhiteboardRootHandle => {\n\tconst root = createRoot(rootElement)\n\tconst { isComparisonView, ...componentProps } = props\n\n\tconst comparisonMode = shouldRenderComparison(\n\t\t{\n\t\t\tisComparisonView,\n\t\t\tversionSource: componentProps.versionSource,\n\t\t\tfileVersion: componentProps.fileVersion ?? null,\n\t\t},\n\t\t{ isViewerContext: Boolean(rootElement.closest('.viewer__content')) },\n\t)\n\n\tconst ComponentToRender = (componentProps.isEmbedded || comparisonMode)\n\t\t? ReadOnlyViewer\n\t\t: App\n\n\troot.render(\n\t\t<StrictMode>\n\t\t\t<Suspense fallback={<div>Loading…</div>}>\n\t\t\t\t<ComponentToRender {...componentProps as WhiteboardAppProps} />\n\t\t\t</Suspense>\n\t\t</StrictMode>,\n\t)\n\n\treturn {\n\t\tunmount: () => root.unmount(),\n\t}\n}\n\ndeclare global {\n interface Window {\n OCA?: {\n Viewer?: {\n compareFileInfo?: ViewerFileInfo\n }\n }\n }\n}\n","/**\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type Vue from 'vue'\nimport type { ComponentOptions, CreateElement, VNode } from 'vue'\n\nimport { loadState } from '@nextcloud/initial-state'\nimport { linkTo } from '@nextcloud/router'\nimport { getSharingToken, isPublicShare } from '@nextcloud/sharing/public'\n\nimport './styles/index.scss'\nimport logger from './utils/logger'\nimport {\n\tmatchesComparisonRequest,\n\trenderWhiteboardView,\n} from './utils/renderWhiteboardView'\nimport type { WhiteboardRootHandle } from './utils/renderWhiteboardView'\n\ndeclare global {\n\tinterface Window {\n\t\tEXCALIDRAW_ASSET_PATH?: string | string[]\n\t}\n}\n\nwindow.EXCALIDRAW_ASSET_PATH = linkTo('whiteboard', 'dist/')\n\ntype RecordingContext = {\n\tfileId: number\n\tcollabBackendUrl: string\n\tjwt: string\n}\n\ntype PublicShareContext = {\n\tfileId: number\n\tcollabBackendUrl: string\n\tsharingToken: string | null\n}\n\ntype ViewerContext = {\n\tcollabBackendUrl: string\n\tresolveSharingToken: () => string | null\n}\n\ntype RuntimeDescriptor =\n\t| { type: 'recording'; context: RecordingContext }\n\t| { type: 'public-share'; context: PublicShareContext }\n\t| { type: 'viewer'; context: ViewerContext }\n\nconst VIEWER_REGISTRATION_ATTEMPTS = 3\nconst VIEWER_REGISTRATION_DELAY_MS = 250\n\nconst bootstrapWhiteboardRuntime = (): void => {\n\tconst runtime = detectRuntime()\n\n\tswitch (runtime.type) {\n\tcase 'recording':\n\t\trunRecordingRuntime(runtime.context)\n\t\treturn\n\tcase 'public-share':\n\t\trunPublicShareRuntime(runtime.context)\n\t\treturn\n\tcase 'viewer':\n\tdefault:\n\t\trunDefaultViewerRuntime(runtime.context)\n\t}\n}\n\nconst detectRuntime = (): RuntimeDescriptor => {\n\tconst fileId = normalizeNumericState(\n\t\tloadState('whiteboard', 'file_id', '0'),\n\t)\n\tconst collabBackendUrl = loadState('whiteboard', 'collabBackendUrl', '')\n\n\tif (loadState('whiteboard', 'isRecording', false)) {\n\t\treturn {\n\t\t\ttype: 'recording',\n\t\t\tcontext: {\n\t\t\t\tfileId,\n\t\t\t\tcollabBackendUrl,\n\t\t\t\tjwt: loadState('whiteboard', 'jwt', ''),\n\t\t\t},\n\t\t}\n\t}\n\n\tif (isPublicShare()) {\n\t\treturn {\n\t\t\ttype: 'public-share',\n\t\t\tcontext: {\n\t\t\t\tfileId,\n\t\t\t\tcollabBackendUrl,\n\t\t\t\tsharingToken: getSharingToken(),\n\t\t\t},\n\t\t}\n\t}\n\n\treturn {\n\t\ttype: 'viewer',\n\t\tcontext: {\n\t\t\tcollabBackendUrl,\n\t\t\tresolveSharingToken: () => getSharingToken(),\n\t\t},\n\t}\n}\n\nfunction runRecordingRuntime(context: RecordingContext): void {\n\trunWhenDomReady(async () => {\n\t\tawait primeRecordingJwt(context.fileId, context.jwt)\n\n\t\tdocument.body.removeAttribute('id')\n\t\tdocument.body.innerHTML = ''\n\t\tconst whiteboardElement = createWhiteboardElement()\n\t\twhiteboardElement.classList.add('recording')\n\t\tdocument.body.appendChild(whiteboardElement)\n\n\t\trenderWhiteboardView(whiteboardElement, {\n\t\t\tfileId: context.fileId,\n\t\t\tisEmbedded: false,\n\t\t\tfileName: '',\n\t\t\tpublicSharingToken: null,\n\t\t\tcollabBackendUrl: context.collabBackendUrl,\n\t\t\tversionSource: null,\n\t\t\tfileVersion: null,\n\t\t})\n\t})\n}\n\nfunction runPublicShareRuntime(context: PublicShareContext): void {\n\tconst viewerContext: ViewerContext = {\n\t\tcollabBackendUrl: context.collabBackendUrl,\n\t\tresolveSharingToken: () => context.sharingToken,\n\t}\n\n\tlet hasOpenedInViewer = false\n\tconst isWhiteboardPublicShare = (): boolean => {\n\t\t// LoadViewer triggers whiteboard-main on all public shares; only continue if\n\t\t// this share was explicitly marked as a whiteboard file by the backend.\n\t\tif (!context.fileId) {\n\t\t\treturn false\n\t\t}\n\n\t\t// On NC29/30, there's a hidden input with id=\"mimetype\" that we can check.\n\t\t// On NC31+, this element doesn't exist, so we rely on the backend-provided\n\t\t// whiteboard file id check above.\n\t\tconst mimetypeElmt = document.getElementById('mimetype') as HTMLInputElement | null\n\t\tif (mimetypeElmt && mimetypeElmt.value !== 'application/vnd.excalidraw+json') {\n\t\t\treturn false\n\t\t}\n\n\t\treturn true\n\t}\n\n\tconst ensurePublicShareLayout = (): void => {\n\t\tdocument.body.classList.add('whiteboard-public-share')\n\t}\n\n\tconst openInViewer = (): void => {\n\t\tif (!isWhiteboardPublicShare()) {\n\t\t\thasOpenedInViewer = true\n\t\t\treturn\n\t\t}\n\n\t\tif (hasOpenedInViewer) {\n\t\t\treturn\n\t\t}\n\n\t\tensurePublicShareLayout()\n\n\t\tconst viewerApi = getViewerApi()\n\t\tif (!viewerApi) {\n\t\t\treturn\n\t\t}\n\n\t\tif (typeof viewerApi.openWith !== 'function' && typeof viewerApi.open !== 'function') {\n\t\t\treturn\n\t\t}\n\n\t\thasOpenedInViewer = true\n\n\t\ttry {\n\t\t\tviewerApi.setRootElement?.(null)\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\n\t\ttry {\n\t\t\tif (typeof viewerApi.openWith === 'function') {\n\t\t\t\tviewerApi.openWith('whiteboard', { path: '/', enableSidebar: false, canLoop: false })\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tviewerApi.open?.({ path: '/', enableSidebar: false, canLoop: false })\n\t\t} catch (error) {\n\t\t\thasOpenedInViewer = false\n\t\t\tlogger.error('Could not open public share in viewer', { error })\n\t\t}\n\t}\n\n\tconst openEmbeddedFallback = (): void => {\n\t\tif (hasOpenedInViewer) {\n\t\t\treturn\n\t\t}\n\n\t\tif (!isWhiteboardPublicShare()) {\n\t\t\treturn\n\t\t}\n\n\t\tconst previewHost = document.getElementById('preview') || document.getElementById('imgframe')\n\t\tif (!previewHost) {\n\t\t\treturn\n\t\t}\n\n\t\tensurePublicShareLayout()\n\n\t\tpreviewHost.innerHTML = ''\n\n\t\tconst whiteboardElement = createWhiteboardElement()\n\t\tpreviewHost.appendChild(whiteboardElement)\n\n\t\trenderWhiteboardView(whiteboardElement, {\n\t\t\tfileId: context.fileId,\n\t\t\tisEmbedded: false,\n\t\t\tfileName: document.title,\n\t\t\tpublicSharingToken: context.sharingToken,\n\t\t\tcollabBackendUrl: context.collabBackendUrl,\n\t\t\tversionSource: null,\n\t\t\tfileVersion: null,\n\t\t})\n\t}\n\n\trunWhenDomReady(() => {\n\t\tregisterViewerHandler(createWhiteboardComponent(viewerContext), 0, openInViewer)\n\n\t\twindow.setTimeout(() => {\n\t\t\topenEmbeddedFallback()\n\t\t}, 2500)\n\t})\n}\n\nfunction runDefaultViewerRuntime(context: ViewerContext): void {\n\trunWhenDomReady(() => {\n\t\tregisterViewerHandler(createWhiteboardComponent(context))\n\t})\n}\n\ntype ViewerComponentOptions = {\n\tcollabBackendUrl: string\n\tresolveSharingToken: () => string | null\n}\n\ntype WhiteboardComponentData = { root: WhiteboardRootHandle | null }\n\ntype WhiteboardComponentInstance = Vue &\n\tWhiteboardComponentData & {\n\t\tfileid?: number | null\n\t\tfileId?: number | null\n\t\tfileVersion?: string | null\n\t\tsource?: string | null\n\t\tisEmbedded?: boolean\n\t\tisComparisonView?: boolean\n\t\tbasename?: string\n\t}\n\ntype VueComponentDefinition = ComponentOptions<WhiteboardComponentInstance> & {\n\tdata: () => WhiteboardComponentData\n}\n\ntype ViewerHandlerRegistration = {\n\tid: string\n\tmimes: string[]\n\tcomponent: VueComponentDefinition\n\tgroup: string | null\n\ttheme: string\n\tcanCompare: boolean\n}\n\ntype ViewerApi = {\n\tregisterHandler?: (handler: ViewerHandlerRegistration) => void\n\topen?: (options?: {\n\t\tpath?: string\n\t\tfileInfo?: unknown\n\t\tlist?: unknown[]\n\t\tenableSidebar?: boolean\n\t\tloadMore?: () => unknown[]\n\t\tcanLoop?: boolean\n\t\tonPrev?: () => void\n\t\tonNext?: () => void\n\t\tonClose?: () => void\n\t}) => void\n\topenWith?: (handlerId: string, options?: {\n\t\tpath?: string\n\t\tfileInfo?: unknown\n\t\tlist?: unknown[]\n\t\tenableSidebar?: boolean\n\t\tloadMore?: () => unknown[]\n\t\tcanLoop?: boolean\n\t\tonPrev?: () => void\n\t\tonNext?: () => void\n\t\tonClose?: () => void\n\t}) => void\n\tsetRootElement?: (el?: string | null) => void\n\tcompareFileInfo?: unknown\n}\n\ntype WindowWithViewer = Window & {\n\tOCA?: {\n\t\tViewer?: ViewerApi\n\t}\n}\n\nconst createWhiteboardComponent = (\n\toptions: ViewerComponentOptions,\n): VueComponentDefinition => ({\n\tname: 'Whiteboard',\n\trender(\n\t\tthis: WhiteboardComponentInstance,\n\t\tcreateElement: CreateElement,\n\t): VNode {\n\t\tthis.$emit('update:loaded', true)\n\t\tconst containerId = generateWhiteboardElementId()\n\n\t\tthis.$nextTick(() => {\n\t\t\tconst rootElement = document.getElementById(containerId)\n\t\t\tif (!rootElement) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\trootElement.addEventListener('keydown', (event) => {\n\t\t\t\tif (event.key === 'Escape') {\n\t\t\t\t\tevent.stopPropagation()\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tconst normalizedFileId\n\t\t\t\t= Number(this.fileid ?? this.fileId ?? 0) || 0\n\t\t\tconst isComparisonView = Boolean(this.isComparisonView)\n\t\t\tconst isEmbedded = Boolean(this.isEmbedded)\n\t\t\tconst rawVersionSource = this.source ?? null\n\t\t\tconst rawFileVersion = this.fileVersion ?? null\n\t\t\tconst isVersionsDavSource\n\t\t\t\t= rawVersionSource?.includes('/dav/versions/')\n\t\t\t\t|| rawVersionSource?.includes('/dav/trashbin/')\n\t\t\t\t|| false\n\t\t\tconst shouldUseVersionPreview\n\t\t\t\t= isComparisonView\n\t\t\t\t|| (rawFileVersion !== null && isVersionsDavSource)\n\t\t\t\t|| matchesComparisonRequest(\n\t\t\t\t\trawVersionSource,\n\t\t\t\t\trawFileVersion ?? null,\n\t\t\t\t)\n\t\t\tconst versionSource = isEmbedded\n\t\t\t\t? rawVersionSource\n\t\t\t\t: shouldUseVersionPreview\n\t\t\t\t\t? rawVersionSource\n\t\t\t\t\t: null\n\t\t\tconst fileVersion = isEmbedded\n\t\t\t\t? rawFileVersion\n\t\t\t\t: shouldUseVersionPreview\n\t\t\t\t\t? rawFileVersion\n\t\t\t\t\t: null\n\t\t\tconst fileName\n\t\t\t\t= typeof this.basename === 'string' ? this.basename : ''\n\n\t\t\tthis.root = renderWhiteboardView(rootElement, {\n\t\t\t\tfileId: normalizedFileId,\n\t\t\t\tisEmbedded,\n\t\t\t\tfileName,\n\t\t\t\tpublicSharingToken: options.resolveSharingToken(),\n\t\t\t\tcollabBackendUrl: options.collabBackendUrl,\n\t\t\t\tversionSource,\n\t\t\t\tfileVersion,\n\t\t\t\tisComparisonView,\n\t\t\t})\n\t\t})\n\n\t\treturn createElement(\n\t\t\t'div',\n\t\t\t{\n\t\t\t\tattrs: { id: containerId },\n\t\t\t\tclass: [\n\t\t\t\t\t'whiteboard',\n\t\t\t\t\t{\n\t\t\t\t\t\t'whiteboard-viewer__embedding': Boolean(\n\t\t\t\t\t\t\tthis.isEmbedded,\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t'',\n\t\t)\n\t},\n\tbeforeDestroy(this: WhiteboardComponentInstance) {\n\t\tthis.root?.unmount()\n\t},\n\tprops: {\n\t\tfilename: { type: String, default: null },\n\t\tfileid: { type: Number, default: null },\n\t\tfileId: { type: Number, default: null },\n\t\tfileVersion: { type: String, default: null },\n\t\tsource: { type: String, default: null },\n\t\tisEmbedded: { type: Boolean, default: false },\n\t\tisComparisonView: { type: Boolean, default: false },\n\t},\n\tdata: (): WhiteboardComponentData => ({ root: null }),\n})\n\nconst registerViewerHandler = (\n\tcomponent: VueComponentDefinition,\n\tattempt = 0,\n\tafterRegister?: () => void,\n): void => {\n\tconst viewerApi = getViewerApi()\n\n\tif (viewerApi?.registerHandler) {\n\t\tviewerApi.registerHandler({\n\t\t\tid: 'whiteboard',\n\t\t\tmimes: ['application/vnd.excalidraw+json'],\n\t\t\tcomponent,\n\t\t\tgroup: null,\n\t\t\ttheme: 'default',\n\t\t\tcanCompare: true,\n\t\t})\n\t\tafterRegister?.()\n\t\treturn\n\t}\n\n\tif (attempt >= VIEWER_REGISTRATION_ATTEMPTS) {\n\t\tlogger.error('Could not register whiteboard handler for viewer')\n\t\treturn\n\t}\n\n\twindow.setTimeout(\n\t\t() => registerViewerHandler(component, attempt + 1, afterRegister),\n\t\tVIEWER_REGISTRATION_DELAY_MS,\n\t)\n}\n\nconst getViewerApi = (): ViewerApi | undefined =>\n\t(window as WindowWithViewer).OCA?.Viewer\n\nconst runWhenDomReady = (callback: () => void | Promise<void>): void => {\n\tif (document.readyState === 'loading') {\n\t\tconst handler = () => {\n\t\t\tdocument.removeEventListener('DOMContentLoaded', handler)\n\t\t\tcallback()\n\t\t}\n\t\tdocument.addEventListener('DOMContentLoaded', handler)\n\t\treturn\n\t}\n\n\tcallback()\n}\n\nconst primeRecordingJwt = async (\n\tfileId: number,\n\tjwt: string,\n): Promise<void> => {\n\tif (!jwt) {\n\t\treturn\n\t}\n\n\tconst { useJWTStore } = await import('./stores/useJwtStore')\n\tconst payload = useJWTStore.getState().parseJwt(jwt)\n\n\tif (!payload) {\n\t\treturn\n\t}\n\n\tuseJWTStore.setState((state) => ({\n\t\t...state,\n\t\ttokens: {\n\t\t\t...state.tokens,\n\t\t\t[fileId]: jwt,\n\t\t},\n\t\ttokenExpiries: {\n\t\t\t...state.tokenExpiries,\n\t\t\t[fileId]: payload.exp,\n\t\t},\n\t}))\n}\n\nconst normalizeNumericState = (value: unknown): number => {\n\tconst normalized = Number(value)\n\treturn Number.isFinite(normalized) ? normalized : 0\n}\n\nconst generateWhiteboardElementId = () =>\n\t`whiteboard-${Math.random()\n\t\t.toString(36)\n\t\t.replace(/[^a-z]+/g, '')\n\t\t.substr(2, 10)}`\n\nconst createWhiteboardElement = (id = generateWhiteboardElementId()) => {\n\tconst element = document.createElement('div')\n\telement.id = id\n\telement.className = 'whiteboard'\n\treturn element\n}\n\nbootstrapWhiteboardRuntime()\n"],"file":"js/whiteboard-main.mjs"} |