1
1
import {
2
+ IconButton ,
2
3
MenuItem ,
3
4
MenuSeparator ,
4
5
toast ,
@@ -22,10 +23,11 @@ import {
22
23
InformationIcon ,
23
24
LinkedPageIcon ,
24
25
OpenInNewIcon ,
26
+ PlusIcon ,
25
27
SplitViewIcon ,
26
28
} from '@blocksuite/icons/rc' ;
27
29
import { useLiveData , useServices } from '@toeverything/infra' ;
28
- import { useCallback , useMemo } from 'react' ;
30
+ import { useCallback , useMemo , useState } from 'react' ;
29
31
30
32
import type { NodeOperation } from '../../tree/types' ;
31
33
@@ -52,6 +54,7 @@ export const useExplorerDocNodeOperations = (
52
54
} ) ;
53
55
const { openConfirmModal } = useConfirmModal ( ) ;
54
56
57
+ const [ addLinkedPageLoading , setAddLinkedPageLoading ] = useState ( false ) ;
55
58
const docRecord = useLiveData ( docsService . list . doc$ ( docId ) ) ;
56
59
57
60
const { createPage } = usePageHelper (
@@ -117,17 +120,22 @@ export const useExplorerDocNodeOperations = (
117
120
} , [ docId , workbenchService . workbench ] ) ;
118
121
119
122
const handleAddLinkedPage = useAsyncCallback ( async ( ) => {
120
- const canEdit = await guardService . can ( 'Doc_Update' , docId ) ;
121
- if ( ! canEdit ) {
122
- toast ( t [ 'com.affine.no-permission' ] ( ) ) ;
123
- return ;
123
+ setAddLinkedPageLoading ( true ) ;
124
+ try {
125
+ const canEdit = await guardService . can ( 'Doc_Update' , docId ) ;
126
+ if ( ! canEdit ) {
127
+ toast ( t [ 'com.affine.no-permission' ] ( ) ) ;
128
+ return ;
129
+ }
130
+ const newDoc = createPage ( ) ;
131
+ // TODO: handle timeout & error
132
+ await docsService . addLinkedDoc ( docId , newDoc . id ) ;
133
+ track . $ . navigationPanel . docs . createDoc ( { control : 'linkDoc' } ) ;
134
+ track . $ . navigationPanel . docs . linkDoc ( { control : 'createDoc' } ) ;
135
+ options . openNodeCollapsed ( ) ;
136
+ } finally {
137
+ setAddLinkedPageLoading ( false ) ;
124
138
}
125
- const newDoc = createPage ( ) ;
126
- // TODO: handle timeout & error
127
- await docsService . addLinkedDoc ( docId , newDoc . id ) ;
128
- track . $ . navigationPanel . docs . createDoc ( { control : 'linkDoc' } ) ;
129
- track . $ . navigationPanel . docs . linkDoc ( { control : 'createDoc' } ) ;
130
- options . openNodeCollapsed ( ) ;
131
139
} , [ createPage , guardService , docId , docsService , options , t ] ) ;
132
140
133
141
const handleToggleFavoriteDoc = useCallback ( ( ) => {
@@ -139,6 +147,20 @@ export const useExplorerDocNodeOperations = (
139
147
140
148
return useMemo (
141
149
( ) => [
150
+ {
151
+ index : 0 ,
152
+ inline : true ,
153
+ view : (
154
+ < IconButton
155
+ size = "16"
156
+ icon = { < PlusIcon /> }
157
+ tooltip = { t [ 'com.affine.rootAppSidebar.explorer.doc-add-tooltip' ] ( ) }
158
+ onClick = { handleAddLinkedPage }
159
+ loading = { addLinkedPageLoading }
160
+ disabled = { addLinkedPageLoading }
161
+ />
162
+ ) ,
163
+ } ,
142
164
{
143
165
index : 50 ,
144
166
view : (
@@ -233,6 +255,7 @@ export const useExplorerDocNodeOperations = (
233
255
} ,
234
256
] ,
235
257
[
258
+ addLinkedPageLoading ,
236
259
docId ,
237
260
favorite ,
238
261
handleAddLinkedPage ,
0 commit comments