mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
feat(core): mode in query string (#7904)
This commit is contained in:
@@ -81,6 +81,7 @@
|
||||
"mixpanel-browser": "^2.49.0",
|
||||
"nanoid": "^5.0.7",
|
||||
"next-themes": "^0.3.0",
|
||||
"query-string": "^9.1.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-error-boundary": "^4.0.13",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Entity, LiveData } from '@toeverything/infra';
|
||||
import type { Location, To } from 'history';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import queryString from 'query-string';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { createNavigableHistory } from '../../../utils/navigable-history';
|
||||
@@ -77,6 +79,52 @@ export class View extends Entity<{
|
||||
|
||||
icon$ = new LiveData(this.props.icon ?? 'allDocs');
|
||||
|
||||
queryString$<T extends Record<string, unknown>>({
|
||||
parseNumbers = true,
|
||||
}: { parseNumbers?: boolean } = {}) {
|
||||
return this.location$.map(
|
||||
location =>
|
||||
queryString.parse(location.search, {
|
||||
parseBooleans: true,
|
||||
parseNumbers: parseNumbers,
|
||||
}) as Partial<T>
|
||||
);
|
||||
}
|
||||
|
||||
updateQueryString<T extends Record<string, unknown>>(
|
||||
patch: Partial<T>,
|
||||
{
|
||||
forceUpdate,
|
||||
parseNumbers,
|
||||
replace,
|
||||
}: {
|
||||
forceUpdate?: boolean;
|
||||
parseNumbers?: boolean;
|
||||
replace?: boolean;
|
||||
} = {}
|
||||
) {
|
||||
const oldQueryStrings = queryString.parse(location.search, {
|
||||
parseBooleans: true,
|
||||
parseNumbers: parseNumbers,
|
||||
});
|
||||
const newQueryStrings = { ...oldQueryStrings, ...patch };
|
||||
|
||||
if (forceUpdate || !isEqual(oldQueryStrings, newQueryStrings)) {
|
||||
const search = queryString.stringify(newQueryStrings);
|
||||
|
||||
const newState = {
|
||||
...this.history.location,
|
||||
search,
|
||||
};
|
||||
|
||||
if (replace) {
|
||||
this.history.replace(newState);
|
||||
} else {
|
||||
this.history.push(newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
push(path: To) {
|
||||
this.history.push(path);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import type { Editor } from '@affine/core/modules/editor';
|
||||
import { EditorService, EditorsService } from '@affine/core/modules/editor';
|
||||
import { RecentDocsService } from '@affine/core/modules/quicksearch';
|
||||
import { ViewService } from '@affine/core/modules/workbench/services/view';
|
||||
import type { PageRootService } from '@blocksuite/blocks';
|
||||
import type { DocMode, PageRootService } from '@blocksuite/blocks';
|
||||
import {
|
||||
BookmarkBlockService,
|
||||
customImageProxyMiddleware,
|
||||
@@ -330,9 +330,25 @@ export const DetailPage = ({ pageId }: { pageId: string }): ReactElement => {
|
||||
const docRecordList = docsService.list;
|
||||
const docListReady = useLiveData(docRecordList.isReady$);
|
||||
const docRecord = useLiveData(docRecordList.doc$(pageId));
|
||||
const viewService = useService(ViewService);
|
||||
|
||||
const queryString = useLiveData(
|
||||
viewService.view.queryString$<{
|
||||
mode?: string;
|
||||
}>()
|
||||
);
|
||||
|
||||
const queryStringMode =
|
||||
queryString.mode && ['edgeless', 'page'].includes(queryString.mode)
|
||||
? (queryString.mode as DocMode)
|
||||
: null;
|
||||
|
||||
// We only read the querystring mode when entering, so use useState here.
|
||||
const [initialQueryStringMode] = useState(() => queryStringMode);
|
||||
|
||||
const [doc, setDoc] = useState<Doc | null>(null);
|
||||
const [editor, setEditor] = useState<Editor | null>(null);
|
||||
const editorMode = useLiveData(editor?.mode$);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!docRecord) {
|
||||
@@ -351,12 +367,26 @@ export const DetailPage = ({ pageId }: { pageId: string }): ReactElement => {
|
||||
}
|
||||
const editor = doc.scope
|
||||
.get(EditorsService)
|
||||
.createEditor(doc.getPrimaryMode() || 'page');
|
||||
.createEditor(initialQueryStringMode || doc.getPrimaryMode() || 'page');
|
||||
setEditor(editor);
|
||||
return () => {
|
||||
editor.dispose();
|
||||
};
|
||||
}, [doc]);
|
||||
}, [doc, initialQueryStringMode]);
|
||||
|
||||
// update editor mode to queryString
|
||||
useEffect(() => {
|
||||
if (editorMode) {
|
||||
viewService.view.updateQueryString(
|
||||
{
|
||||
mode: editorMode,
|
||||
},
|
||||
{
|
||||
replace: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
}, [editorMode, viewService.view]);
|
||||
|
||||
// set sync engine priority target
|
||||
useEffect(() => {
|
||||
|
||||
@@ -310,6 +310,7 @@ export enum ErrorNames {
|
||||
MAILER_SERVICE_IS_NOT_CONFIGURED = 'MAILER_SERVICE_IS_NOT_CONFIGURED',
|
||||
MEMBER_QUOTA_EXCEEDED = 'MEMBER_QUOTA_EXCEEDED',
|
||||
MISSING_OAUTH_QUERY_PARAMETER = 'MISSING_OAUTH_QUERY_PARAMETER',
|
||||
NOT_FOUND = 'NOT_FOUND',
|
||||
NOT_IN_WORKSPACE = 'NOT_IN_WORKSPACE',
|
||||
NO_COPILOT_PROVIDER_AVAILABLE = 'NO_COPILOT_PROVIDER_AVAILABLE',
|
||||
OAUTH_ACCOUNT_ALREADY_CONNECTED = 'OAUTH_ACCOUNT_ALREADY_CONNECTED',
|
||||
|
||||
Reference in New Issue
Block a user