-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathstore.ts
136 lines (122 loc) · 3.97 KB
/
store.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { createStore, atom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
import { assertExists, DisposableGroup, Workspace } from '@blocksuite/store'
import { atomWithObservable } from 'jotai/utils'
// @ts-expect-error
import { createIndexedDBProvider } from '@toeverything/y-indexeddb'
import { AffineSchemas } from '@blocksuite/blocks/models'
import type { EditorContainer } from '@blocksuite/editor'
import type { PageMeta } from '@blocksuite/store'
import { initPage, WorkspaceNotFoundError } from './utils.ts'
import { Observable, from } from 'rxjs'
import { filter, mergeMap } from 'rxjs/operators'
const editorContainerAtom = atom<Promise<typeof EditorContainer>>(async () => {
const { EditorContainer } = await import('@blocksuite/editor')
return EditorContainer
})
export const rootStore = createStore()
// if the value is `null`, it means the user has not created any workspace yet
export const workspaceIdsAtom = atomWithStorage<string[] | null>('workspaces', null)
// hotfix for jotai #1813
rootStore.sub(workspaceIdsAtom, () => {})
workspaceIdsAtom.onMount = (set) => {
if (localStorage.getItem('workspaces') === null) {
set([
'demo-workspace'
])
}
}
export const currentWorkspaceIdAtom = atom<string | null>(null)
export const currentPageIdAtom = atom<string | null>(null)
const hashMap = new Map<string, Workspace>()
export const currentWorkspaceAtom = atom<Promise<Workspace | null>>(
async (get, {
signal
}) => {
const ids = get(workspaceIdsAtom)
const id = get(currentWorkspaceIdAtom)
console.log(ids)
if (!id) return null
if (ids === null) {
return null
}
if (ids.indexOf(id) === -1) {
throw new WorkspaceNotFoundError('workspace not found')
}
let workspace = hashMap.get(id)
if (!workspace) {
workspace = new Workspace({
id
})
workspace.register(AffineSchemas)
hashMap.set(id, workspace)
}
const provider = createIndexedDBProvider(workspace.id, workspace.doc)
assertExists(provider)
provider.connect()
provider.whenSynced.then(() => {
assertExists(workspace)
if (workspace.isEmpty) {
const page = workspace.createPage({
id: 'page0'
})
initPage(page)
} else {
const page = workspace.getPage('page0')
assertExists(page)
}
})
await provider.whenSynced
if (signal.aborted) {
provider.disconnect()
return null
}
signal.addEventListener('abort', () => {
provider.disconnect()
})
return workspace
})
export const currentPageMetaAtom = atomWithObservable<PageMeta[]>(
(get) => {
return from(get(currentWorkspaceAtom)).pipe(
filter((workspace): workspace is Workspace => workspace !== null),
mergeMap(workspace => {
const group = new DisposableGroup()
return new Observable<PageMeta[]>((subscriber) => {
group.add(workspace.slots.pageAdded.on(() => {
subscriber.next(workspace.meta.pageMetas)
}))
group.add(workspace.slots.pageRemoved.on(() => {
subscriber.next(workspace.meta.pageMetas)
}))
subscriber.next(workspace.meta.pageMetas)
return () => {
group.dispose()
}
})
})
)
})
export const editorAtom = atom<Promise<EditorContainer | null>>(async (get) => {
const workspace = await get(currentWorkspaceAtom)
const pageId = get(currentPageIdAtom)
if (!workspace || !pageId) return null
const EditorContainer = await get(editorContainerAtom)
const editor = new EditorContainer()
const page = workspace.getPage(pageId)
if (!page) {
return null
}
editor.page = page
return editor
})
if (typeof window !== 'undefined') {
const workspaceId = window.location.pathname.split('/')[1]
const pageId = window.location.pathname.split('/')[2]
if (workspaceId) {
rootStore.set(currentWorkspaceIdAtom, workspaceId)
}
if (pageId) {
rootStore.set(currentPageIdAtom, pageId)
}
}