@@ -11,13 +11,18 @@ import { Tree } from '../Tree'
11
11
import { Modal } from '../Modal'
12
12
import { Button } from '../Button'
13
13
import FolderIcon from '../Icons/Folder'
14
- import { AssetNode , AssetNodeFolder } from './types'
15
- import { getFullNodePath } from './utils'
14
+ import { AssetNodeFolder } from './types'
15
+ import { getFilterFromTree , getFullNodePath } from './utils'
16
16
import Search from '../Search'
17
17
import { withAssetDir } from '../../lib/data-layer/host/fs-utils'
18
18
import { removeAsset } from '../../redux/data-layer'
19
19
import { useAppDispatch } from '../../redux/hooks'
20
20
import { determineAssetType , extractFileExtension } from '../ImportAsset/utils'
21
+ import { generateAssetTree , getChildren as _getChildren , TreeNode , ROOT , getTiles } from './tree'
22
+ import { Filters } from './Filters'
23
+ import { Filter } from './Filters/types'
24
+
25
+ export { TreeNode }
21
26
22
27
function noop ( ) { }
23
28
@@ -32,81 +37,34 @@ interface ModalState {
32
37
entities : Entity [ ]
33
38
}
34
39
35
- export const ROOT = 'File System'
36
-
37
40
export const DRAG_N_DROP_ASSET_KEY = 'local-asset'
38
41
39
- export type TreeNode = Omit < AssetNode , 'children' > & { children ?: string [ ] ; matches ?: string [ ] }
40
-
41
42
const FilesTree = Tree < string > ( )
42
43
43
44
function ProjectView ( { folders, thumbnails } : Props ) {
44
45
const sdk = useSdk ( )
45
46
const dispatch = useAppDispatch ( )
46
47
const [ open , setOpen ] = useState ( new Set < string > ( ) )
47
48
const [ modal , setModal ] = useState < ModalState | undefined > ( undefined )
48
- const [ lastSelected , setLastSelected ] = useState < string > ( )
49
+ const [ lastSelected , setLastSelected ] = useState < string > ( ROOT )
49
50
const [ search , setSearch ] = useState < string > ( '' )
50
51
const [ tree , setTree ] = useState < Map < string , TreeNode > > ( new Map ( ) )
51
-
52
- const getTree = useCallback ( ( ) => {
53
- function getPath ( node : string , children : string ) {
54
- if ( ! node ) return children
55
- return `${ node } /${ children } `
56
- }
57
- const tree = new Map < string , TreeNode > ( )
58
- tree . set ( ROOT , { children : folders . map ( ( f ) => f . name ) , name : ROOT , type : 'folder' , parent : null } )
59
- open . add ( ROOT )
60
-
61
- function hasMatch ( name : string ) {
62
- return search && name . toLocaleLowerCase ( ) . includes ( search . toLocaleLowerCase ( ) )
63
- }
64
-
65
- function generateTree ( node : AssetNodeFolder , parentName : string = '' ) : string [ ] {
66
- const namePath = getPath ( parentName , node . name )
67
- const childrens = node . children . map ( ( c ) => `${ namePath } /${ c . name } ` )
68
- const matchesList : string [ ] = [ ]
69
- for ( const children of node . children ) {
70
- if ( children . type === 'folder' ) {
71
- matchesList . push ( ...generateTree ( children , namePath ) )
72
- } else {
73
- const name = getPath ( namePath , children . name )
74
- const matches = hasMatch ( name )
75
- if ( matches ) {
76
- open . add ( name )
77
- matchesList . push ( name )
78
- }
79
- tree . set ( name , { ...children , matches : matches ? [ name ] : [ ] , parent : node } )
80
- }
81
- }
82
- if ( matchesList . length ) {
83
- open . add ( namePath )
84
- }
85
- tree . set ( namePath , { ...node , children : childrens , parent : null , matches : matchesList } )
86
- return matchesList
87
- }
88
-
89
- for ( const f of folders ) {
90
- generateTree ( f )
91
- }
92
- return tree
93
- } , [ folders , search ] )
52
+ const [ filters , setFilters ] = useState < Filter [ ] > ( [ ] )
53
+ const [ activeFilter , setActiveFilter ] = useState < Filter > ( 'all' )
94
54
95
55
useEffect ( ( ) => {
96
- setTree ( getTree ( ) )
97
- } , [ folders , search ] )
98
-
99
- /**
100
- * Values
101
- */
102
- const selectedTreeNode = tree . get ( lastSelected ?? ROOT )
56
+ const { tree, filters } = generateAssetTree ( folders , open , search , activeFilter )
57
+ setTree ( tree )
58
+ setFilters ( getFilterFromTree ( filters ) )
59
+ } , [ folders , search , activeFilter ] )
103
60
104
61
/**
105
62
* Callbacks
106
63
*/
107
64
108
65
const onSelect = useCallback (
109
66
( value : string ) => {
67
+ open . add ( value )
110
68
setLastSelected ( value )
111
69
} ,
112
70
[ setLastSelected ]
@@ -148,7 +106,7 @@ function ProjectView({ folders, thumbnails }: Props) {
148
106
}
149
107
dispatch ( removeAsset ( { path } ) )
150
108
} ,
151
- [ open , setOpen , selectedTreeNode , lastSelected ]
109
+ [ open , setOpen , lastSelected ]
152
110
)
153
111
154
112
const handleConfirm = useCallback ( async ( ) => {
@@ -158,11 +116,13 @@ function ProjectView({ folders, thumbnails }: Props) {
158
116
} , [ modal , setModal ] )
159
117
160
118
const handleModalClose = useCallback ( ( ) => setModal ( undefined ) , [ ] )
119
+
161
120
const handleClickFolder = useCallback (
162
- ( val : string ) => ( ) => {
163
- if ( lastSelected === val ) return
164
- open . add ( val )
165
- setLastSelected ( val )
121
+ ( node : TreeNode ) => ( ) => {
122
+ if ( node . type === 'asset' ) return
123
+ const path = getFullNodePath ( node ) . slice ( 1 )
124
+ open . add ( path )
125
+ setLastSelected ( path )
166
126
} ,
167
127
[ setLastSelected ]
168
128
)
@@ -171,16 +131,10 @@ function ProjectView({ folders, thumbnails }: Props) {
171
131
172
132
const getChildren = useCallback (
173
133
( val : string ) => {
174
- const value = tree . get ( val )
175
- if ( ! value ?. children ?. length ) return [ ]
176
- if ( ! search . length ) return value . children
177
-
178
- return value . children . filter ( ( $ ) => {
179
- const childrenValue = tree . get ( $ )
180
- return ! ! childrenValue ?. matches ?. length
181
- } )
134
+ const childs = _getChildren ( val , tree , search , activeFilter )
135
+ return childs
182
136
} ,
183
- [ tree , search ]
137
+ [ tree , search , activeFilter ]
184
138
)
185
139
186
140
const getThumbnail = useCallback (
@@ -192,6 +146,12 @@ function ProjectView({ folders, thumbnails }: Props) {
192
146
[ thumbnails ]
193
147
)
194
148
149
+ const handleFilterClick = useCallback ( ( type : Filter ) => {
150
+ setActiveFilter ( type )
151
+ } , [ ] )
152
+
153
+ const tiles = getTiles ( lastSelected , tree , search , activeFilter )
154
+
195
155
return (
196
156
< >
197
157
< Modal isOpen = { ! ! modal ?. isOpen } onRequestClose = { handleModalClose } className = "RemoveAsset" >
@@ -206,6 +166,7 @@ function ProjectView({ folders, thumbnails }: Props) {
206
166
</ div >
207
167
</ Modal >
208
168
< div className = "ProjectView" >
169
+ < Filters filters = { filters } active = { activeFilter } onClick = { handleFilterClick } />
209
170
< div className = "Tree-View" >
210
171
< Search
211
172
value = { search }
@@ -241,31 +202,18 @@ function ProjectView({ folders, thumbnails }: Props) {
241
202
/>
242
203
</ div >
243
204
< div className = "FolderView" >
244
- { selectedTreeNode ?. type === 'folder'
245
- ? selectedTreeNode ?. children ?. map ( ( $ ) => (
246
- < Tile
247
- key = { $ }
248
- valueId = { $ }
249
- value = { tree . get ( $ ) }
250
- getDragContext = { handleDragContext }
251
- onSelect = { handleClickFolder ( $ ) }
252
- onRemove = { handleRemove }
253
- getThumbnail = { getThumbnail }
254
- dndType = { DRAG_N_DROP_ASSET_KEY }
255
- />
256
- ) )
257
- : ! ! selectedTreeNode &&
258
- lastSelected && (
259
- < Tile
260
- valueId = { lastSelected }
261
- value = { selectedTreeNode }
262
- getDragContext = { handleDragContext }
263
- onSelect = { handleClickFolder ( selectedTreeNode . name ) }
264
- onRemove = { handleRemove }
265
- getThumbnail = { getThumbnail }
266
- dndType = { DRAG_N_DROP_ASSET_KEY }
267
- />
268
- ) }
205
+ { tiles . map ( ( node ) => (
206
+ < Tile
207
+ key = { node . name }
208
+ valueId = { getFullNodePath ( node ) . slice ( 1 ) }
209
+ value = { node }
210
+ getDragContext = { handleDragContext }
211
+ onSelect = { handleClickFolder ( node ) }
212
+ onRemove = { handleRemove }
213
+ getThumbnail = { getThumbnail }
214
+ dndType = { DRAG_N_DROP_ASSET_KEY }
215
+ />
216
+ ) ) }
269
217
</ div >
270
218
</ div >
271
219
</ >
0 commit comments