1414// You should have received a copy of the GNU Affero General Public License
1515// along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
17- import React , { useEffect , useState } from "react" ;
17+ import React , { useEffect , useRef , useState } from "react" ;
1818import { createStyles , Theme , withStyles } from "@material-ui/core/styles" ;
1919import Grid from "@material-ui/core/Grid" ;
2020import TextField from "@material-ui/core/TextField" ;
@@ -33,7 +33,7 @@ import {
3333 searchField ,
3434} from "../../../../Common/FormComponents/common/styleLibrary" ;
3535import PageHeader from "../../../../Common/PageHeader/PageHeader" ;
36- import { Button , Input } from "@material-ui/core" ;
36+ import { Button , Input , Typography } from "@material-ui/core" ;
3737import * as reactMoment from "react-moment" ;
3838import { CreateIcon } from "../../../../../../icons" ;
3939import BrowserBreadcrumbs from "../../../../ObjectBrowser/BrowserBreadcrumbs" ;
@@ -150,6 +150,30 @@ interface IListObjectsProps {
150150 fileDownloadStarted : typeof fileDownloadStarted ;
151151}
152152
153+ function useInterval ( callback : any , delay : number ) {
154+ const savedCallback = useRef < Function | null > ( null ) ;
155+
156+ // Remember the latest callback.
157+ useEffect ( ( ) => {
158+ savedCallback . current = callback ;
159+ } , [ callback ] ) ;
160+
161+ // Set up the interval.
162+ useEffect ( ( ) => {
163+ function tick ( ) {
164+ if ( savedCallback !== undefined && savedCallback . current ) {
165+ savedCallback . current ( ) ;
166+ }
167+ }
168+ if ( delay !== null ) {
169+ let id = setInterval ( tick , delay ) ;
170+ return ( ) => clearInterval ( id ) ;
171+ }
172+ } , [ delay ] ) ;
173+ }
174+
175+ const defLoading = < Typography component = "h3" > Loading...</ Typography > ;
176+
153177const ListObjects = ( {
154178 classes,
155179 match,
@@ -171,6 +195,41 @@ const ListObjects = ({
171195 const [ selectedObject , setSelectedObject ] = useState < string > ( "" ) ;
172196 const [ selectedBucket , setSelectedBucket ] = useState < string > ( "" ) ;
173197 const [ filterObjects , setFilterObjects ] = useState < string > ( "" ) ;
198+ const [ loadingPromise , setLoadingPromise ] = useState < Promise < any > | null > (
199+ null
200+ ) ;
201+ const [ loadingStartTime , setLoadingStartTime ] = useState < number > ( 0 ) ;
202+ const [ loadingMessage , setLoadingMessage ] = useState < React . ReactNode > (
203+ defLoading
204+ ) ;
205+
206+ const updateMessage = ( ) => {
207+ let timeDelta = Date . now ( ) - loadingStartTime ;
208+
209+ if ( timeDelta / 1000 >= 6 ) {
210+ setLoadingMessage (
211+ < React . Fragment >
212+ < Typography component = "h3" >
213+ This operation is taking longer than expected... (
214+ { Math . ceil ( timeDelta / 1000 ) } s)
215+ </ Typography >
216+ </ React . Fragment >
217+ ) ;
218+ } else if ( timeDelta / 1000 >= 3 ) {
219+ setLoadingMessage (
220+ < Typography component = "h3" >
221+ This operation is taking longer than expected...
222+ </ Typography >
223+ ) ;
224+ }
225+ } ;
226+
227+ useInterval ( ( ) => {
228+ // Your custom logic here
229+ if ( loading ) {
230+ updateMessage ( ) ;
231+ }
232+ } , 1000 ) ;
174233
175234 useEffect ( ( ) => {
176235 const bucketName = match . params [ "bucket" ] ;
@@ -206,7 +265,11 @@ const ListObjects = ({
206265 extraPath = `?prefix=${ internalPaths } /` ;
207266 }
208267
209- api
268+ let currentTimestamp = Date . now ( ) + 0 ;
269+ setLoadingStartTime ( currentTimestamp ) ;
270+ setLoadingMessage ( defLoading ) ;
271+
272+ let p = api
210273 . invoke ( "GET" , `/api/v1/buckets/${ bucketName } /objects${ extraPath } ` )
211274 . then ( ( res : BucketObjectsList ) => {
212275 setSelectedBucket ( bucketName ) ;
@@ -239,6 +302,7 @@ const ListObjects = ({
239302 setLoading ( false ) ;
240303 setErrorSnackMessage ( err ) ;
241304 } ) ;
305+ setLoadingPromise ( p ) ;
242306 }
243307 } , [ loading , match , setLastAsFile , setErrorSnackMessage ] ) ;
244308
@@ -558,6 +622,7 @@ const ListObjects = ({
558622 } ,
559623 ] }
560624 isLoading = { loading }
625+ loadingMessage = { loadingMessage }
561626 entityName = "Objects"
562627 idField = "name"
563628 records = { filteredRecords }
0 commit comments