import { action, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import ReactLoading from 'react-loading'; import { Doc } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { StrCast } from '../../../fields/Types'; import { Networking } from '../../Network'; import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { FieldView, FieldViewProps } from './FieldView'; import './LoadingBox.scss'; /** * LoadingBox Class represents a placeholder doc for documents that are currently * being uploaded to the server and being fetched by the client. The LoadingBox doc is then used to * generate the actual type of doc that is required once the document has been successfully uploaded. * * Design considerations: * We are using the docToFiles map in Documents to keep track of all files being uploaded in one session of the client. * If the file is not found we assume an error has occurred with the file upload, e.g. it has been interrupted by a client refresh * or network issues. The docToFiles essentially gets reset everytime the page is refreshed. * * TODOs: * 1) ability to query server to retrieve files that already exist if users upload duplicate files. * 2) ability to restart upload if there is an error * 3) detect network error and notify the user * 4 )if file upload gets interrupted, it still gets uploaded to the server if there are no network interruptions which leads to unused space. this could be * handled with (1) * 5) Fixing the stacking view bug * 6) Fixing the CSS * * @author naafiyan */ @observer export class LoadingBox extends ViewBoxAnnotatableComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LoadingBox, fieldKey); } @observable public static CurrentlyLoading: Doc[] = []; // this assignment doesn't work. the actual assignment happens in DocumentManager's constructor // removes from currently loading display @action public static removeCurrentlyLoading(doc: Doc) { if (LoadingBox.CurrentlyLoading) { const index = LoadingBox.CurrentlyLoading.indexOf(doc); index !== -1 && LoadingBox.CurrentlyLoading.splice(index, 1); } } // adds doc to currently loading display @action public static addCurrentlyLoading(doc: Doc) { if (LoadingBox.CurrentlyLoading.indexOf(doc) === -1) { LoadingBox.CurrentlyLoading.push(doc); } } _timer: any; @observable progress = ''; componentDidMount() { if (!LoadingBox.CurrentlyLoading?.includes(this.rootDoc)) { this.rootDoc.loadingError = 'Upload interrupted, please try again'; } else { const updateFunc = async () => { const result = await Networking.QueryYoutubeProgress(StrCast(this.rootDoc[Id])); // We use the guid of the overwriteDoc to track file uploads. runInAction(() => (this.progress = result.progress)); !this.rootDoc.loadingError && (this._timer = setTimeout(updateFunc, 1000)); }; this._timer = setTimeout(updateFunc, 1000); } } componentWillUnmount() { clearTimeout(this._timer); } render() { return (
{StrCast(this.rootDoc.title)}

{StrCast(this.rootDoc.loadingError, 'Loading ' + (this.progress.replace('[download]', '') || '(can take several minutes)'))}

{this.rootDoc.loadingError ? null : (
)}
); } }