mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: split create document and open document (#2261)
* fix: add method * fix: update text block and doc title
This commit is contained in:
parent
3b1152615a
commit
07947db98b
10
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
10
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
@ -576,7 +576,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab"
|
name = "collab"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#dd49b08fae2ad008844409c7ce6b8c754446955c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#986737b4125162ae94dbeb6ece8267714f67b1dd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -594,7 +594,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-derive"
|
name = "collab-derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#dd49b08fae2ad008844409c7ce6b8c754446955c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#986737b4125162ae94dbeb6ece8267714f67b1dd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -606,7 +606,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-document"
|
name = "collab-document"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#dd49b08fae2ad008844409c7ce6b8c754446955c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#986737b4125162ae94dbeb6ece8267714f67b1dd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -622,7 +622,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-folder"
|
name = "collab-folder"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#dd49b08fae2ad008844409c7ce6b8c754446955c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#986737b4125162ae94dbeb6ece8267714f67b1dd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -640,7 +640,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-persistence"
|
name = "collab-persistence"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#dd49b08fae2ad008844409c7ce6b8c754446955c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#986737b4125162ae94dbeb6ece8267714f67b1dd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useDocumentTitle } from './DocumentTitle.hooks';
|
import { useDocumentTitle } from './DocumentTitle.hooks';
|
||||||
import TextBlock from '../TextBlock';
|
import TextBlock from '../TextBlock';
|
||||||
|
import { NodeContext } from '../_shared/SubscribeNode.hooks';
|
||||||
|
|
||||||
export default function DocumentTitle({ id }: { id: string }) {
|
export default function DocumentTitle({ id }: { id: string }) {
|
||||||
const { node } = useDocumentTitle(id);
|
const { node } = useDocumentTitle(id);
|
||||||
if (!node) return null;
|
if (!node) return null;
|
||||||
return (
|
return (
|
||||||
<div data-block-id={node.id} className='doc-title relative pt-[50px] text-4xl font-bold'>
|
<NodeContext.Provider value={node}>
|
||||||
<TextBlock placeholder='Untitled' childIds={[]} node={{
|
<div data-block-id={node.id} className='doc-title relative pt-[50px] text-4xl font-bold'>
|
||||||
...node,
|
<TextBlock placeholder='Untitled' childIds={[]} node={node} />
|
||||||
data: {
|
</div>
|
||||||
...node.data,
|
</NodeContext.Provider>
|
||||||
delta: node.data.delta || [],
|
|
||||||
}
|
|
||||||
}} />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import { withErrorBoundary } from 'react-error-boundary';
|
|||||||
import { ErrorBoundaryFallbackComponent } from '../_shared/ErrorBoundaryFallbackComponent';
|
import { ErrorBoundaryFallbackComponent } from '../_shared/ErrorBoundaryFallbackComponent';
|
||||||
import { Node } from '@/appflowy_app/stores/reducers/document/slice';
|
import { Node } from '@/appflowy_app/stores/reducers/document/slice';
|
||||||
import TextBlock from '../TextBlock';
|
import TextBlock from '../TextBlock';
|
||||||
import { TextDelta } from '@/appflowy_app/interfaces/document';
|
import { NodeContext } from '../_shared/SubscribeNode.hooks';
|
||||||
|
|
||||||
function NodeComponent({ id, ...props }: { id: string } & React.HTMLAttributes<HTMLDivElement>) {
|
function NodeComponent({ id, ...props }: { id: string } & React.HTMLAttributes<HTMLDivElement>) {
|
||||||
const { node, childIds, isSelected, ref } = useNode(id);
|
const { node, childIds, isSelected, ref } = useNode(id);
|
||||||
@ -13,19 +13,7 @@ function NodeComponent({ id, ...props }: { id: string } & React.HTMLAttributes<H
|
|||||||
const renderBlock = useCallback((_props: { node: Node; childIds?: string[] }) => {
|
const renderBlock = useCallback((_props: { node: Node; childIds?: string[] }) => {
|
||||||
switch (_props.node.type) {
|
switch (_props.node.type) {
|
||||||
case 'text': {
|
case 'text': {
|
||||||
const delta = _props.node.data.delta;
|
return <TextBlock node={node} childIds={childIds} />;
|
||||||
if (!delta) return null;
|
|
||||||
return (
|
|
||||||
<TextBlock
|
|
||||||
node={{
|
|
||||||
..._props.node,
|
|
||||||
data: {
|
|
||||||
delta,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
childIds={childIds}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -35,14 +23,16 @@ function NodeComponent({ id, ...props }: { id: string } & React.HTMLAttributes<H
|
|||||||
if (!node) return null;
|
if (!node) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...props} ref={ref} data-block-id={node.id} className={`relative my-[2px] px-[2px] ${props.className}`}>
|
<NodeContext.Provider value={node}>
|
||||||
{renderBlock({
|
<div {...props} ref={ref} data-block-id={node.id} className={`relative my-[2px] px-[2px] ${props.className}`}>
|
||||||
node,
|
{renderBlock({
|
||||||
childIds,
|
node,
|
||||||
})}
|
childIds,
|
||||||
<div className='block-overlay' />
|
})}
|
||||||
{isSelected ? <div className='pointer-events-none absolute inset-0 z-[-1] rounded-[4px] bg-[#E0F8FF]' /> : null}
|
<div className='block-overlay' />
|
||||||
</div>
|
{isSelected ? <div className='pointer-events-none absolute inset-0 z-[-1] rounded-[4px] bg-[#E0F8FF]' /> : null}
|
||||||
|
</div>
|
||||||
|
</NodeContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ function Root({ documentData }: { documentData: DocumentData }) {
|
|||||||
return <Skeleton />;
|
return <Skeleton />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='appflowy-block-doc' className='h-[100%] overflow-hidden'>
|
<div id='appflowy-block-doc' className='h-[100%] overflow-hidden'>
|
||||||
<VirtualizedList node={node} childIds={childIds} renderNode={renderNode} />
|
<VirtualizedList node={node} childIds={childIds} renderNode={renderNode} />
|
||||||
|
@ -4,8 +4,7 @@ import { useTextBlock } from './TextBlock.hooks';
|
|||||||
import { Node } from '@/appflowy_app/stores/reducers/document/slice';
|
import { Node } from '@/appflowy_app/stores/reducers/document/slice';
|
||||||
import NodeComponent from '../Node';
|
import NodeComponent from '../Node';
|
||||||
import HoveringToolbar from '../_shared/HoveringToolbar';
|
import HoveringToolbar from '../_shared/HoveringToolbar';
|
||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { TextDelta } from '@/appflowy_app/interfaces/document';
|
|
||||||
|
|
||||||
function TextBlock({
|
function TextBlock({
|
||||||
node,
|
node,
|
||||||
@ -13,11 +12,12 @@ function TextBlock({
|
|||||||
placeholder,
|
placeholder,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
node: Node & { data: { delta: TextDelta[] } };
|
node: Node;
|
||||||
childIds?: string[];
|
childIds?: string[];
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
} & React.HTMLAttributes<HTMLDivElement>) {
|
} & React.HTMLAttributes<HTMLDivElement>) {
|
||||||
const { editor, value, onChange, onKeyDownCapture, onDOMBeforeInput } = useTextBlock(node.data.delta);
|
const delta = useMemo(() => node.data.delta || [], [node.data.delta]);
|
||||||
|
const { editor, value, onChange, onKeyDownCapture, onDOMBeforeInput } = useTextBlock(delta);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...props} className={`py-[2px] ${props.className}`}>
|
<div {...props} className={`py-[2px] ${props.className}`}>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Node } from '@/appflowy_app/stores/reducers/document/slice';
|
import { Node } from '@/appflowy_app/stores/reducers/document/slice';
|
||||||
import { useAppSelector } from '@/appflowy_app/stores/store';
|
import { useAppSelector } from '@/appflowy_app/stores/store';
|
||||||
import { useMemo } from 'react';
|
import { useMemo, createContext } from 'react';
|
||||||
|
export const NodeContext = createContext<Node | null>(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribe to a node and its children
|
* Subscribe to a node and its children
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { useCallback, useContext, useMemo, useRef, useEffect } from 'react';
|
import { useCallback, useContext, useMemo, useRef, useEffect } from 'react';
|
||||||
import { DocumentControllerContext } from '$app/stores/effects/document/document_controller';
|
import { DocumentControllerContext } from '$app/stores/effects/document/document_controller';
|
||||||
import { TextDelta } from '$app/interfaces/document';
|
import { TextDelta, BlockActionType } from '$app/interfaces/document';
|
||||||
import { debounce } from '@/appflowy_app/utils/tool';
|
import { debounce } from '@/appflowy_app/utils/tool';
|
||||||
import { createEditor } from 'slate';
|
import { createEditor } from 'slate';
|
||||||
import { withReact } from 'slate-react';
|
import { withReact } from 'slate-react';
|
||||||
|
|
||||||
import * as Y from 'yjs';
|
import * as Y from 'yjs';
|
||||||
import { withYjs, YjsEditor, slateNodesToInsertDelta } from '@slate-yjs/core';
|
import { withYjs, YjsEditor, slateNodesToInsertDelta } from '@slate-yjs/core';
|
||||||
|
import { NodeContext } from './SubscribeNode.hooks';
|
||||||
|
import { BlockActionTypePB } from '@/services/backend/models/flowy-document2';
|
||||||
|
|
||||||
export function useTextInput(delta: TextDelta[]) {
|
export function useTextInput(delta: TextDelta[]) {
|
||||||
const { sendDelta } = useTransact();
|
const { sendDelta } = useTransact();
|
||||||
@ -19,23 +21,30 @@ export function useTextInput(delta: TextDelta[]) {
|
|||||||
|
|
||||||
function useController() {
|
function useController() {
|
||||||
const docController = useContext(DocumentControllerContext);
|
const docController = useContext(DocumentControllerContext);
|
||||||
|
const node = useContext(NodeContext);
|
||||||
|
|
||||||
const update = useCallback(
|
const update = useCallback(
|
||||||
(delta: TextDelta[]) => {
|
async (delta: TextDelta[]) => {
|
||||||
docController?.applyActions([
|
if (!docController || !node) return;
|
||||||
|
await docController.applyActions([
|
||||||
{
|
{
|
||||||
type: 'update',
|
action: BlockActionTypePB.Update,
|
||||||
payload: {
|
payload: {
|
||||||
block: {
|
block: {
|
||||||
data: {
|
id: node.id,
|
||||||
|
ty: node.type,
|
||||||
|
parent_id: node.parent || '',
|
||||||
|
children_id: node.children,
|
||||||
|
data: JSON.stringify({
|
||||||
|
...node.data,
|
||||||
delta,
|
delta,
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
[docController]
|
[docController, node]
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -48,7 +57,7 @@ function useTransact() {
|
|||||||
|
|
||||||
const sendDelta = useCallback(
|
const sendDelta = useCallback(
|
||||||
(delta: TextDelta[]) => {
|
(delta: TextDelta[]) => {
|
||||||
update(delta);
|
void update(delta);
|
||||||
},
|
},
|
||||||
[update]
|
[update]
|
||||||
);
|
);
|
||||||
@ -99,7 +108,6 @@ function useBindYjs(delta: TextDelta[], update: (_delta: TextDelta[]) => void) {
|
|||||||
|
|
||||||
const textEventHandler = (event: Y.YTextEvent) => {
|
const textEventHandler = (event: Y.YTextEvent) => {
|
||||||
const textDelta = event.target.toDelta();
|
const textDelta = event.target.toDelta();
|
||||||
console.log('delta', textDelta);
|
|
||||||
update(textDelta);
|
update(textDelta);
|
||||||
};
|
};
|
||||||
yText.applyDelta(delta);
|
yText.applyDelta(delta);
|
||||||
|
@ -10,6 +10,8 @@ import { AppObserver } from '../../../stores/effects/folder/app/app_observer';
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { INITIAL_FOLDER_HEIGHT, PAGE_ITEM_HEIGHT } from '../../_shared/constants';
|
import { INITIAL_FOLDER_HEIGHT, PAGE_ITEM_HEIGHT } from '../../_shared/constants';
|
||||||
|
|
||||||
|
import { DocumentController } from '$app/stores/effects/document/document_controller';
|
||||||
|
|
||||||
export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
|
export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
|
||||||
const appDispatch = useAppDispatch();
|
const appDispatch = useAppDispatch();
|
||||||
const workspace = useAppSelector((state) => state.workspace);
|
const workspace = useAppSelector((state) => state.workspace);
|
||||||
@ -115,19 +117,24 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
|
|||||||
name: 'New Document 1',
|
name: 'New Document 1',
|
||||||
layoutType: ViewLayoutPB.Document,
|
layoutType: ViewLayoutPB.Document,
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
|
await new DocumentController(newView.id).create();
|
||||||
|
appDispatch(
|
||||||
|
pagesActions.addPage({
|
||||||
|
folderId: folder.id,
|
||||||
|
pageType: ViewLayoutPB.Document,
|
||||||
|
title: newView.name,
|
||||||
|
id: newView.id,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
appDispatch(
|
setShowPages(true);
|
||||||
pagesActions.addPage({
|
|
||||||
folderId: folder.id,
|
|
||||||
pageType: ViewLayoutPB.Document,
|
|
||||||
title: newView.name,
|
|
||||||
id: newView.id,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
setShowPages(true);
|
navigate(`/page/document/${newView.id}`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
navigate(`/page/document/${newView.id}`);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAddNewBoardPage = async () => {
|
const onAddNewBoardPage = async () => {
|
||||||
|
@ -41,3 +41,11 @@ export interface DocumentData {
|
|||||||
childrenMap: Record<string, string[]>;
|
childrenMap: Record<string, string[]>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
export enum BlockActionType {
|
||||||
|
Insert = 0,
|
||||||
|
Update = 1,
|
||||||
|
Delete = 2,
|
||||||
|
Move = 3
|
||||||
|
}
|
||||||
|
@ -1,29 +1,30 @@
|
|||||||
import {
|
import {
|
||||||
DocumentDataPB,
|
|
||||||
DocumentVersionPB,
|
|
||||||
EditPayloadPB,
|
|
||||||
FlowyError,
|
FlowyError,
|
||||||
OpenDocumentPayloadPB,
|
|
||||||
DocumentDataPB2,
|
DocumentDataPB2,
|
||||||
ViewIdPB,
|
|
||||||
OpenDocumentPayloadPBV2,
|
OpenDocumentPayloadPBV2,
|
||||||
|
CreateDocumentPayloadPBV2,
|
||||||
ApplyActionPayloadPBV2,
|
ApplyActionPayloadPBV2,
|
||||||
BlockActionTypePB,
|
|
||||||
BlockActionPB,
|
BlockActionPB,
|
||||||
CloseDocumentPayloadPBV2,
|
CloseDocumentPayloadPBV2,
|
||||||
} from '@/services/backend';
|
} from '@/services/backend';
|
||||||
import { DocumentEventApplyEdit, DocumentEventGetDocument } from '@/services/backend/events/flowy-document';
|
|
||||||
import { Result } from 'ts-results';
|
import { Result } from 'ts-results';
|
||||||
import { FolderEventCloseView } from '@/services/backend/events/flowy-folder2';
|
|
||||||
import {
|
import {
|
||||||
DocumentEvent2ApplyAction,
|
DocumentEvent2ApplyAction,
|
||||||
DocumentEvent2CloseDocument,
|
DocumentEvent2CloseDocument,
|
||||||
DocumentEvent2OpenDocument,
|
DocumentEvent2OpenDocument,
|
||||||
|
DocumentEvent2CreateDocument,
|
||||||
} from '@/services/backend/events/flowy-document2';
|
} from '@/services/backend/events/flowy-document2';
|
||||||
|
|
||||||
export class DocumentBackendService {
|
export class DocumentBackendService {
|
||||||
constructor(public readonly viewId: string) {}
|
constructor(public readonly viewId: string) {}
|
||||||
|
|
||||||
|
create = (): Promise<Result<void, FlowyError>> => {
|
||||||
|
const payload = CreateDocumentPayloadPBV2.fromObject({
|
||||||
|
document_id: this.viewId,
|
||||||
|
});
|
||||||
|
return DocumentEvent2CreateDocument(payload);
|
||||||
|
};
|
||||||
|
|
||||||
open = (): Promise<Result<DocumentDataPB2, FlowyError>> => {
|
open = (): Promise<Result<DocumentDataPB2, FlowyError>> => {
|
||||||
const payload = OpenDocumentPayloadPBV2.fromObject({
|
const payload = OpenDocumentPayloadPBV2.fromObject({
|
||||||
document_id: this.viewId,
|
document_id: this.viewId,
|
||||||
@ -31,7 +32,7 @@ export class DocumentBackendService {
|
|||||||
return DocumentEvent2OpenDocument(payload);
|
return DocumentEvent2OpenDocument(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
applyActions = (actions: [BlockActionPB]): Promise<Result<void, FlowyError>> => {
|
applyActions = (actions: ReturnType<typeof BlockActionPB.prototype.toObject>[]): Promise<Result<void, FlowyError>> => {
|
||||||
const payload = ApplyActionPayloadPBV2.fromObject({
|
const payload = ApplyActionPayloadPBV2.fromObject({
|
||||||
document_id: this.viewId,
|
document_id: this.viewId,
|
||||||
actions: actions,
|
actions: actions,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { DocumentData, BlockType } from '@/appflowy_app/interfaces/document';
|
import { DocumentData, BlockType } from '@/appflowy_app/interfaces/document';
|
||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
import { DocumentBackendService } from './document_bd_svc';
|
import { DocumentBackendService } from './document_bd_svc';
|
||||||
import { FlowyError } from '@/services/backend';
|
import { FlowyError, BlockActionPB } from '@/services/backend';
|
||||||
import { DocumentObserver } from './document_observer';
|
import { DocumentObserver } from './document_observer';
|
||||||
|
|
||||||
export const DocumentControllerContext = createContext<DocumentController | null>(null);
|
export const DocumentControllerContext = createContext<DocumentController | null>(null);
|
||||||
@ -15,51 +15,62 @@ export class DocumentController {
|
|||||||
this.observer = new DocumentObserver(viewId);
|
this.observer = new DocumentObserver(viewId);
|
||||||
}
|
}
|
||||||
|
|
||||||
open = async (): Promise<DocumentData | FlowyError> => {
|
create = async (): Promise<FlowyError | void> => {
|
||||||
// example:
|
const result = await this.backendService.create();
|
||||||
|
if (result.ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return result.val;
|
||||||
|
};
|
||||||
|
open = async (): Promise<DocumentData> => {
|
||||||
await this.observer.subscribe({
|
await this.observer.subscribe({
|
||||||
didReceiveUpdate: () => {
|
didReceiveUpdate: this.updated,
|
||||||
console.log('didReceiveUpdate');
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const document = await this.backendService.open();
|
const document = await this.backendService.open();
|
||||||
if (document.ok) {
|
if (document.ok) {
|
||||||
console.log(document.val);
|
const blocks: DocumentData['blocks'] = {};
|
||||||
const blocks: DocumentData["blocks"] = {};
|
|
||||||
document.val.blocks.forEach((block) => {
|
document.val.blocks.forEach((block) => {
|
||||||
|
let data = {};
|
||||||
|
try {
|
||||||
|
data = JSON.parse(block.data);
|
||||||
|
} catch {
|
||||||
|
console.log('json parse error', block.data);
|
||||||
|
}
|
||||||
|
|
||||||
blocks[block.id] = {
|
blocks[block.id] = {
|
||||||
id: block.id,
|
id: block.id,
|
||||||
type: block.ty as BlockType,
|
type: block.ty as BlockType,
|
||||||
parent: block.parent_id,
|
parent: block.parent_id,
|
||||||
children: block.children_id,
|
children: block.children_id,
|
||||||
data: JSON.parse(block.data),
|
data,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const childrenMap: Record<string, string[]> = {};
|
const childrenMap: Record<string, string[]> = {};
|
||||||
document.val.meta.children_map.forEach((child, key) => { childrenMap[key] = child.children; });
|
document.val.meta.children_map.forEach((child, key) => {
|
||||||
|
childrenMap[key] = child.children;
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
rootId: document.val.page_id,
|
rootId: document.val.page_id,
|
||||||
blocks,
|
blocks,
|
||||||
meta: {
|
meta: {
|
||||||
childrenMap
|
childrenMap,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
return document.val;
|
|
||||||
|
|
||||||
|
return Promise.reject(document.val);
|
||||||
};
|
};
|
||||||
|
|
||||||
applyActions = (
|
applyActions = async (actions: ReturnType<typeof BlockActionPB.prototype.toObject>[]) => {
|
||||||
actions: {
|
await this.backendService.applyActions(actions);
|
||||||
type: string;
|
|
||||||
payload: any;
|
|
||||||
}[]
|
|
||||||
) => {
|
|
||||||
//
|
|
||||||
};
|
};
|
||||||
|
|
||||||
dispose = async () => {
|
dispose = async () => {
|
||||||
await this.backendService.close();
|
await this.backendService.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private updated = (payload: Uint8Array) => {
|
||||||
|
console.log('didReceiveUpdate', payload);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import { FolderNotificationObserver } from '../folder/notifications/observer';
|
|||||||
import { DocumentNotification } from '@/services/backend';
|
import { DocumentNotification } from '@/services/backend';
|
||||||
import { DocumentNotificationObserver } from './notifications/observer';
|
import { DocumentNotificationObserver } from './notifications/observer';
|
||||||
|
|
||||||
export type DidReceiveUpdateCallback = () => void; // todo: add params
|
export type DidReceiveUpdateCallback = (payload: Uint8Array) => void; // todo: add params
|
||||||
|
|
||||||
export class DocumentObserver {
|
export class DocumentObserver {
|
||||||
private listener?: DocumentNotificationObserver;
|
private listener?: DocumentNotificationObserver;
|
||||||
@ -17,8 +17,9 @@ export class DocumentObserver {
|
|||||||
parserHandler: (notification, result) => {
|
parserHandler: (notification, result) => {
|
||||||
switch (notification) {
|
switch (notification) {
|
||||||
case DocumentNotification.DidReceiveUpdate:
|
case DocumentNotification.DidReceiveUpdate:
|
||||||
callbacks.didReceiveUpdate();
|
if (!result.ok) break;
|
||||||
// Fixme: ...
|
callbacks.didReceiveUpdate(result.val);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -20,12 +20,16 @@ export const useDocument = () => {
|
|||||||
if (!params?.id) return;
|
if (!params?.id) return;
|
||||||
const c = new DocumentController(params.id);
|
const c = new DocumentController(params.id);
|
||||||
setController(c);
|
setController(c);
|
||||||
const res = await c.open();
|
try {
|
||||||
console.log(res)
|
const res = await c.open();
|
||||||
if (!res) return;
|
console.log(res)
|
||||||
// setDocumentData(res)
|
if (!res) return;
|
||||||
setDocumentId(params.id)
|
setDocumentData(res);
|
||||||
|
setDocumentId(params.id);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
return () => {
|
return () => {
|
||||||
console.log('==== leave ====', params?.id)
|
console.log('==== leave ====', params?.id)
|
||||||
|
50
frontend/rust-lib/Cargo.lock
generated
50
frontend/rust-lib/Cargo.lock
generated
@ -113,7 +113,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -124,7 +124,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -817,7 +817,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"scratch",
|
"scratch",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -834,7 +834,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1792,7 +1792,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1916,9 +1916,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.3.16"
|
version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
|
checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
@ -2064,9 +2064,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.14.25"
|
version = "0.14.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
|
checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
@ -2668,7 +2668,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2808,7 +2808,7 @@ dependencies = [
|
|||||||
"pest_meta",
|
"pest_meta",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3027,9 +3027,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prost"
|
name = "prost"
|
||||||
version = "0.11.8"
|
version = "0.11.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
|
checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"prost-derive",
|
"prost-derive",
|
||||||
@ -3037,9 +3037,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prost-derive"
|
name = "prost-derive"
|
||||||
version = "0.11.8"
|
version = "0.11.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
|
checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"itertools",
|
"itertools",
|
||||||
@ -3050,9 +3050,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prost-types"
|
name = "prost-types"
|
||||||
version = "0.11.8"
|
version = "0.11.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88"
|
checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"prost",
|
"prost",
|
||||||
]
|
]
|
||||||
@ -3631,14 +3631,14 @@ checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.95"
|
version = "1.0.96"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744"
|
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@ -3653,7 +3653,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3846,9 +3846,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.14"
|
version = "2.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fcf316d5356ed6847742d036f8a39c3b8435cac10bd528a4bd461928a6ab34d5"
|
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -3942,7 +3942,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4039,7 +4039,7 @@ checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.14",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -20,8 +20,8 @@ use crate::entities::{BlockPB, ChildrenPB, DocumentDataPB2, MetaPB};
|
|||||||
pub struct Document(Arc<Mutex<InnerDocument>>);
|
pub struct Document(Arc<Mutex<InnerDocument>>);
|
||||||
|
|
||||||
impl Document {
|
impl Document {
|
||||||
pub fn new(collab: Collab, data: DocumentDataWrapper) -> FlowyResult<Self> {
|
pub fn new(collab: Collab) -> FlowyResult<Self> {
|
||||||
let inner = InnerDocument::create(collab, data.0)
|
let inner = InnerDocument::create(collab)
|
||||||
.map_err(|_| FlowyError::from(ErrorCode::DocumentDataInvalid))?;
|
.map_err(|_| FlowyError::from(ErrorCode::DocumentDataInvalid))?;
|
||||||
Ok(Self(Arc::new(Mutex::new(inner))))
|
Ok(Self(Arc::new(Mutex::new(inner))))
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,13 @@ pub struct OpenDocumentPayloadPBV2 {
|
|||||||
// Support customize initial data
|
// Support customize initial data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, ProtoBuf)]
|
||||||
|
pub struct CreateDocumentPayloadPBV2 {
|
||||||
|
#[pb(index = 1)]
|
||||||
|
pub document_id: String,
|
||||||
|
// Support customize initial data
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, ProtoBuf)]
|
#[derive(Default, ProtoBuf)]
|
||||||
pub struct CloseDocumentPayloadPBV2 {
|
pub struct CloseDocumentPayloadPBV2 {
|
||||||
#[pb(index = 1)]
|
#[pb(index = 1)]
|
||||||
@ -102,3 +109,21 @@ impl Default for BlockActionTypePB {
|
|||||||
Self::Insert
|
Self::Insert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, ProtoBuf)]
|
||||||
|
pub struct DocEventPB {
|
||||||
|
#[pb(index = 1)]
|
||||||
|
pub events: Vec<BlockEventPB>,
|
||||||
|
|
||||||
|
#[pb(index = 2)]
|
||||||
|
pub is_remote: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, ProtoBuf)]
|
||||||
|
pub struct BlockEventPB {
|
||||||
|
#[pb(index = 1)]
|
||||||
|
pub path: Vec<String>,
|
||||||
|
|
||||||
|
#[pb(index = 2)]
|
||||||
|
pub delta: String,
|
||||||
|
}
|
||||||
|
@ -4,13 +4,14 @@ use crate::{
|
|||||||
document::DocumentDataWrapper,
|
document::DocumentDataWrapper,
|
||||||
entities::{
|
entities::{
|
||||||
ApplyActionPayloadPBV2, BlockActionPB, BlockActionPayloadPB, BlockActionTypePB,
|
ApplyActionPayloadPBV2, BlockActionPB, BlockActionPayloadPB, BlockActionTypePB,
|
||||||
BlockPB, CloseDocumentPayloadPBV2, DocumentDataPB2, OpenDocumentPayloadPBV2,
|
BlockPB, CloseDocumentPayloadPBV2, DocumentDataPB2, OpenDocumentPayloadPBV2, CreateDocumentPayloadPBV2,
|
||||||
|
BlockEventPB
|
||||||
},
|
},
|
||||||
manager::DocumentManager,
|
manager::DocumentManager,
|
||||||
};
|
};
|
||||||
|
|
||||||
use collab_document::blocks::{
|
use collab_document::blocks::{
|
||||||
json_str_to_hashmap, Block, BlockAction, BlockActionPayload, BlockActionType,
|
json_str_to_hashmap, Block, BlockAction, BlockActionPayload, BlockActionType, BlockEvent
|
||||||
};
|
};
|
||||||
use flowy_error::{FlowyError, FlowyResult};
|
use flowy_error::{FlowyError, FlowyResult};
|
||||||
use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult};
|
use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult};
|
||||||
@ -27,6 +28,16 @@ pub(crate) async fn open_document_handler(
|
|||||||
data_result_ok(DocumentDataPB2::from(DocumentDataWrapper(document_data)))
|
data_result_ok(DocumentDataPB2::from(DocumentDataWrapper(document_data)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn create_document_handler(
|
||||||
|
data: AFPluginData<CreateDocumentPayloadPBV2>,
|
||||||
|
manager: AFPluginState<Arc<DocumentManager>>,
|
||||||
|
) -> FlowyResult<()> {
|
||||||
|
let context = data.into_inner();
|
||||||
|
let data = DocumentDataWrapper::default();
|
||||||
|
manager.create_document(context.document_id, data)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn close_document_handler(
|
pub(crate) async fn close_document_handler(
|
||||||
data: AFPluginData<CloseDocumentPayloadPBV2>,
|
data: AFPluginData<CloseDocumentPayloadPBV2>,
|
||||||
manager: AFPluginState<Arc<DocumentManager>>,
|
manager: AFPluginState<Arc<DocumentManager>>,
|
||||||
@ -96,3 +107,13 @@ impl From<BlockPB> for Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<BlockEvent> for BlockEventPB {
|
||||||
|
fn from(block_event: BlockEvent) -> Self {
|
||||||
|
let delta = serde_json::to_value(&block_event.delta).unwrap();
|
||||||
|
Self {
|
||||||
|
path: block_event.path.into(),
|
||||||
|
delta: delta.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@ use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
|||||||
use lib_dispatch::prelude::AFPlugin;
|
use lib_dispatch::prelude::AFPlugin;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
event_handler::{apply_action_handler, close_document_handler, open_document_handler},
|
event_handler::{apply_action_handler, close_document_handler, open_document_handler, create_document_handler },
|
||||||
manager::DocumentManager,
|
manager::DocumentManager,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17,6 +17,7 @@ pub fn init(document_manager: Arc<DocumentManager>) -> AFPlugin {
|
|||||||
plugin = plugin.event(DocumentEvent2::OpenDocument, open_document_handler);
|
plugin = plugin.event(DocumentEvent2::OpenDocument, open_document_handler);
|
||||||
plugin = plugin.event(DocumentEvent2::CloseDocument, close_document_handler);
|
plugin = plugin.event(DocumentEvent2::CloseDocument, close_document_handler);
|
||||||
plugin = plugin.event(DocumentEvent2::ApplyAction, apply_action_handler);
|
plugin = plugin.event(DocumentEvent2::ApplyAction, apply_action_handler);
|
||||||
|
plugin = plugin.event(DocumentEvent2::CreateDocument, create_document_handler);
|
||||||
|
|
||||||
plugin
|
plugin
|
||||||
}
|
}
|
||||||
@ -32,4 +33,7 @@ pub enum DocumentEvent2 {
|
|||||||
|
|
||||||
#[event(input = "ApplyActionPayloadPBV2")]
|
#[event(input = "ApplyActionPayloadPBV2")]
|
||||||
ApplyAction = 2,
|
ApplyAction = 2,
|
||||||
|
|
||||||
|
#[event(input = "CreateDocumentPayloadPBV2")]
|
||||||
|
CreateDocument = 3,
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use parking_lot::RwLock;
|
|||||||
use crate::{
|
use crate::{
|
||||||
document::{Document, DocumentDataWrapper},
|
document::{Document, DocumentDataWrapper},
|
||||||
notification::{send_notification, DocumentNotification},
|
notification::{send_notification, DocumentNotification},
|
||||||
|
entities::{DocEventPB, BlockEventPB},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait DocumentUser: Send + Sync {
|
pub trait DocumentUser: Send + Sync {
|
||||||
@ -32,23 +33,45 @@ impl DocumentManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_document(&self, doc_id: String, data: DocumentDataWrapper) -> FlowyResult<Arc<Document>> {
|
||||||
|
self.get_document(doc_id, Some(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_document(&self, doc_id: String, data: Option<DocumentDataWrapper>) -> FlowyResult<Arc<Document>> {
|
||||||
|
let collab = self.get_collab_for_doc_id(&doc_id)?;
|
||||||
|
let document = Arc::new(Document::new(collab)?);
|
||||||
|
self.documents.write().insert(doc_id, document.clone());
|
||||||
|
if data.is_some() {
|
||||||
|
// Here use unwrap() is safe, because we have checked data.is_some() before.
|
||||||
|
document.lock().create_with_data(data.unwrap().0).map_err(|err| FlowyError::internal().context(err))?;
|
||||||
|
}
|
||||||
|
Ok(document)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn open_document(&self, doc_id: String) -> FlowyResult<Arc<Document>> {
|
pub fn open_document(&self, doc_id: String) -> FlowyResult<Arc<Document>> {
|
||||||
if let Some(doc) = self.documents.read().get(&doc_id) {
|
if let Some(doc) = self.documents.read().get(&doc_id) {
|
||||||
return Ok(doc.clone());
|
return Ok(doc.clone());
|
||||||
}
|
}
|
||||||
let collab = self.get_collab_for_doc_id(&doc_id)?;
|
|
||||||
let data = DocumentDataWrapper::default();
|
|
||||||
let document = Arc::new(Document::new(collab, data)?);
|
|
||||||
|
|
||||||
|
let document = self.get_document(doc_id.clone(), None)?;
|
||||||
let clone_doc_id = doc_id.clone();
|
let clone_doc_id = doc_id.clone();
|
||||||
let _document_data = document
|
let _document_data = document
|
||||||
.lock()
|
.lock()
|
||||||
.open(move |_, _| {
|
.open(move |events, is_remote| {
|
||||||
// TODO: add payload data.
|
println!("events: {:?}", events);
|
||||||
send_notification(&clone_doc_id, DocumentNotification::DidReceiveUpdate).send();
|
println!("is_remote: {:?}", is_remote);
|
||||||
|
send_notification(&clone_doc_id, DocumentNotification::DidReceiveUpdate)
|
||||||
|
.payload(DocEventPB {
|
||||||
|
events: events
|
||||||
|
.iter()
|
||||||
|
.map(|event| event.to_owned().into())
|
||||||
|
.collect::<Vec<BlockEventPB>>(),
|
||||||
|
is_remote: is_remote.to_owned(),
|
||||||
|
})
|
||||||
|
.send();
|
||||||
|
|
||||||
})
|
})
|
||||||
.map_err(|err| FlowyError::internal().context(err))?;
|
.map_err(|err| FlowyError::internal().context(err))?;
|
||||||
self.documents.write().insert(doc_id, document.clone());
|
|
||||||
Ok(document)
|
Ok(document)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user