fix-state

This commit is contained in:
tonyrewin 2022-10-18 18:50:49 +03:00
parent 23c8bba3fd
commit 05cdf42c05
10 changed files with 77 additions and 91 deletions

View File

@ -1,3 +1,6 @@
[0.6.0]
[+] editor enabled
[0.5.1]
[+] nanostores-base global store
[-] Root.tsx components

View File

@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 1H18V-1H2V1ZM19 2V18H21V2H19ZM18 19H2V21H18V19ZM1 18V2H-1V18H1ZM2 19C1.44772 19 1 18.5523 1 18H-1C-1 19.6569 0.343147 21 2 21V19ZM19 18C19 18.5523 18.5523 19 18 19V21C19.6569 21 21 19.6569 21 18H19ZM18 1C18.5523 1 19 1.44772 19 2H21C21 0.343146 19.6569 -1 18 -1V1ZM2 -1C0.343146 -1 -1 0.343147 -1 2H1C1 1.44772 1.44772 1 2 1V-1Z" fill="#141414"/>
</svg>

Before

Width:  |  Height:  |  Size: 462 B

View File

@ -5,7 +5,7 @@ import { ProseMirror } from '../components/ProseMirror'
import '../styles/Editor.scss'
import type { ProseMirrorExtension, ProseMirrorState } from '../prosemirror/helpers'
export default () => {
export const Editor = () => {
const [store, ctrl] = useState()
const onInit = (text: EditorState, editorView: EditorView) => ctrl.setState({ editorView, text })
const onReconfigure = (text: EditorState) => ctrl.setState({ text })

View File

@ -51,9 +51,9 @@ export const Sidebar = (_props: SidebarProps) => {
}
const collabText = () => {
if (store.collab?.started) {
return 'Stop'
return t('Stop collab')
} else {
return store.collab?.error ? t('Restart') : t('Start')
return store.collab?.error ? t('Restart collab') : t('Start collab')
}
}
const editorView = () => unwrap(store.editorView)
@ -142,7 +142,7 @@ export const Sidebar = (_props: SidebarProps) => {
</Show>
<Link onClick={onCollab} title={store.collab?.error ? 'Connection error' : ''}>
{t('Collab')} {collabText()}
{collabText()}
</Link>
<Show when={collabUsers() > 0}>
<span>

View File

@ -1,25 +0,0 @@
import './styles/Editor.scss'
import type { EditorView } from 'prosemirror-view'
import type { EditorState } from 'prosemirror-state'
import { useState } from './store'
import { ProseMirror } from './components/ProseMirror'
export const Editor = () => {
const [store, ctrl] = useState()
const onInit = (text: EditorState, editorView: EditorView) => ctrl.setState({ editorView, text })
const onReconfigure = (text: EditorState) => ctrl.setState({ text })
const onChange = (text: EditorState) => ctrl.setState({ text, lastModified: new Date() })
return (
<ProseMirror
// eslint-disable-next-line solid/no-react-specific-props
className="editor"
style={store.markdown && `white-space: pre-wrap;`}
editorView={store.editorView}
text={store.text}
extensions={store.extensions}
onInit={onInit}
onReconfigure={onReconfigure}
onChange={onChange}
/>
)
}

View File

@ -8,6 +8,10 @@ import { setReactions } from '../../../stores/editor'
export const roomConnect = (room, username = '', keyname = 'collab'): [XmlFragment, WebrtcProvider] => {
const ydoc = new Doc()
const yarr = ydoc.getArray(keyname + '-reactions')
yarr.observeDeep(() => {
console.debug('[p2p] yarray updated', yarr.toArray())
setReactions(yarr.toArray() as Reaction[])
})
const yXmlFragment = ydoc.getXmlFragment(keyname)
const webrtcOptions = {
awareness: new Awareness(ydoc),
@ -22,23 +26,20 @@ export const roomConnect = (room, username = '', keyname = 'collab'): [XmlFragme
peerOpts: {},
password: ''
}
// connect with provider
const provider = new WebrtcProvider(room, ydoc, webrtcOptions)
let name = username
yarr.observeDeep(() => {
console.debug('yarray updated:', yarr.toArray())
setReactions(yarr.toArray() as Reaction[])
})
if (Boolean(name) === false) {
name = uniqueNamesGenerator({
console.debug('[p2p] provider', provider)
// setting username
provider.awareness.setLocalStateField('user', {
name:
username ??
uniqueNamesGenerator({
dictionaries: [adjectives, animals],
style: 'capital',
separator: ' ',
length: 2
})
}
})
provider.awareness.setLocalStateField('user', { name })
return [yXmlFragment, provider]
}

View File

@ -176,7 +176,7 @@ export const createCtrl = (initial): [Store<State>, { [key: string]: any }] => {
}
}
const getTheme = (state: State) => ({ theme: state.config.theme })
const getTheme = (state: State) => ({ theme: state.config?.theme || '' })
const clean = () => {
setState({
@ -204,7 +204,7 @@ export const createCtrl = (initial): [Store<State>, { [key: string]: any }] => {
let state = await readStoredState()
console.log('[editor] init with state', state)
try {
if (state.args.room) {
if (state.args?.room) {
state = await doStartCollab(state)
} else if (state.args.text) {
state = await doOpenDraft(state, {
@ -354,10 +354,11 @@ export const createCtrl = (initial): [Store<State>, { [key: string]: any }] => {
}
const doStartCollab = async (state: State): Promise<State> => {
const backup = state.args?.room && state.collab?.room !== state.args.room
const restoredRoom = state.args?.room && state.collab?.room !== state.args.room
const room = state.args?.room ?? uuidv4()
state.args.room = room
window.history.replaceState(null, '', `/${room}`)
state.args = { ...state.args, room }
let newst = state
try {
const { roomConnect } = await import('../prosemirror/p2p')
const [type, provider] = roomConnect(room)
@ -370,8 +371,7 @@ export const createCtrl = (initial): [Store<State>, { [key: string]: any }] => {
collab: true
})
let newst = state
if ((backup && !isEmpty(state.text as EditorState)) || state.path) {
if ((restoredRoom && !isEmpty(state.text as EditorState)) || state.path) {
let drafts = state.drafts
if (!state.error) {
drafts = addToDrafts(drafts, { lastModified: new Date(), text: state.text } as Draft)
@ -384,6 +384,7 @@ export const createCtrl = (initial): [Store<State>, { [key: string]: any }] => {
path: undefined,
error: undefined
}
window.history.replaceState(null, '', `/${room}`)
}
return {
@ -391,6 +392,13 @@ export const createCtrl = (initial): [Store<State>, { [key: string]: any }] => {
extensions,
collab: { started: true, room, y: { type, provider } }
}
} catch (error) {
console.error(error)
return {
...state,
collab: { error }
}
}
}
const stopCollab = (state: State) => {

View File

@ -1,10 +1,11 @@
import { newState } from '../Editor/store'
import { MainLayout } from '../Layouts/MainLayout'
import { CreateView } from '../Views/Create'
export const CreatePage = () => {
return (
<MainLayout>
<CreateView />
<CreateView state={newState()} />
</MainLayout>
)
}

View File

@ -1,14 +1,16 @@
import { Show, onCleanup, createEffect, onError, onMount, untrack } from 'solid-js'
import { createMutable, unwrap } from 'solid-js/store'
import { State, StateContext, newState } from '../Editor/store'
import { State, StateContext } from '../Editor/store'
import { createCtrl } from '../Editor/store/ctrl'
import { Layout } from '../Editor/components/Layout'
import { Editor } from '../Editor'
import { Editor } from '../Editor/components/Editor'
import { Sidebar } from '../Editor/components/Sidebar'
import ErrorView from '../Editor/components/Error'
export const CreateView = () => {
const [store, ctrl] = createCtrl(newState())
const matchDark = () => window.matchMedia('(prefers-color-scheme: dark)')
export const CreateView = (props: { state: State }) => {
const [store, ctrl] = createCtrl(props.state)
const mouseEnterCoords = createMutable({ x: 0, y: 0 })
const onMouseEnter = (e: MouseEvent) => {
@ -25,10 +27,10 @@ export const CreateView = () => {
await ctrl.init()
})
const onChangeTheme = () => ctrl.updateTheme()
onMount(() => {
const mediaQuery = '(prefers-color-scheme: dark)'
window.matchMedia(mediaQuery).addEventListener('change', ctrl.updateTheme)
onCleanup(() => window.matchMedia(mediaQuery).removeEventListener('change', ctrl.updateTheme))
matchDark().addEventListener('change', onChangeTheme)
onCleanup(() => matchDark().removeEventListener('change', onChangeTheme))
})
onError((error) => {

View File

@ -157,10 +157,9 @@
"History of changes": "История правок",
"Undo": "Откат",
"Redo": "Повторить действие",
"Start": "Начать",
"Stop": "Остановить",
"Restart": "Перезапустить",
"Stop collab": "Индивидуальный режим",
"Restart collab": "Перезапустить коллаборацию",
"Start collab": "Коллаборативный режим",
"Clear": "Сбросить",
"Collab": "Совместно",
"Режим": "Theme"
}