Editor async loading, minor fixes
This commit is contained in:
parent
72c5b1bc70
commit
b2387543fc
|
@ -1,14 +1,14 @@
|
||||||
import { For, Show, createEffect, createSignal, onCleanup } 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 } from '../store/context'
|
import { Draft, useState } from '../store/context'
|
||||||
import { mod } from '../env'
|
|
||||||
import * as remote from '../remote'
|
import * as remote from '../remote'
|
||||||
import { isEmpty } from '../prosemirror/helpers'
|
import { isEmpty } from '../prosemirror/helpers'
|
||||||
import type { Styled } from './Layout'
|
import type { Styled } from './Layout'
|
||||||
import '../styles/Sidebar.scss'
|
import '../styles/Sidebar.scss'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import styles from './Sidebar.module.scss'
|
import styles from './Sidebar.module.scss'
|
||||||
|
import { isServer } from 'solid-js/web'
|
||||||
|
|
||||||
const Off = (props) => <div class="sidebar-off">{props.children}</div>
|
const Off = (props) => <div class="sidebar-off">{props.children}</div>
|
||||||
|
|
||||||
|
@ -141,6 +141,12 @@ export const Sidebar = () => {
|
||||||
onCleanup(() => clearTimeout(id))
|
onCleanup(() => clearTimeout(id))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [mod, setMod] = createSignal<'Ctrl' | 'Cmd'>('Ctrl')
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
setMod(navigator.platform.includes('Mac') ? 'Cmd' : 'Ctrl')
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={'sidebar-container' + (isHidden() ? ' sidebar-container--hidden' : '')}>
|
<div class={'sidebar-container' + (isHidden() ? ' sidebar-container--hidden' : '')}>
|
||||||
<span class="sidebar-opener" onClick={toggleSidebar}>
|
<span class="sidebar-opener" onClick={toggleSidebar}>
|
||||||
|
@ -149,55 +155,54 @@ export const Sidebar = () => {
|
||||||
|
|
||||||
<Off onClick={() => editorView().focus()}>
|
<Off onClick={() => editorView().focus()}>
|
||||||
<div class="sidebar-closer" onClick={toggleSidebar} />
|
<div class="sidebar-closer" onClick={toggleSidebar} />
|
||||||
<Show when={true}>
|
|
||||||
<div>
|
|
||||||
{store.path && (
|
|
||||||
<Label>
|
|
||||||
<i>({store.path.slice(Math.max(0, store.path.length - 24))})</i>
|
|
||||||
</Label>
|
|
||||||
)}
|
|
||||||
<Link>Пригласить соавторов</Link>
|
|
||||||
<Link>Настройки публикации</Link>
|
|
||||||
<Link>История правок</Link>
|
|
||||||
|
|
||||||
<div class="theme-switcher">
|
<div>
|
||||||
Ночная тема
|
{store.path && (
|
||||||
<input type="checkbox" name="theme" id="theme" onClick={toggleTheme} />
|
<Label>
|
||||||
<label for="theme">Ночная тема</label>
|
<i>({store.path.slice(Math.max(0, store.path.length - 24))})</i>
|
||||||
</div>
|
</Label>
|
||||||
<Link
|
)}
|
||||||
onClick={onDiscard}
|
<Link>Пригласить соавторов</Link>
|
||||||
disabled={!store.path && store.drafts.length === 0 && isEmpty(store.text)}
|
<Link>Настройки публикации</Link>
|
||||||
data-testid="discard"
|
<Link>История правок</Link>
|
||||||
>
|
|
||||||
{discardText()} <Keys keys={[mod, 'w']} />
|
<div class="theme-switcher">
|
||||||
</Link>
|
Ночная тема
|
||||||
<Link onClick={onUndo}>
|
<input type="checkbox" name="theme" id="theme" onClick={toggleTheme} />
|
||||||
Undo <Keys keys={[mod, 'z']} />
|
<label for="theme">Ночная тема</label>
|
||||||
</Link>
|
|
||||||
<Link onClick={onRedo}>
|
|
||||||
Redo <Keys keys={[mod, 'Shift', 'z']} />
|
|
||||||
</Link>
|
|
||||||
<Link onClick={onToggleMarkdown} data-testid="markdown">
|
|
||||||
Markdown mode {store.markdown && '✅'} <Keys keys={[mod, 'm']} />
|
|
||||||
</Link>
|
|
||||||
<Link onClick={onCopyAllAsMd}>Copy all as MD {lastAction() === 'copy-md' && '📋'}</Link>
|
|
||||||
<Show when={store.drafts.length > 0}>
|
|
||||||
<h4>Drafts:</h4>
|
|
||||||
<p>
|
|
||||||
<For each={store.drafts}>{(draft) => <DraftLink draft={draft} />}</For>
|
|
||||||
</p>
|
|
||||||
</Show>
|
|
||||||
<Link onClick={onCollab} title={store.collab?.error ? 'Connection error' : ''}>
|
|
||||||
Collab {collabText()}
|
|
||||||
</Link>
|
|
||||||
<Show when={collabUsers() > 0}>
|
|
||||||
<span>
|
|
||||||
{collabUsers()} {collabUsers() === 1 ? 'user' : 'users'} connected
|
|
||||||
</span>
|
|
||||||
</Show>
|
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
<Link
|
||||||
|
onClick={onDiscard}
|
||||||
|
disabled={!store.path && store.drafts.length === 0 && isEmpty(store.text)}
|
||||||
|
data-testid="discard"
|
||||||
|
>
|
||||||
|
{discardText()} <Keys keys={[mod(), 'w']} />
|
||||||
|
</Link>
|
||||||
|
<Link onClick={onUndo}>
|
||||||
|
Undo <Keys keys={[mod(), 'z']} />
|
||||||
|
</Link>
|
||||||
|
<Link onClick={onRedo}>
|
||||||
|
Redo <Keys keys={[mod(), 'Shift', 'z']} />
|
||||||
|
</Link>
|
||||||
|
<Link onClick={onToggleMarkdown} data-testid="markdown">
|
||||||
|
Markdown mode {store.markdown && '✅'} <Keys keys={[mod(), 'm']} />
|
||||||
|
</Link>
|
||||||
|
<Link onClick={onCopyAllAsMd}>Copy all as MD {lastAction() === 'copy-md' && '📋'}</Link>
|
||||||
|
<Show when={store.drafts.length > 0}>
|
||||||
|
<h4>Drafts:</h4>
|
||||||
|
<p>
|
||||||
|
<For each={store.drafts}>{(draft) => <DraftLink draft={draft} />}</For>
|
||||||
|
</p>
|
||||||
|
</Show>
|
||||||
|
<Link onClick={onCollab} title={store.collab?.error ? 'Connection error' : ''}>
|
||||||
|
Collab {collabText()}
|
||||||
|
</Link>
|
||||||
|
<Show when={collabUsers() > 0}>
|
||||||
|
<span>
|
||||||
|
{collabUsers()} {collabUsers() === 1 ? 'user' : 'users'} connected
|
||||||
|
</span>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
</Off>
|
</Off>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const dbPromise = async () => {
|
import { openDB } from 'idb'
|
||||||
const { openDB } = await import('idb')
|
|
||||||
|
const dbPromise = () => {
|
||||||
return openDB('discours.io', 2, {
|
return openDB('discours.io', 2, {
|
||||||
upgrade(db) {
|
upgrade(db) {
|
||||||
db.createObjectStore('keyval')
|
db.createObjectStore('keyval')
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
export const isDark = () => (window as any).matchMedia('(prefers-color-scheme: dark)').matches
|
export const isDark = () =>
|
||||||
export const mod = 'Ctrl'
|
typeof window !== undefined && window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
export const alt = 'Alt'
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { undo as yUndo, redo as yRedo } from 'y-prosemirror'
|
||||||
import debounce from 'lodash/debounce'
|
import debounce from 'lodash/debounce'
|
||||||
import { createSchema, createExtensions, createEmptyText } from '../prosemirror/setup'
|
import { createSchema, createExtensions, createEmptyText } from '../prosemirror/setup'
|
||||||
import { State, Draft, Config, ServiceError, newState, ExtensionsProps, EditorActions } from './context'
|
import { State, Draft, Config, ServiceError, newState, ExtensionsProps, EditorActions } from './context'
|
||||||
import { mod } from '../env'
|
|
||||||
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'
|
||||||
|
@ -102,13 +101,13 @@ export const createCtrl = (initial: State): [Store<State>, EditorActions] => {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
const keymap = {
|
const keymap: ExtensionsProps['keymap'] = {
|
||||||
[`${mod}-w`]: discard,
|
[`Mod-w`]: discard,
|
||||||
[`${mod}-z`]: onUndo,
|
[`Mod-z`]: onUndo,
|
||||||
[`Shift-${mod}-z`]: onRedo,
|
[`Shift-Mod-z`]: onRedo,
|
||||||
[`${mod}-y`]: onRedo,
|
[`Mod-y`]: onRedo,
|
||||||
[`${mod}-m`]: toggleMarkdown
|
[`Mod-m`]: toggleMarkdown
|
||||||
} as ExtensionsProps['keymap']
|
}
|
||||||
|
|
||||||
const createTextFromDraft = async (draft: Draft) => {
|
const createTextFromDraft = async (draft: Draft) => {
|
||||||
const state = unwrap(store)
|
const state = unwrap(store)
|
||||||
|
|
|
@ -63,7 +63,6 @@ export interface Collab {
|
||||||
export type LoadingType = 'loading' | 'initialized'
|
export type LoadingType = 'loading' | 'initialized'
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
isMac?: boolean
|
|
||||||
text?: ProseMirrorState
|
text?: ProseMirrorState
|
||||||
editorView?: EditorView
|
editorView?: EditorView
|
||||||
extensions?: ProseMirrorExtension[]
|
extensions?: ProseMirrorExtension[]
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
.index {
|
|
||||||
width: 350px;
|
|
||||||
}
|
|
|
@ -134,7 +134,7 @@ export const Header = (props: Props) => {
|
||||||
<div class={styles.usernav}>
|
<div class={styles.usernav}>
|
||||||
<div class={clsx(styles.userControl, styles.userControl, 'col')}>
|
<div class={clsx(styles.userControl, styles.userControl, 'col')}>
|
||||||
<div class={clsx(styles.userControlItem, styles.userControlItemWritePost)}>
|
<div class={clsx(styles.userControlItem, styles.userControlItemWritePost)}>
|
||||||
<a href="/create">
|
<a href="/create" onClick={handleClientRouteLinkClick}>
|
||||||
<span class={styles.textLabel}>{t('Create post')}</span>
|
<span class={styles.textLabel}>{t('Create post')}</span>
|
||||||
<Icon name="pencil" class={styles.icon} />
|
<Icon name="pencil" class={styles.icon} />
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import { newState } from '../Editor/store/context'
|
import { lazy, Suspense } from 'solid-js'
|
||||||
import { MainLayout } from '../Layouts/MainLayout'
|
import { MainLayout } from '../Layouts/MainLayout'
|
||||||
import { CreateView } from '../Views/Create'
|
import { Loading } from '../Loading'
|
||||||
|
|
||||||
|
const CreateView = lazy(() => import('../Views/Create'))
|
||||||
|
|
||||||
export const CreatePage = () => {
|
export const CreatePage = () => {
|
||||||
return (
|
return (
|
||||||
<MainLayout>
|
<MainLayout>
|
||||||
<CreateView state={newState()} />
|
<Suspense fallback={<Loading />}>
|
||||||
|
<CreateView />
|
||||||
|
</Suspense>
|
||||||
</MainLayout>
|
</MainLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Show, onCleanup, createEffect, onError, onMount, untrack } from 'solid-js'
|
import { Show, onCleanup, createEffect, onError, onMount, untrack } from 'solid-js'
|
||||||
import { createMutable, unwrap } from 'solid-js/store'
|
import { createMutable, unwrap } from 'solid-js/store'
|
||||||
import { State, StateContext } from '../Editor/store/context'
|
import { State, StateContext, newState } from '../Editor/store/context'
|
||||||
import { createCtrl } from '../Editor/store/actions'
|
import { createCtrl } from '../Editor/store/actions'
|
||||||
import { Layout } from '../Editor/components/Layout'
|
import { Layout } from '../Editor/components/Layout'
|
||||||
import { Editor } from '../Editor/components/Editor'
|
import { Editor } from '../Editor/components/Editor'
|
||||||
|
@ -9,16 +9,14 @@ import ErrorView from '../Editor/components/Error'
|
||||||
|
|
||||||
const matchDark = () => window.matchMedia('(prefers-color-scheme: dark)')
|
const matchDark = () => window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
|
|
||||||
export const CreateView = (props: { state: State }) => {
|
export const CreateView = () => {
|
||||||
let isMac = false
|
|
||||||
const onChangeTheme = () => ctrl.updateTheme()
|
const onChangeTheme = () => ctrl.updateTheme()
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
isMac = window?.navigator.platform.includes('Mac')
|
|
||||||
matchDark().addEventListener('change', onChangeTheme)
|
matchDark().addEventListener('change', onChangeTheme)
|
||||||
onCleanup(() => matchDark().removeEventListener('change', onChangeTheme))
|
onCleanup(() => matchDark().removeEventListener('change', onChangeTheme))
|
||||||
})
|
})
|
||||||
|
|
||||||
const [store, ctrl] = createCtrl({ ...props.state, isMac })
|
const [store, ctrl] = createCtrl(newState())
|
||||||
const mouseEnterCoords = createMutable({ x: 0, y: 0 })
|
const mouseEnterCoords = createMutable({ x: 0, y: 0 })
|
||||||
|
|
||||||
const onMouseEnter = (e: MouseEvent) => {
|
const onMouseEnter = (e: MouseEvent) => {
|
||||||
|
@ -66,3 +64,5 @@ export const CreateView = (props: { state: State }) => {
|
||||||
</StateContext.Provider>
|
</StateContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default CreateView
|
||||||
|
|
Loading…
Reference in New Issue
Block a user