From 9b7880f86aebb4ebd8c4c6f6bf8efd2d1cd48e66 Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Fri, 23 Aug 2024 14:16:11 +0700 Subject: [PATCH] UBERF-7931 Get rid of file collab provider (#6380) Signed-off-by: Alexander Onnikov --- common/config/rush/pnpm-lock.yaml | 15 +++- plugins/text-editor-resources/package.json | 3 +- .../components/CollaborativeTextEditor.svelte | 8 +-- .../src/provider/indexeddb.ts | 32 +++++++++ .../src/provider/storage.ts | 71 ------------------- 5 files changed, 51 insertions(+), 78 deletions(-) create mode 100644 plugins/text-editor-resources/src/provider/indexeddb.ts delete mode 100644 plugins/text-editor-resources/src/provider/storage.ts diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index ba4aecd349..345e8450ed 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -23683,6 +23683,16 @@ packages: engines: {node: '>=0.4'} dev: false + /y-indexeddb@9.0.12(yjs@13.6.12): + resolution: {integrity: sha512-9oCFRSPPzBK7/w5vOkJBaVCQZKHXB/v6SIT+WYhnJxlEC61juqG0hBrAf+y3gmSMLFLwICNH9nQ53uscuse6Hg==} + engines: {node: '>=16.0.0', npm: '>=8.0.0'} + peerDependencies: + yjs: ^13.0.0 + dependencies: + lib0: 0.2.89 + yjs: 13.6.12 + dev: false + /y-prosemirror@1.2.2(prosemirror-model@1.19.4)(y-protocols@1.0.6)(yjs@13.6.12): resolution: {integrity: sha512-hHdnIAhfa8mIoLWtTkMDb6RBzN3lye1QVkaZwVm58sledAA1zTl+yyEtgkrY/sdH6SaQL0rsLj61zHjgr5D0HQ==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} @@ -25060,7 +25070,7 @@ packages: dev: false file:projects/collaborator.tgz(@tiptap/pm@2.2.4)(bufferutil@4.0.8)(prosemirror-model@1.19.4)(utf-8-validate@6.0.4)(y-protocols@1.0.6): - resolution: {integrity: sha512-2kBYCHIIHeDD99Oj4ViM3+h4CPlelHbpP+HOtuYXSxNeM+hsIhmqdQJrSBoLA3u5LGTsHHapjg94S4sgaMz60Q==, tarball: file:projects/collaborator.tgz} + resolution: {integrity: sha512-svaotn6ykOZH+tModYWz/Y3hct1yHDm/enwC9NCpH17VVNALvRIqUx8F2DWvQV5mUwJYxLcKgdsBqNPB4MjMag==, tarball: file:projects/collaborator.tgz} id: file:projects/collaborator.tgz name: '@rush-temp/collaborator' version: 0.0.0 @@ -33848,7 +33858,7 @@ packages: dev: false file:projects/text-editor-resources.tgz(@types/node@20.11.19)(bufferutil@4.0.8)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(prosemirror-model@1.19.4)(ts-node@10.9.2)(utf-8-validate@6.0.4): - resolution: {integrity: sha512-piHhMfwGIkFR7VYjYWS1lGTwg5zIQaKJmKSSAY7gpRGM4BA88RagpPmx8eT/hXvFv83a+4CzkMUK/atGHWRZcQ==, tarball: file:projects/text-editor-resources.tgz} + resolution: {integrity: sha512-PNeHw/vqYgLq6arghBnAisN4GlvA0DWANKiXTvjahoXM0EhEz6SVX2bh6Fd9xrDqYKWVdfVc2X5o5Zk1dI4qEw==, tarball: file:projects/text-editor-resources.tgz} id: file:projects/text-editor-resources.tgz name: '@rush-temp/text-editor-resources' version: 0.0.0 @@ -33901,6 +33911,7 @@ packages: svelte-preprocess: 5.1.3(postcss-load-config@4.0.2)(postcss@8.4.35)(sass@1.71.1)(svelte@4.2.12)(typescript@5.3.3) ts-jest: 29.1.2(esbuild@0.20.1)(jest@29.7.0)(typescript@5.3.3) typescript: 5.3.3 + y-indexeddb: 9.0.12(yjs@13.6.12) y-prosemirror: 1.2.2(prosemirror-model@1.19.4)(y-protocols@1.0.6)(yjs@13.6.12) y-protocols: 1.0.6(yjs@13.6.12) yjs: 13.6.12 diff --git a/plugins/text-editor-resources/package.json b/plugins/text-editor-resources/package.json index 5f597ae2fc..b176d93471 100644 --- a/plugins/text-editor-resources/package.json +++ b/plugins/text-editor-resources/package.json @@ -77,6 +77,7 @@ "rfc6902": "^5.0.1", "diff": "^5.1.0", "slugify": "^1.6.6", - "lib0": "^0.2.88" + "lib0": "^0.2.88", + "y-indexeddb": "^9.0.12" } } diff --git a/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte b/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte index 88f5273226..c534421264 100644 --- a/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte +++ b/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte @@ -43,7 +43,7 @@ import { deleteAttachment } from '../command/deleteAttachment' import { textEditorCommandHandler } from '../commands' import { EditorKitOptions, getEditorKit } from '../../src/kits/editor-kit' - import { DirectStorageProvider } from '../provider/storage' + import { IndexeddbProvider } from '../provider/indexeddb' import { TiptapCollabProvider } from '../provider/tiptap' import { formatCollaborativeDocumentId, formatPlatformDocumentId } from '../provider/utils' import textEditor, { @@ -121,7 +121,7 @@ const ydoc = getContext(CollaborationIds.Doc) ?? new YDoc() const contextProvider = getContext(CollaborationIds.Provider) - const localProvider = contextProvider === undefined ? new DirectStorageProvider(collaborativeDoc, ydoc) : undefined + const localProvider = new IndexeddbProvider(collaborativeDoc, ydoc) const remoteProvider: TiptapCollabProvider = contextProvider ?? @@ -142,7 +142,7 @@ $: loading = !localSynced && !remoteSynced $: editable = !readonly && remoteSynced - void localProvider?.loaded.then(() => (localSynced = true)) + void localProvider.loaded.then(() => (localSynced = true)) void remoteProvider.loaded.then(() => (remoteSynced = true)) let editor: Editor @@ -480,7 +480,7 @@ if (contextProvider === undefined) { remoteProvider.destroy() } - localProvider?.destroy() + void localProvider.destroy() }) diff --git a/plugins/text-editor-resources/src/provider/indexeddb.ts b/plugins/text-editor-resources/src/provider/indexeddb.ts new file mode 100644 index 0000000000..14b342ac81 --- /dev/null +++ b/plugins/text-editor-resources/src/provider/indexeddb.ts @@ -0,0 +1,32 @@ +// +// Copyright © 2024 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 { collaborativeDocParse, type CollaborativeDoc } from '@hcengineering/core' +import { type Doc as YDoc } from 'yjs' +import { IndexeddbPersistence } from 'y-indexeddb' + +export class IndexeddbProvider extends IndexeddbPersistence { + loaded: Promise + + constructor (collaborativeDoc: CollaborativeDoc, doc: YDoc) { + const { documentId, versionId } = collaborativeDocParse(collaborativeDoc) + const name = `${documentId}/${versionId}` + + super(name, doc) + + this.loaded = new Promise((resolve) => { + this.on('synced', resolve) + }) + } +} diff --git a/plugins/text-editor-resources/src/provider/storage.ts b/plugins/text-editor-resources/src/provider/storage.ts deleted file mode 100644 index fcd4cd3165..0000000000 --- a/plugins/text-editor-resources/src/provider/storage.ts +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright © 2023, 2024 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 { collaborativeDocParse, type Blob, type CollaborativeDoc, type Ref } from '@hcengineering/core' -import { getFileUrl } 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 = getFileUrl(_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]) - } - }) - } - } -}