postmerge, unstore drafts
This commit is contained in:
parent
c652c4ee84
commit
634c8ae59c
|
@ -9,7 +9,6 @@ export const Editor = () => {
|
||||||
const onInit = (text: EditorState, editorView: EditorView) => ctrl.setState({ editorView, text })
|
const onInit = (text: EditorState, editorView: EditorView) => ctrl.setState({ editorView, text })
|
||||||
const onReconfigure = (text: EditorState) => ctrl.setState({ text })
|
const onReconfigure = (text: EditorState) => ctrl.setState({ text })
|
||||||
const onChange = (text: EditorState) => ctrl.setState({ text, lastModified: new Date() })
|
const onChange = (text: EditorState) => ctrl.setState({ text, lastModified: new Date() })
|
||||||
// const editorCss = (config) => css``
|
|
||||||
const style = () => {
|
const style = () => {
|
||||||
if (store.error) {
|
if (store.error) {
|
||||||
return `display: none;`
|
return `display: none;`
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Switch, Match } from 'solid-js'
|
import { Switch, Match } from 'solid-js'
|
||||||
import { useState } from '../store/context'
|
|
||||||
import '../styles/Button.scss'
|
import '../styles/Button.scss'
|
||||||
|
import { ErrorObject, useState } from '../store/context'
|
||||||
|
import { t } from '../../../utils/intl'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const [store] = useState()
|
const [store] = useState()
|
||||||
|
@ -28,15 +29,13 @@ const InvalidState = (props: { title: string }) => {
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>{props.title}</h1>
|
<h1>{props.title}</h1>
|
||||||
<p>
|
<p>
|
||||||
There is an error with the editor state. This is probably due to an old version in which the data
|
{t('Editing conflict, please copy your notes and refresh page')}
|
||||||
structure has changed. Automatic data migrations may be supported in the future. To fix this now,
|
|
||||||
you can copy important notes from below, clean the state and paste it again.
|
|
||||||
</p>
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
<code>{JSON.stringify(store.error.props)}</code>
|
<code>{JSON.stringify(store.error.props)}</code>
|
||||||
</pre>
|
</pre>
|
||||||
<button class="primary" onClick={onClick}>
|
<button class="primary" onClick={onClick}>
|
||||||
Clean
|
{t('Clean')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -48,7 +47,7 @@ const Other = () => {
|
||||||
const onClick = () => ctrl.discard()
|
const onClick = () => ctrl.discard()
|
||||||
|
|
||||||
const getMessage = () => {
|
const getMessage = () => {
|
||||||
const err = (store.error.props as any).error
|
const err = (store.error.props as ErrorObject['props']).error
|
||||||
return typeof err === 'string' ? err : err.message
|
return typeof err === 'string' ? err : err.message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ export type Styled = {
|
||||||
config?: Config
|
config?: Config
|
||||||
'data-testid'?: string
|
'data-testid'?: string
|
||||||
onClick?: () => void
|
onClick?: () => void
|
||||||
onMouseEnter?: (e: any) => void
|
onMouseEnter?: (ev: MouseEvent) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Layout = (props: Styled) => {
|
export const Layout = (props: Styled) => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { For, Show, createEffect, createSignal, onCleanup, onMount } from 'solid-js'
|
import { For, Show, createEffect, createSignal, onCleanup, onMount } from 'solid-js'
|
||||||
import { unwrap } from 'solid-js/store'
|
import { unwrap } from 'solid-js/store'
|
||||||
import { undo, redo } from 'prosemirror-history'
|
import { undo, redo } from 'prosemirror-history'
|
||||||
import { Draft, useState /*, Config, PrettierConfig */ } from '../store/context'
|
import { Draft, useState } from '../store/context'
|
||||||
import * as remote from '../remote'
|
import * as remote from '../remote'
|
||||||
import { isEmpty /*, isInitialized*/ } from '../prosemirror/helpers'
|
import { isEmpty /*, isInitialized*/ } from '../prosemirror/helpers'
|
||||||
import type { Styled } from './Layout'
|
import type { Styled } from './Layout'
|
||||||
|
|
|
@ -122,7 +122,7 @@ export const markdownSerializer = new MarkdownSerializer(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
function listIsTight(tokens: any, idx: number) {
|
function listIsTight(tokens: any[], idx: number) {
|
||||||
let i = idx
|
let i = idx
|
||||||
while (++i < tokens.length) {
|
while (++i < tokens.length) {
|
||||||
if (tokens[i].type !== 'list_item_open') return tokens[i].hidden
|
if (tokens[i].type !== 'list_item_open') return tokens[i].hidden
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { DOMSerializer, Node as ProsemirrorNode, NodeType, Schema } from 'prosemirror-model'
|
import { DOMSerializer, Node as ProsemirrorNode, NodeType, Schema } from 'prosemirror-model'
|
||||||
import type { EditorView } from 'prosemirror-view'
|
|
||||||
import { inputRules, wrappingInputRule } from 'prosemirror-inputrules'
|
import { inputRules, wrappingInputRule } from 'prosemirror-inputrules'
|
||||||
import { splitListItem } from 'prosemirror-schema-list'
|
import { splitListItem } from 'prosemirror-schema-list'
|
||||||
import { keymap } from 'prosemirror-keymap'
|
import { keymap } from 'prosemirror-keymap'
|
||||||
|
import type { EditorView } from 'prosemirror-view'
|
||||||
import type { ProseMirrorExtension } from '../helpers'
|
import type { ProseMirrorExtension } from '../helpers'
|
||||||
|
|
||||||
const todoListRule = (nodeType: NodeType) =>
|
const todoListRule = (nodeType: NodeType) =>
|
||||||
|
|
|
@ -5,13 +5,16 @@ import { Doc, XmlFragment } from 'yjs'
|
||||||
import type { Reaction } from '../../../graphql/types.gen'
|
import type { Reaction } from '../../../graphql/types.gen'
|
||||||
import { setReactions } from '../../../stores/editor'
|
import { setReactions } from '../../../stores/editor'
|
||||||
|
|
||||||
export const roomConnect = (room, username = '', keyname = 'collab'): [XmlFragment, WebrtcProvider] => {
|
export const roomConnect = (room: string, username = '', keyname = 'collab'): [XmlFragment, WebrtcProvider] => {
|
||||||
const ydoc = new Doc()
|
const ydoc = new Doc()
|
||||||
const yarr = ydoc.getArray(keyname + '-reactions')
|
const yarr = ydoc.getArray(keyname + '-reactions')
|
||||||
|
|
||||||
|
// TODO: use reactions
|
||||||
yarr.observeDeep(() => {
|
yarr.observeDeep(() => {
|
||||||
console.debug('[p2p] yarray updated', yarr.toArray())
|
console.debug('[p2p] yarray updated', yarr.toArray())
|
||||||
setReactions(yarr.toArray() as Reaction[])
|
setReactions(yarr.toArray() as Reaction[])
|
||||||
})
|
})
|
||||||
|
|
||||||
const yXmlFragment = ydoc.getXmlFragment(keyname)
|
const yXmlFragment = ydoc.getXmlFragment(keyname)
|
||||||
const webrtcOptions = {
|
const webrtcOptions = {
|
||||||
awareness: new Awareness(ydoc),
|
awareness: new Awareness(ydoc),
|
||||||
|
|
|
@ -19,6 +19,7 @@ import type { Command } from 'prosemirror-state'
|
||||||
import placeholder from './extension/placeholder'
|
import placeholder from './extension/placeholder'
|
||||||
import todoList from './extension/todo-list'
|
import todoList from './extension/todo-list'
|
||||||
import strikethrough from './extension/strikethrough'
|
import strikethrough from './extension/strikethrough'
|
||||||
|
import scrollPlugin from './extension/scroll'
|
||||||
|
|
||||||
interface ExtensionsProps {
|
interface ExtensionsProps {
|
||||||
data?: unknown
|
data?: unknown
|
||||||
|
@ -29,6 +30,7 @@ interface ExtensionsProps {
|
||||||
y?: YOptions
|
y?: YOptions
|
||||||
schema?: Schema
|
schema?: Schema
|
||||||
collab?: boolean
|
collab?: boolean
|
||||||
|
typewriterMode?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const customKeymap = (props: ExtensionsProps): ProseMirrorExtension => ({
|
const customKeymap = (props: ExtensionsProps): ProseMirrorExtension => ({
|
||||||
|
@ -37,11 +39,11 @@ const customKeymap = (props: ExtensionsProps): ProseMirrorExtension => ({
|
||||||
|
|
||||||
export const createExtensions = (props: ExtensionsProps): ProseMirrorExtension[] => {
|
export const createExtensions = (props: ExtensionsProps): ProseMirrorExtension[] => {
|
||||||
const eee = [
|
const eee = [
|
||||||
// scroll(props.config.typewriterMode),
|
|
||||||
placeholder(t('Just start typing...')),
|
placeholder(t('Just start typing...')),
|
||||||
customKeymap(props),
|
customKeymap(props),
|
||||||
base(props.markdown),
|
base(props.markdown),
|
||||||
selectionMenu()
|
selectionMenu(),
|
||||||
|
scrollPlugin(props.config?.typewriterMode)
|
||||||
]
|
]
|
||||||
if (props.markdown) {
|
if (props.markdown) {
|
||||||
eee.push(
|
eee.push(
|
||||||
|
|
|
@ -10,9 +10,7 @@ import { State, Draft, Config, ServiceError, newState } from './context'
|
||||||
import { serialize, createMarkdownParser } from '../markdown'
|
import { serialize, createMarkdownParser } from '../markdown'
|
||||||
import db from '../db'
|
import db from '../db'
|
||||||
import { isEmpty, isInitialized } from '../prosemirror/helpers'
|
import { isEmpty, isInitialized } from '../prosemirror/helpers'
|
||||||
import { drafts as draftsatom } from '../../../stores/editor'
|
import { createSignal } from 'solid-js'
|
||||||
import { useStore } from '@nanostores/solid'
|
|
||||||
import { createMemo } from 'solid-js'
|
|
||||||
|
|
||||||
const isText = (x) => x && x.doc && x.selection
|
const isText = (x) => x && x.doc && x.selection
|
||||||
const isDraft = (x): boolean => x && (x.text || x.path)
|
const isDraft = (x): boolean => x && (x.text || x.path)
|
||||||
|
@ -239,8 +237,7 @@ export const createCtrl = (initial): [Store<State>, { [key: string]: any }] => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadDraft = async (config: Config, path: string): Promise<Draft> => {
|
const loadDraft = async (config: Config, path: string): Promise<Draft> => {
|
||||||
const draftstore = useStore(draftsatom)
|
const [draft, setDraft] = createSignal<Draft>()
|
||||||
const draft = createMemo(() => draftstore()[path])
|
|
||||||
const schema = createSchema({
|
const schema = createSchema({
|
||||||
config,
|
config,
|
||||||
markdown: false,
|
markdown: false,
|
||||||
|
@ -334,9 +331,9 @@ export const createCtrl = (initial): [Store<State>, { [key: string]: any }] => {
|
||||||
|
|
||||||
if (isInitialized(state.text as EditorState)) {
|
if (isInitialized(state.text as EditorState)) {
|
||||||
if (state.path) {
|
if (state.path) {
|
||||||
// const text = serialize(store.editorView.state)
|
const text = serialize(store.editorView.state)
|
||||||
|
// TODO: saving draft logix here
|
||||||
// await remote.writeDraft(state.path, text)
|
// await remote.writeDraft(state.path, text)
|
||||||
draftsatom.setKey(state.path, store.editorView.state)
|
|
||||||
} else {
|
} else {
|
||||||
data.text = store.editorView.state.toJSON()
|
data.text = store.editorView.state.toJSON()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ export interface Args {
|
||||||
cwd?: string
|
cwd?: string
|
||||||
draft?: string
|
draft?: string
|
||||||
room?: string
|
room?: string
|
||||||
text?: any
|
text?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PrettierConfig {
|
export interface PrettierConfig {
|
||||||
|
@ -23,17 +23,17 @@ export interface PrettierConfig {
|
||||||
export interface Config {
|
export interface Config {
|
||||||
theme: string
|
theme: string
|
||||||
// codeTheme: string;
|
// codeTheme: string;
|
||||||
|
// alwaysOnTop: boolean;
|
||||||
font: string
|
font: string
|
||||||
fontSize: number
|
fontSize: number
|
||||||
contentWidth: number
|
contentWidth: number
|
||||||
// alwaysOnTop: boolean;
|
typewriterMode?: boolean;
|
||||||
// typewriterMode: boolean;
|
|
||||||
prettier: PrettierConfig
|
prettier: PrettierConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ErrorObject {
|
export interface ErrorObject {
|
||||||
id: string
|
id: string
|
||||||
props?: unknown
|
props?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface YOptions {
|
export interface YOptions {
|
||||||
|
@ -78,7 +78,7 @@ export interface Draft {
|
||||||
|
|
||||||
export class ServiceError extends Error {
|
export class ServiceError extends Error {
|
||||||
public errorObject: ErrorObject
|
public errorObject: ErrorObject
|
||||||
constructor(id: string, props: unknown) {
|
constructor(id: string, props: any) {
|
||||||
super(id)
|
super(id)
|
||||||
this.errorObject = { id, props }
|
this.errorObject = { id, props }
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ const matchDark = () => window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
|
|
||||||
export const CreateView = (props: { state: State }) => {
|
export const CreateView = (props: { state: State }) => {
|
||||||
let isMac = false
|
let isMac = false
|
||||||
|
const onChangeTheme = () => ctrl.updateTheme()
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
isMac = window?.navigator.platform.includes('Mac')
|
isMac = window?.navigator.platform.includes('Mac')
|
||||||
matchDark().addEventListener('change', onChangeTheme)
|
matchDark().addEventListener('change', onChangeTheme)
|
||||||
|
@ -34,8 +35,6 @@ export const CreateView = (props: { state: State }) => {
|
||||||
await ctrl.init()
|
await ctrl.init()
|
||||||
})
|
})
|
||||||
|
|
||||||
const onChangeTheme = () => ctrl.updateTheme()
|
|
||||||
|
|
||||||
onError((error) => {
|
onError((error) => {
|
||||||
console.error('[create] error:', error)
|
console.error('[create] error:', error)
|
||||||
ctrl.setState({ error: { id: 'exception', props: { error } } })
|
ctrl.setState({ error: { id: 'exception', props: { error } } })
|
||||||
|
|
|
@ -162,5 +162,6 @@
|
||||||
"Restart collab": "Перезапустить коллаборацию",
|
"Restart collab": "Перезапустить коллаборацию",
|
||||||
"Start collab": "Коллаборативный режим",
|
"Start collab": "Коллаборативный режим",
|
||||||
"Clear": "Сбросить",
|
"Clear": "Сбросить",
|
||||||
"Режим": "Theme"
|
"Theme": "Режим",
|
||||||
|
"Editing conflict, please copy your version and refresh page": "Конфликт редактирования, пожалуйста, скопируйте вашу версию текста и обновите страницу"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user