collab-toggle
All checks were successful
deploy / testbuild (push) Successful in 2m17s
deploy / Update templates on Mailgun (push) Has been skipped

This commit is contained in:
Untone 2024-10-12 01:24:05 +03:00
parent 83c660235a
commit 5c7f810c5f

View File

@ -1,9 +1,14 @@
import { HocuspocusProvider } from '@hocuspocus/provider'
import { useMatch, useNavigate } from '@solidjs/router'
import { Editor } from '@tiptap/core'
import Collaboration from '@tiptap/extension-collaboration'
import CollaborationCursor from '@tiptap/extension-collaboration-cursor'
import type { JSX } from 'solid-js'
import { Accessor, createContext, createSignal, onCleanup, useContext } from 'solid-js'
import { Accessor, createContext, createEffect, createSignal, on, onCleanup, useContext } from 'solid-js'
import { SetStoreFunction, createStore } from 'solid-js/store'
import { debounce } from 'throttle-debounce'
import uniqolor from 'uniqolor'
import { Doc } from 'yjs'
import { useSnackbar } from '~/context/ui'
import deleteShoutQuery from '~/graphql/mutation/core/article-delete'
import updateShoutQuery from '~/graphql/mutation/core/article-update'
@ -14,6 +19,8 @@ import { useLocalize } from './localize'
import { useSession } from './session'
export const AUTO_SAVE_DELAY = 3000
const yDocs: Record<string, Doc> = {}
const providers: Record<string, HocuspocusProvider> = {}
export type WordCounter = {
characters: number
@ -98,7 +105,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => {
const navigate = useNavigate()
const matchEdit = useMatch(() => '/edit')
const matchEditSettings = useMatch(() => '/editSettings')
const { client } = useSession()
const { client, session } = useSession()
const { addFeed } = useFeed()
const snackbar = useSnackbar()
const [isEditorPanelVisible, setIsEditorPanelVisible] = createSignal<boolean>(false)
@ -251,7 +258,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => {
}
} catch (error) {
console.error('[publishShoutById]', error)
snackbar?.showSnackbar({ type: 'error', body: localize?.t('Error') })
snackbar?.showSnackbar({ type: 'error', body: localize?.t('Error') || '' })
}
}
@ -278,6 +285,63 @@ export const EditorProvider = (props: { children: JSX.Element }) => {
})
onCleanup(debouncedAutoSave.cancel)
createEffect(
on(
isCollabMode,
(x?: boolean) => () => {
const editorInstance = editing()
if (!editorInstance) return
try {
const docName = `shout-${form.shoutId}`
const token = session()?.access_token || ''
const profile = session()?.user?.app_data?.profile
if (!(token && profile)) {
throw new Error('Missing authentication data')
}
if (!yDocs[docName]) {
yDocs[docName] = new Doc()
}
if (!providers[docName]) {
providers[docName] = new HocuspocusProvider({
url: 'wss://hocuspocus.discours.io',
name: docName,
document: yDocs[docName],
token
})
console.log(`[collab mode] HocuspocusProvider connected for ${docName}`)
}
if (x) {
const newExtensions = [
Collaboration.configure({ document: yDocs[docName] }),
CollaborationCursor.configure({
provider: providers[docName],
user: { name: profile.name, color: uniqolor(profile.slug).color }
})
]
const extensions = editing()?.options.extensions.concat(newExtensions)
editorInstance.setOptions({ ...editorInstance.options, extensions })
providers[docName].connect()
} else if (editorInstance) {
providers[docName].disconnect()
const updatedExtensions = editorInstance.options.extensions.filter(
(ext) => ext.name !== 'collaboration' && ext.name !== 'collaborationCursor'
)
editorInstance.setOptions({
...editorInstance.options,
extensions: updatedExtensions
})
}
} catch (error) {
console.error('[collab mode] error', error)
}
},
{ defer: true }
)
)
const handleInputChange = (key: keyof ShoutForm, value: string) => {
console.log(`[handleInputChange] ${key}: ${value}`)
setForm(key, value)