Add loading screen for remote fetch and refactor loading ellipses

This commit is contained in:
SleeplessOne1917 2023-07-21 20:22:16 -04:00
parent f580e2d8b7
commit 792c0e63a9
3 changed files with 63 additions and 28 deletions

View file

@ -0,0 +1,34 @@
import { Component } from "inferno";
interface LoadingEllipsesState {
ellipses: string;
}
export class LoadingEllipses extends Component<any, LoadingEllipsesState> {
state: LoadingEllipsesState = {
ellipses: "...",
};
#interval?: NodeJS.Timer;
constructor(props: any, context: any) {
super(props, context);
}
render() {
return this.state.ellipses;
}
componentDidMount() {
this.#interval = setInterval(this.#updateEllipses, 1000);
}
componentWillUnmount() {
clearInterval(this.#interval);
}
#updateEllipses = () => {
this.setState(({ ellipses }) => ({
ellipses: ellipses.length === 3 ? "" : ellipses + ".",
}));
};
}

View file

@ -9,6 +9,7 @@ import {
} from "inferno";
import { I18NextService } from "../../services";
import { Icon, Spinner } from "./icon";
import { LoadingEllipses } from "./loading-ellipses";
interface SearchableSelectProps {
id: string;
@ -22,7 +23,6 @@ interface SearchableSelectProps {
interface SearchableSelectState {
selectedIndex: number;
searchText: string;
loadingEllipses: string;
}
function handleSearch(i: SearchableSelect, e: ChangeEvent<HTMLInputElement>) {
@ -70,12 +70,10 @@ export class SearchableSelect extends Component<
> {
searchInputRef: RefObject<HTMLInputElement> = createRef();
toggleButtonRef: RefObject<HTMLButtonElement> = createRef();
private loadingEllipsesInterval?: NodeJS.Timer = undefined;
state: SearchableSelectState = {
selectedIndex: 0,
searchText: "",
loadingEllipses: "...",
};
constructor(props: SearchableSelectProps, context: any) {
@ -99,7 +97,7 @@ export class SearchableSelect extends Component<
render() {
const { id, options, onSearch, loading } = this.props;
const { searchText, selectedIndex, loadingEllipses } = this.state;
const { searchText, selectedIndex } = this.state;
return (
<div className="searchable-select dropdown col-12 col-sm-auto flex-grow-1">
@ -116,9 +114,14 @@ export class SearchableSelect extends Component<
onClick={linkEvent(this, focusSearch)}
ref={this.toggleButtonRef}
>
{loading
? `${I18NextService.i18n.t("loading")}${loadingEllipses}`
: options[selectedIndex].label}
{loading ? (
<>
{I18NextService.i18n.t("loading")}
<LoadingEllipses />
</>
) : (
options[selectedIndex].label
)}
</button>
<div className="modlog-choices-font-size dropdown-menu w-100 p-2">
<div className="input-group">
@ -180,24 +183,4 @@ export class SearchableSelect extends Component<
selectedIndex,
};
}
componentDidUpdate() {
const { loading } = this.props;
if (loading && !this.loadingEllipsesInterval) {
this.loadingEllipsesInterval = setInterval(() => {
this.setState(({ loadingEllipses }) => ({
loadingEllipses:
loadingEllipses.length === 3 ? "" : loadingEllipses + ".",
}));
}, 750);
} else if (!loading && this.loadingEllipsesInterval) {
clearInterval(this.loadingEllipsesInterval);
}
}
componentWillUnmount() {
if (this.loadingEllipsesInterval) {
clearInterval(this.loadingEllipsesInterval);
}
}
}

View file

@ -8,6 +8,8 @@ import { InitialFetchRequest } from "../interfaces";
import { FirstLoadService, HttpService, I18NextService } from "../services";
import { RequestState } from "../services/HttpService";
import { HtmlTags } from "./common/html-tags";
import { Spinner } from "./common/icon";
import { LoadingEllipses } from "./common/loading-ellipses";
interface RemoteFetchProps {
uri?: string;
@ -90,7 +92,9 @@ export class RemoteFetch extends Component<any, RemoteFetchState> {
}
get content() {
const status: "success" | "loading" | "empty" = "success";
const status = "loading" as "success" | "loading" | "empty";
const { uri } = getRemoteFetchQueryParams();
switch (status) {
case "success": {
@ -103,6 +107,20 @@ export class RemoteFetch extends Component<any, RemoteFetchState> {
</>
);
}
case "loading": {
return (
<>
<h1>
Fetching {uri ? uriToQuery(uri) : "remote community"}
<LoadingEllipses />
</h1>
<h5>
<Spinner large />
</h5>
</>
);
}
}
}