1
1
import {
2
2
type ExternalGetDataFeedbackArgs ,
3
3
type fromExternalData ,
4
+ type MonitorDragEvent ,
5
+ monitorForElements ,
6
+ type MonitorGetFeedback ,
4
7
type toExternalData ,
5
8
} from '@affine/component' ;
6
9
import { createPageModeSpecs } from '@affine/core/components/blocksuite/block-suite-editor/specs/page' ;
7
10
import type { AffineDNDData } from '@affine/core/types/dnd' ;
8
11
import { BlockStdScope } from '@blocksuite/affine/block-std' ;
9
- import { DndApiExtensionIdentifier } from '@blocksuite/affine/blocks' ;
12
+ import {
13
+ DndApiExtensionIdentifier ,
14
+ type DragBlockPayload ,
15
+ } from '@blocksuite/affine/blocks' ;
10
16
import { type SliceSnapshot } from '@blocksuite/affine/store' ;
11
17
import { Service } from '@toeverything/infra' ;
12
18
@@ -19,6 +25,10 @@ type EntityResolver = (data: string) => Entity | null;
19
25
20
26
type ExternalDragPayload = ExternalGetDataFeedbackArgs [ 'source' ] ;
21
27
28
+ type MixedDNDData = AffineDNDData & {
29
+ draggable : DragBlockPayload ;
30
+ } ;
31
+
22
32
export class DndService extends Service {
23
33
constructor (
24
34
private readonly docsService : DocsService ,
@@ -53,6 +63,78 @@ export class DndService extends Service {
53
63
return null ;
54
64
} ) ;
55
65
} ) ;
66
+
67
+ this . setupBlocksuiteAdapter ( ) ;
68
+ }
69
+
70
+ private setupBlocksuiteAdapter ( ) {
71
+ /**
72
+ * Migrate from affine to blocksuite
73
+ * For now, we only support doc
74
+ */
75
+ const affineToBlocksuite = ( args : MonitorDragEvent < MixedDNDData > ) => {
76
+ const data = args . source . data ;
77
+ if ( data . entity && ! data . bsEntity ) {
78
+ if ( data . entity . type !== 'doc' ) {
79
+ return ;
80
+ }
81
+ const dndAPI = this . getBlocksuiteDndAPI ( ) ;
82
+ if ( ! dndAPI ) {
83
+ return ;
84
+ }
85
+ const snapshotSlice = dndAPI . fromEntity ( {
86
+ docId : data . entity . id ,
87
+ flavour : 'affine:embed-linked-doc' ,
88
+ } ) ;
89
+ if ( ! snapshotSlice ) {
90
+ return ;
91
+ }
92
+ data . bsEntity = {
93
+ type : 'blocks' ,
94
+ modelIds : [ ] ,
95
+ snapshot : snapshotSlice ,
96
+ } ;
97
+ }
98
+ } ;
99
+
100
+ /**
101
+ * Migrate from blocksuite to affine
102
+ */
103
+ const blocksuiteToAffine = ( args : MonitorDragEvent < MixedDNDData > ) => {
104
+ const data = args . source . data ;
105
+ if ( ! data . entity && data . bsEntity ) {
106
+ if ( data . bsEntity . type !== 'blocks' || ! data . bsEntity . snapshot ) {
107
+ return ;
108
+ }
109
+ const dndAPI = this . getBlocksuiteDndAPI ( ) ;
110
+ if ( ! dndAPI ) {
111
+ return ;
112
+ }
113
+ const entity = this . resolveBlockSnapshot ( data . bsEntity . snapshot ) ;
114
+ if ( ! entity ) {
115
+ return ;
116
+ }
117
+ data . entity = entity ;
118
+ }
119
+ } ;
120
+
121
+ this . disposables . push (
122
+ monitorForElements ( {
123
+ canMonitor : ( args : MonitorGetFeedback < MixedDNDData > ) => {
124
+ return (
125
+ args . source . data . entity ?. type === 'doc' ||
126
+ ( args . source . data . bsEntity ?. type === 'blocks' &&
127
+ ! ! args . source . data . bsEntity . snapshot )
128
+ ) ;
129
+ } ,
130
+ // assume data is only applied on drag start
131
+ onDragStart : args => {
132
+ // affine <-> blocksuite
133
+ affineToBlocksuite ( args ) ;
134
+ blocksuiteToAffine ( args ) ;
135
+ } ,
136
+ } )
137
+ ) ;
56
138
}
57
139
58
140
private readonly resolvers : ( (
@@ -161,6 +243,9 @@ export class DndService extends Service {
161
243
return null ;
162
244
} ;
163
245
246
+ /**
247
+ * @deprecated Blocksuite DND is now using pragmatic-dnd as well
248
+ */
164
249
private readonly resolveBlocksuiteExternalData = (
165
250
source : ExternalDragPayload
166
251
) : AffineDNDData [ 'draggable' ] | null => {
0 commit comments