UNPKG

@kwiz/fluentui

Version:
85 lines 5.17 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { jsx as _jsx } from "react/jsx-runtime"; import { CommonLogger, debounce, firstIndexOf, firstOrNull, isNotEmptyString, isNullOrEmptyString, isNumber, promiseOnce } from "@kwiz/common"; import { isValidElement, useCallback, useMemo, useRef } from "react"; import { Loading } from "../controls/loading"; import { PleaseWait } from "../controls/please-wait"; import { useStateEX } from "./hooks"; const logger = new CommonLogger("useReloadTracker"); /** a simple reload marker, can be used as a dependency, and called as a function */ export function useReloadTracker(props) { const [reloadKey, setReload, reloadKeyRef] = useStateEX({ global: 1 }); const promises = useRef([]); let counter = useRef(1); const reload = useCallback(debounce((scope) => { const rk = Object.assign({}, reloadKeyRef.current); if (scope === "global" || isNullOrEmptyString(scope)) { //if global - notify all listeners Object.keys(rk).forEach(s => { rk[s] = (isNumber(rk[s]) ? rk[s] : 0) + 1; }); logger.debug('Reload all scopes'); } else { //notify only listeners for my scope + global listeners rk[scope] = (isNumber(rk[scope]) ? rk[scope] : 0) + 1; rk.global++; logger.debug(`Reload ${scope}: ${rk[scope]}, and global: ${rk.global}`); } setReload(rk); }, 100), []); const [isLoading, setLoading, isLoadingRef] = useStateEX({ type: "idle" }, { skipUpdateIfSame: true }); //this does not have dependencies, never changes, so unsafe to use state. use stateRef objects. const queue = useCallback((promise, info) => __awaiter(this, void 0, void 0, function* () { const type = (info === null || info === void 0 ? void 0 : info.type) || "optional"; if (isLoadingRef.current.type !== "required") //if its required - do not update this back to optional setLoading({ type, label: info.label }); const myId = counter.current++; promises.current.push({ id: myId, type, label: info === null || info === void 0 ? void 0 : info.label }); try { return yield (isNotEmptyString(info.cacheKey) ? (() => { const cache_reloadKey = isNotEmptyString(info.cacheScope) ? `${info.cacheScope}:${reloadKeyRef.current[info.cacheScope] || 0}` : `global:${reloadKeyRef.current.global}`; const promiseOnceCacheKey = `${cache_reloadKey}|${info.cacheKey}`; logger.log(promiseOnceCacheKey); return promiseOnce(promiseOnceCacheKey, promise); })() : promise()); } finally { //remove this promise const myIndex = firstIndexOf(promises.current, p => p.id === myId); promises.current.splice(myIndex, 1); //if no more promises - set loading to false if (promises.current.length === 0) setLoading({ type: "idle" }); //else, if it is state required and no more required promiese - drop it to optional else { //drop the label/type to the next promise in queue, prioritize required ones. const nextPromise = firstOrNull(promises.current, p_1 => p_1.type === "required") || promises.current[0]; setLoading({ type: nextPromise.type, label: nextPromise.label }); } } }), []); const reloadElement = useMemo(() => { return (isLoading === null || isLoading === void 0 ? void 0 : isLoading.type) === "required" ? isValidElement(props === null || props === void 0 ? void 0 : props.requiredElement) ? props.requiredElement : _jsx(Loading, Object.assign({ fullsize: true, label: isLoading.label }, props === null || props === void 0 ? void 0 : props.requiredElement)) : (isLoading === null || isLoading === void 0 ? void 0 : isLoading.type) === "optional" ? isValidElement(props === null || props === void 0 ? void 0 : props.optionalElement) ? props.optionalElement : _jsx(PleaseWait, Object.assign({ label: isLoading.label }, props === null || props === void 0 ? void 0 : props.optionalElement)) : undefined; }, [isLoading.type, isLoading.label]); return { reloadKey, reload, isLoading, queue, reloadElement }; } //# sourceMappingURL=use-reload-tracker.js.map