@@ -64,7 +64,12 @@ import useOnScroll from '#/hooks/useOnScroll'
64
64
import type * as assetSearchBar from '#/layouts/AssetSearchBar'
65
65
import * as eventListProvider from '#/layouts/AssetsTable/EventListProvider'
66
66
import AssetsTableContextMenu from '#/layouts/AssetsTableContextMenu'
67
- import { isLocalCategory , type Category } from '#/layouts/CategorySwitcher/Category'
67
+ import {
68
+ canTransferBetweenCategories ,
69
+ isLocalCategory ,
70
+ useTransferBetweenCategories ,
71
+ type Category ,
72
+ } from '#/layouts/CategorySwitcher/Category'
68
73
import DragModal from '#/modals/DragModal'
69
74
import DuplicateAssetsModal from '#/modals/DuplicateAssetsModal'
70
75
import UpsertSecretModal from '#/modals/UpsertSecretModal'
@@ -81,6 +86,7 @@ import {
81
86
useSetCanDownload ,
82
87
useSetIsAssetPanelTemporarilyVisible ,
83
88
useSetNewestFolderId ,
89
+ useSetPasteData ,
84
90
useSetSelectedKeys ,
85
91
useSetSuggestions ,
86
92
useSetTargetDirectory ,
@@ -141,7 +147,6 @@ import { fileExtension } from '#/utilities/fileInfo'
141
147
import type { DetailedRectangle } from '#/utilities/geometry'
142
148
import { DEFAULT_HANDLER } from '#/utilities/inputBindings'
143
149
import LocalStorage from '#/utilities/LocalStorage'
144
- import type { PasteData } from '#/utilities/pasteData'
145
150
import PasteType from '#/utilities/PasteType'
146
151
import {
147
152
canPermissionModifyDirectoryContents ,
@@ -309,14 +314,11 @@ export interface AssetsTableState {
309
314
readonly scrollContainerRef : RefObject < HTMLElement >
310
315
readonly visibilities : ReadonlyMap < AssetId , Visibility >
311
316
readonly category : Category
312
- readonly hasPasteData : boolean
313
- readonly setPasteData : ( pasteData : PasteData < Set < AssetId > > ) => void
314
317
readonly sortInfo : SortInfo < SortableColumn > | null
315
318
readonly setSortInfo : ( sortInfo : SortInfo < SortableColumn > | null ) => void
316
319
readonly query : AssetQuery
317
320
readonly setQuery : Dispatch < SetStateAction < AssetQuery > >
318
321
readonly nodeMap : Readonly < MutableRefObject < ReadonlyMap < AssetId , AnyAssetTreeNode > > >
319
- readonly pasteData : Readonly < MutableRefObject < PasteData < ReadonlySet < AssetId > > | null > >
320
322
readonly hideColumn : ( column : Column ) => void
321
323
readonly doToggleDirectoryExpansion : (
322
324
directoryId : DirectoryId ,
@@ -396,7 +398,7 @@ export default function AssetsTable(props: AssetsTableProps) {
396
398
const setSelectedKeys = useSetSelectedKeys ( )
397
399
const setVisuallySelectedKeys = useSetVisuallySelectedKeys ( )
398
400
const updateAssetRef = useRef < Record < AnyAsset [ 'id' ] , ( asset : AnyAsset ) => void > > ( { } )
399
- const [ pasteData , setPasteData ] = useState < PasteData < ReadonlySet < AssetId > > | null > ( null )
401
+ const setPasteData = useSetPasteData ( )
400
402
401
403
const { data : users } = useBackendQuery ( backend , 'listUsers' , [ ] )
402
404
const { data : userGroups } = useBackendQuery ( backend , 'listUserGroups' , [ ] )
@@ -864,7 +866,6 @@ export default function AssetsTable(props: AssetsTableProps) {
864
866
const lastSelectedIdsRef = useRef < AssetId | ReadonlySet < AssetId > | null > ( null )
865
867
const headerRowRef = useRef < HTMLTableRowElement > ( null )
866
868
const assetTreeRef = useRef < AnyAssetTreeNode > ( assetTree )
867
- const pasteDataRef = useRef < PasteData < ReadonlySet < AssetId > > | null > ( null )
868
869
const nodeMapRef = useRef < ReadonlyMap < AssetId , AnyAssetTreeNode > > (
869
870
new Map < AssetId , AnyAssetTreeNode > ( ) ,
870
871
)
@@ -1141,25 +1142,22 @@ export default function AssetsTable(props: AssetsTableProps) {
1141
1142
nodeMapRef . current = newNodeMap
1142
1143
} , [ assetTree ] )
1143
1144
1144
- useEffect ( ( ) => {
1145
- pasteDataRef . current = pasteData
1146
- } , [ pasteData ] )
1147
-
1148
1145
useEffect ( ( ) => {
1149
1146
if ( ! hidden ) {
1150
1147
return inputBindings . attach ( document . body , 'keydown' , {
1151
1148
cancelCut : ( ) => {
1152
- if ( pasteDataRef . current == null ) {
1149
+ const { pasteData } = driveStore . getState ( )
1150
+ if ( pasteData == null ) {
1153
1151
return false
1154
1152
} else {
1155
- dispatchAssetEvent ( { type : AssetEventType . cancelCut , ids : pasteDataRef . current . data } )
1153
+ dispatchAssetEvent ( { type : AssetEventType . cancelCut , ids : pasteData . data . ids } )
1156
1154
setPasteData ( null )
1157
1155
return
1158
1156
}
1159
1157
} ,
1160
1158
} )
1161
1159
}
1162
- } , [ hidden , inputBindings , dispatchAssetEvent ] )
1160
+ } , [ dispatchAssetEvent , driveStore , hidden , inputBindings , setPasteData ] )
1163
1161
1164
1162
useEffect (
1165
1163
( ) =>
@@ -2145,29 +2143,40 @@ export default function AssetsTable(props: AssetsTableProps) {
2145
2143
const doCopy = useEventCallback ( ( ) => {
2146
2144
unsetModal ( )
2147
2145
const { selectedKeys } = driveStore . getState ( )
2148
- setPasteData ( { type : PasteType . copy , data : selectedKeys } )
2146
+ setPasteData ( {
2147
+ type : PasteType . copy ,
2148
+ data : { backendType : backend . type , category, ids : selectedKeys } ,
2149
+ } )
2149
2150
} )
2150
2151
2151
2152
const doCut = useEventCallback ( ( ) => {
2152
2153
unsetModal ( )
2154
+ const { selectedKeys, pasteData } = driveStore . getState ( )
2153
2155
if ( pasteData != null ) {
2154
- dispatchAssetEvent ( { type : AssetEventType . cancelCut , ids : pasteData . data } )
2156
+ dispatchAssetEvent ( { type : AssetEventType . cancelCut , ids : pasteData . data . ids } )
2155
2157
}
2156
- const { selectedKeys } = driveStore . getState ( )
2157
- setPasteData ( { type : PasteType . move , data : selectedKeys } )
2158
+ setPasteData ( {
2159
+ type : PasteType . move ,
2160
+ data : { backendType : backend . type , category, ids : selectedKeys } ,
2161
+ } )
2158
2162
dispatchAssetEvent ( { type : AssetEventType . cut , ids : selectedKeys } )
2159
2163
setSelectedKeys ( EMPTY_SET )
2160
2164
} )
2161
2165
2166
+ const transferBetweenCategories = useTransferBetweenCategories ( category )
2162
2167
const doPaste = useEventCallback ( ( newParentKey : DirectoryId , newParentId : DirectoryId ) => {
2163
2168
unsetModal ( )
2164
- if ( pasteData != null ) {
2165
- if ( pasteData . data . has ( newParentKey ) ) {
2169
+ const { pasteData } = driveStore . getState ( )
2170
+ if (
2171
+ pasteData ?. data . backendType === backend . type &&
2172
+ canTransferBetweenCategories ( pasteData . data . category , category )
2173
+ ) {
2174
+ if ( pasteData . data . ids . has ( newParentKey ) ) {
2166
2175
toast . error ( 'Cannot paste a folder into itself.' )
2167
2176
} else {
2168
2177
doToggleDirectoryExpansion ( newParentId , newParentKey , true )
2169
2178
if ( pasteData . type === PasteType . copy ) {
2170
- const assets = Array . from ( pasteData . data , ( id ) => nodeMapRef . current . get ( id ) ) . flatMap (
2179
+ const assets = Array . from ( pasteData . data . ids , ( id ) => nodeMapRef . current . get ( id ) ) . flatMap (
2171
2180
( asset ) => ( asset ? [ asset . item ] : [ ] ) ,
2172
2181
)
2173
2182
dispatchAssetListEvent ( {
@@ -2177,12 +2186,13 @@ export default function AssetsTable(props: AssetsTableProps) {
2177
2186
newParentKey,
2178
2187
} )
2179
2188
} else {
2180
- dispatchAssetEvent ( {
2181
- type : AssetEventType . move ,
2182
- ids : pasteData . data ,
2189
+ transferBetweenCategories (
2190
+ pasteData . data . category ,
2191
+ category ,
2192
+ pasteData . data . ids ,
2183
2193
newParentKey ,
2184
2194
newParentId ,
2185
- } )
2195
+ )
2186
2196
}
2187
2197
setPasteData ( null )
2188
2198
}
@@ -2207,7 +2217,6 @@ export default function AssetsTable(props: AssetsTableProps) {
2207
2217
hidden
2208
2218
backend = { backend }
2209
2219
category = { category }
2210
- pasteData = { pasteData }
2211
2220
nodeMapRef = { nodeMapRef }
2212
2221
rootDirectoryId = { rootDirectoryId }
2213
2222
event = { { pageX : 0 , pageY : 0 } }
@@ -2217,7 +2226,7 @@ export default function AssetsTable(props: AssetsTableProps) {
2217
2226
doDelete = { doDeleteById }
2218
2227
/>
2219
2228
) ,
2220
- [ backend , category , pasteData , rootDirectoryId , doCopy , doCut , doPaste , doDeleteById ] ,
2229
+ [ backend , category , rootDirectoryId , doCopy , doCut , doPaste , doDeleteById ] ,
2221
2230
)
2222
2231
2223
2232
const onDropzoneDragOver = ( event : DragEvent < Element > ) => {
@@ -2260,14 +2269,11 @@ export default function AssetsTable(props: AssetsTableProps) {
2260
2269
visibilities,
2261
2270
scrollContainerRef : rootRef ,
2262
2271
category,
2263
- hasPasteData : pasteData != null ,
2264
- setPasteData,
2265
2272
sortInfo,
2266
2273
setSortInfo,
2267
2274
query,
2268
2275
setQuery,
2269
2276
nodeMap : nodeMapRef ,
2270
- pasteData : pasteDataRef ,
2271
2277
hideColumn,
2272
2278
doToggleDirectoryExpansion,
2273
2279
doCopy,
@@ -2283,7 +2289,6 @@ export default function AssetsTable(props: AssetsTableProps) {
2283
2289
rootDirectoryId ,
2284
2290
visibilities ,
2285
2291
category ,
2286
- pasteData ,
2287
2292
sortInfo ,
2288
2293
query ,
2289
2294
doToggleDirectoryExpansion ,
@@ -2762,7 +2767,6 @@ export default function AssetsTable(props: AssetsTableProps) {
2762
2767
< AssetsTableContextMenu
2763
2768
backend = { backend }
2764
2769
category = { category }
2765
- pasteData = { pasteData }
2766
2770
nodeMapRef = { nodeMapRef }
2767
2771
event = { event }
2768
2772
rootDirectoryId = { rootDirectoryId }
0 commit comments