diff --git a/packages/text-editor/src/components/CollaborativeTextEditor.svelte b/packages/text-editor/src/components/CollaborativeTextEditor.svelte index 50ca74c1cc..00997f9fa3 100644 --- a/packages/text-editor/src/components/CollaborativeTextEditor.svelte +++ b/packages/text-editor/src/components/CollaborativeTextEditor.svelte @@ -44,7 +44,7 @@ import { textEditorCommandHandler } from '../commands' import { EditorKit } from '../kits/editor-kit' import textEditorPlugin from '../plugin' - import { MinioProvider } from '../provider/minio' + import { DirectStorageProvider } from '../provider/storage' import { TiptapCollabProvider } from '../provider/tiptap' import { formatCollaborativeDocumentId, formatPlatformDocumentId } from '../provider/utils' import { @@ -135,7 +135,7 @@ const ydoc = getContext(CollaborationIds.Doc) ?? new YDoc() const contextProvider = getContext(CollaborationIds.Provider) - const localProvider = contextProvider === undefined ? new MinioProvider(documentId, ydoc) : undefined + const localProvider = contextProvider === undefined ? new DirectStorageProvider(collaborativeDoc, ydoc) : undefined const remoteProvider: TiptapCollabProvider = contextProvider ?? diff --git a/packages/text-editor/src/provider/minio.ts b/packages/text-editor/src/provider/minio.ts deleted file mode 100644 index cb44d96651..0000000000 --- a/packages/text-editor/src/provider/minio.ts +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright © 2023 Hardcore Engineering Inc. -// -// Licensed under the Eclipse Public License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. You may -// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// -// See the License for the specific language governing permissions and -// limitations under the License. -// -import { parseDocumentId, type DocumentId } from '@hcengineering/collaborator-client' -import { collaborativeDocParse, concatLink } from '@hcengineering/core' -import { getMetadata } from '@hcengineering/platform' -import presentation, { getCurrentWorkspaceUrl } from '@hcengineering/presentation' -import { ObservableV2 as Observable } from 'lib0/observable' -import { applyUpdate, type Doc as YDoc } from 'yjs' - -interface EVENTS { - synced: (...args: any[]) => void -} - -async function fetchContent (doc: YDoc, name: string): Promise { - for (let i = 0; i < 2; i++) { - try { - const frontUrl = getMetadata(presentation.metadata.FrontUrl) ?? window.location.origin - - try { - const res = await fetch(concatLink(frontUrl, `/files/${getCurrentWorkspaceUrl()}?file=${name}`)) - - if (res.ok) { - const blob = await res.blob() - const buffer = await blob.arrayBuffer() - applyUpdate(doc, new Uint8Array(buffer)) - return - } - } catch {} - } catch (err: any) { - console.error(err) - } - // White a while - await new Promise((resolve) => setTimeout(resolve, 10)) - } -} - -export class MinioProvider extends Observable { - loaded: Promise - - constructor (documentId: DocumentId, doc: YDoc) { - super() - - this.loaded = new Promise((resolve) => { - this.on('synced', resolve) - }) - - const { collaborativeDoc } = parseDocumentId(documentId) - const { documentId: minioDocumentId, versionId } = collaborativeDocParse(collaborativeDoc) - - if (versionId === 'HEAD' && minioDocumentId !== undefined) { - void fetchContent(doc, minioDocumentId).then(() => { - this.emit('synced', [this]) - }) - } - } -} diff --git a/packages/text-editor/src/provider/storage.ts b/packages/text-editor/src/provider/storage.ts new file mode 100644 index 0000000000..bb8f8e9f6a --- /dev/null +++ b/packages/text-editor/src/provider/storage.ts @@ -0,0 +1,71 @@ +// +// Copyright © 2023 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +import { type Blob, type CollaborativeDoc, type Ref, collaborativeDocParse } from '@hcengineering/core' +import { getBlobHref } from '@hcengineering/presentation' +import { ObservableV2 as Observable } from 'lib0/observable' +import { applyUpdate, type Doc as YDoc } from 'yjs' + +interface EVENTS { + synced: (...args: any[]) => void +} + +async function fetchContent (blob: Ref, doc: YDoc): Promise { + const update = await fetchBlobContent(blob) + if (update !== undefined) { + applyUpdate(doc, update) + return true + } + + return false +} + +async function fetchBlobContent (_id: Ref): Promise { + try { + const href = await getBlobHref(undefined, _id) + const res = await fetch(href) + + if (res.ok) { + const blob = await res.blob() + const buffer = await blob.arrayBuffer() + return new Uint8Array(buffer) + } + } catch (err: any) { + console.error(err) + } + + return undefined +} + +export class DirectStorageProvider extends Observable { + loaded: Promise + + constructor (collaborativeDoc: CollaborativeDoc, doc: YDoc) { + super() + + this.loaded = new Promise((resolve) => { + this.on('synced', resolve) + }) + + const { documentId, versionId } = collaborativeDocParse(collaborativeDoc) + + if (versionId === 'HEAD') { + void fetchContent(documentId as Ref, doc).then((synced) => { + if (synced) { + this.emit('synced', [this]) + } + }) + } + } +}