feat(core): drop doc onto split view (#9487)

fix AF-2068, AF-2069, AF-1175, AF-2061, AF-2079, AF-2034, AF-2080, AF-1960, AF-2081

1. replace `dnd-kit` with `@atlaskit/pragmatic-drag-and-drop`
2. allow creating split views by drag & drop the following
   a. WorkbenchLinks (route links), like journals, trash, all docs
   b. doc refs
   c. tags/collection
3. style adjustments to split view
4. remove split view's feature flag and make it GA for electron

https://github.com/user-attachments/assets/6a3e4a25-faa2-4215-8eb0-983f44db6e8c
This commit is contained in:
pengx17
2025-01-08 05:05:33 +00:00
parent c0ed74dfed
commit a4841bbfa3
53 changed files with 1574 additions and 905 deletions

View File

@@ -1,8 +1,9 @@
import { Skeleton } from '@affine/component';
import { type DropTargetGetFeedback, Skeleton } from '@affine/component';
import { ResizePanel } from '@affine/component/resize-panel';
import { useAppSettingHelper } from '@affine/core/components/hooks/affine/use-app-setting-helper';
import { NavigateContext } from '@affine/core/components/hooks/use-navigate-helper';
import { WorkspaceNavigator } from '@affine/core/components/workspace-selector';
import type { AffineDNDData } from '@affine/core/types/dnd';
import { useI18n } from '@affine/i18n';
import {
useLiveData,
@@ -14,6 +15,8 @@ import { debounce } from 'lodash-es';
import type { PropsWithChildren, ReactElement } from 'react';
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { WorkbenchService } from '../../workbench';
import { allowedSplitViewEntityTypes } from '../../workbench/view/split-view/types';
import { WorkspaceService } from '../../workspace';
import { AppSidebarService } from '../services/app-sidebar';
import * as styles from './fallback.css';
@@ -44,6 +47,7 @@ export function AppSidebar({ children }: PropsWithChildren) {
const clientBorder = appSettings.clientBorder;
const appSidebarService = useService(AppSidebarService).sidebar;
const workbenchService = useService(WorkbenchService).workbench;
const open = useLiveData(appSidebarService.open$);
const width = useLiveData(appSidebarService.width$);
@@ -147,6 +151,31 @@ export function AppSidebar({ children }: PropsWithChildren) {
};
}, [appSidebarService, resizing, sidebarState, width]);
const resizeHandleDropTargetOptions = useMemo(() => {
return () => ({
data: () => {
const firstView = workbenchService.views$.value.at(0);
if (!firstView) {
return {};
}
return {
at: 'workbench:resize-handle',
edge: 'left', // left of the first view
viewId: firstView.id,
};
},
canDrop: (data: DropTargetGetFeedback<AffineDNDData>) => {
return (
(!!data.source.data.entity?.type &&
allowedSplitViewEntityTypes.has(data.source.data.entity?.type)) ||
data.source.data.from?.at === 'workbench:link'
);
},
});
}, [workbenchService.views$.value]);
if (!initialized) {
return null;
}
@@ -154,6 +183,7 @@ export function AppSidebar({ children }: PropsWithChildren) {
return (
<>
<ResizePanel
resizeHandleDropTargetOptions={resizeHandleDropTargetOptions}
floating={
sidebarState === 'floating' || sidebarState === 'floating-with-mask'
}