@@ -7,7 +7,7 @@ import React, {
77 useRef ,
88 useState ,
99} from 'react' ;
10- import { InView } from 'react-intersection-observer' ;
10+ import { useInView } from 'react-intersection-observer' ;
1111import { Tooltip } from 'react-tooltip' ;
1212import FigureLabels from '../common/FigureLabels' ;
1313import FileUploader from '../common/FileUploader' ;
@@ -50,26 +50,41 @@ function Figure(props) {
5050}
5151
5252
53- const FilesList = memo ( ( props : any ) => {
54- const { files, numFiles, selectFile} = props ;
55- const [ { offset, limit} , setOffset ] = useState ( { offset : 0 , limit : 10 } ) ;
53+ const ScrollSpy = ( props ) => {
54+ const { fetchFiles} = props ;
55+ const { ref, inView} = useInView ( {
56+ triggerOnce : true ,
57+ onChange : ( loadMore ) => {
58+ if ( loadMore && ! inView ) {
59+ fetchFiles ( ) ;
60+ }
61+ } ,
62+ } ) ;
63+ console . log ( 'ScrollSpy' , inView ) ;
64+ if ( inView ) {
65+ console . log ( 'already visible' ) ;
66+ fetchFiles ( ) ;
67+ }
5668
57- console . log ( 'FolderList' , numFiles , files ) ;
69+ return (
70+ < div className = "scroll-spy" ref = { ref } > </ div >
71+ ) ;
72+ } ;
5873
59- function loadMore ( inView , entry ) {
60- if ( inView ) {
61- console . log ( 'load more:' , entry . target ) ;
62- }
63- }
74+
75+ const FilesList = memo ( ( props : any ) => {
76+ const { structure , fetchFiles , selectFile } = props ;
77+
78+ console . log ( 'FolderList' , structure ) ;
6479
6580 return (
6681 < ul className = "files-browser" > {
67- files . length === 0 ?
82+ structure . files . length === 0 ?
6883 < li className = "status" > { gettext ( "Empty folder" ) } </ li > : (
69- < > { files . map ( file => (
84+ < > { structure . files . map ( file => (
7085 < li key = { file . id } onClick = { ( ) => selectFile ( file ) } > < Figure { ...file } /> </ li >
7186 ) ) }
72- { numFiles > files . length && < InView as = "li" onChange = { loadMore } /> }
87+ { structure . offset !== null && < ScrollSpy fetchFiles = { fetchFiles } /> }
7388 </ >
7489 ) } </ ul >
7590 ) ;
@@ -82,7 +97,8 @@ export default function FileSelectDialog(props) {
8297 root_folder : null ,
8398 last_folder : null ,
8499 files : null ,
85- num_files : 0 ,
100+ offset : null ,
101+ search_query : '' ,
86102 labels : [ ] ,
87103 } ) ;
88104 const [ uploadedFile , setUploadedFile ] = useState ( null ) ;
@@ -110,6 +126,48 @@ export default function FileSelectDialog(props) {
110126 } ;
111127 } , [ dialog ] ) ;
112128
129+ const setCurrentFolder = ( folderId ) => {
130+ setStructure ( prevStructure => {
131+ const newStructure = Object . assign ( structure , {
132+ ...prevStructure ,
133+ last_folder : folderId ,
134+ files : [ ] ,
135+ offset : null ,
136+ search_query : '' ,
137+ } ) ;
138+ fetchFiles ( ) ;
139+ return newStructure ;
140+ } ) ;
141+ } ;
142+
143+ const setSearchQuery = ( query ) => {
144+ setStructure ( prevStructure => {
145+ const newStructure = Object . assign ( structure , {
146+ ...prevStructure ,
147+ files : [ ] ,
148+ offset : null ,
149+ search_query : query ,
150+ } ) ;
151+ fetchFiles ( ) ;
152+ return newStructure ;
153+ } ) ;
154+ } ;
155+
156+ const refreshFilesList = ( ) => {
157+ setStructure ( prevStructure => {
158+ const newStructure = Object . assign ( structure , {
159+ root_folder : prevStructure . root_folder ,
160+ files : [ ] ,
161+ last_folder : prevStructure . last_folder ,
162+ offset : null ,
163+ search_query : prevStructure . search_query ,
164+ labels : prevStructure . labels ,
165+ } ) ;
166+ fetchFiles ( ) ;
167+ return newStructure ;
168+ } ) ;
169+ } ;
170+
113171 async function getStructure ( ) {
114172 const response = await fetch ( `${ baseUrl } structure/${ realm } ` ) ;
115173 if ( response . ok ) {
@@ -119,29 +177,29 @@ export default function FileSelectDialog(props) {
119177 }
120178 }
121179
122- async function fetchFiles ( folderId : string , searchQuery = '' ) {
180+ async function fetchFiles ( ) {
123181 const fetchUrl = ( ( ) => {
124- if ( searchQuery ) {
125- const params = new URLSearchParams ( { q : searchQuery } ) ;
126- return ` ${ baseUrl } ${ folderId } /search? ${ params . toString ( ) } ` ;
182+ const params = new URLSearchParams ( ) ;
183+ if ( structure . offset !== null ) {
184+ params . set ( 'offset' , String ( structure . offset ) ) ;
127185 }
128- return `${ baseUrl } ${ folderId } /list` ;
186+ if ( structure . search_query ) {
187+ params . set ( 'q' , structure . search_query ) ;
188+ return `${ baseUrl } ${ structure . last_folder } /search?${ params . toString ( ) } ` ;
189+ }
190+ return `${ baseUrl } ${ structure . last_folder } /list?${ params . toString ( ) } ` ;
129191 } ) ( ) ;
130- const newStructure = {
131- root_folder : structure . root_folder ,
132- last_folder : folderId ,
133- files : null ,
134- num_files : 0 ,
135- labels : structure . labels ,
136- } ;
137192 const response = await fetch ( fetchUrl ) ;
138193 if ( response . ok ) {
139194 const body = await response . json ( ) ;
140- newStructure . files = body . files ;
195+ setStructure ( {
196+ ...structure ,
197+ files : structure . files . concat ( body . files ) ,
198+ offset : body . offset ,
199+ } ) ;
141200 } else {
142201 console . error ( response ) ;
143202 }
144- setStructure ( newStructure ) ;
145203 }
146204
147205 function refreshStructure ( ) {
@@ -162,8 +220,8 @@ export default function FileSelectDialog(props) {
162220 settings = { { csrfToken, baseUrl, selectFile, labels : structure . labels } }
163221 /> : < >
164222 < MenuBar
165- lastFolderId = { structure . last_folder }
166- fetchFiles = { fetchFiles }
223+ refreshFilesList = { refreshFilesList }
224+ setSearchQuery = { setSearchQuery }
167225 openUploader = { ( ) => uploaderRef . current . openUploader ( ) }
168226 labels = { structure . labels }
169227 />
@@ -174,7 +232,7 @@ export default function FileSelectDialog(props) {
174232 baseUrl = { baseUrl }
175233 folder = { structure . root_folder }
176234 lastFolderId = { structure . last_folder }
177- fetchFiles = { fetchFiles }
235+ setCurrentFolder = { setCurrentFolder }
178236 refreshStructure = { refreshStructure }
179237 /> }
180238 </ ul >
@@ -187,7 +245,11 @@ export default function FileSelectDialog(props) {
187245 > {
188246 structure . files === null ?
189247 < div className = "status" > { gettext ( "Loading files…" ) } </ div > :
190- < FilesList files = { structure . files } numFiles = { structure . num_files } selectFile = { selectFile } />
248+ < FilesList
249+ structure = { structure }
250+ fetchFiles = { fetchFiles }
251+ selectFile = { selectFile }
252+ />
191253 } </ FileUploader >
192254 </ div >
193255 </ > }
0 commit comments