diff --git a/ui/v2.5/src/hooks/ListHook.tsx b/ui/v2.5/src/hooks/ListHook.tsx index ed23c04ce..67c99811c 100644 --- a/ui/v2.5/src/hooks/ListHook.tsx +++ b/ui/v2.5/src/hooks/ListHook.tsx @@ -1,6 +1,6 @@ import _ from "lodash"; import queryString from "query-string"; -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useRef } from "react"; import { ApolloError } from "apollo-client"; import { useHistory, useLocation } from "react-router-dom"; import { @@ -16,6 +16,7 @@ import { FindStudiosQueryResult, FindPerformersQueryResult } from "src/core/generated-graphql"; +import { useInterfaceLocalForage } from 'src/hooks/LocalForage'; import { LoadingIndicator } from "src/components/Shared"; import { ListFilter } from "src/components/List/ListFilter"; import { Pagination } from "src/components/List/Pagination"; @@ -74,6 +75,8 @@ interface IQuery<T extends IQueryResult, T2 extends IDataItem> { const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>( options: IListHookOptions<QueryResult> & IQuery<QueryResult, QueryData> ): IListHookData => { + const [interfaceForage, setInterfaceForage] = useInterfaceLocalForage(); + const forageInitialised = useRef(false); const history = useHistory(); const location = useLocation(); const [filter, setFilter] = useState<ListFilterModel>( @@ -90,14 +93,56 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>( const totalCount = options.getCount(result); const items = options.getData(result); - useEffect(() => ( - setFilter( - new ListFilterModel( + useEffect(() => { + if(!forageInitialised.current && !interfaceForage.loading) { + forageInitialised.current = true; + + // Don't use query parameters for sub-components + if(options.subComponent) + return; + // Don't read localForage if page already had query parameters + if(history.location.search) + return; + + const queryData = interfaceForage.data?.queries[options.filterMode]; + if(!queryData) + return; + + const newFilter = new ListFilterModel( options.filterMode, - options.subComponent ? "" : queryString.parse(location.search) - ) - ) - ), [location, options.filterMode, options.subComponent]); + queryString.parse(queryData.filter) + ); + newFilter.currentPage = queryData.currentPage; + newFilter.itemsPerPage = queryData.itemsPerPage; + + const newLocation = { ...history.location }; + newLocation.search = queryData.filter; + history.replace(newLocation); + } + }, [interfaceForage.data, interfaceForage.loading, history, options.subComponent, options.filterMode]); + + useEffect(() => { + if(options.subComponent) + return; + + const newFilter = new ListFilterModel( + options.filterMode, + options.subComponent ? "" : queryString.parse(location.search) + ); + setFilter(newFilter); + + if(forageInitialised.current) { + setInterfaceForage((d) => { + const dataClone = _.cloneDeep(d); + dataClone!.queries[options.filterMode] = { + filter: location.search, + itemsPerPage: newFilter.itemsPerPage, + currentPage: newFilter.currentPage + }; + return dataClone; + }); + } + }, [location, options.filterMode, options.subComponent, setInterfaceForage]); function getFilter() { if (!options.filterHook) { diff --git a/ui/v2.5/src/hooks/LocalForage.ts b/ui/v2.5/src/hooks/LocalForage.ts index 56d1dc642..e11c45a78 100644 --- a/ui/v2.5/src/hooks/LocalForage.ts +++ b/ui/v2.5/src/hooks/LocalForage.ts @@ -1,22 +1,26 @@ import localForage from "localforage"; import _ from "lodash"; -import React from "react"; +import React, { Dispatch, SetStateAction } from "react"; interface IInterfaceWallConfig {} export interface IInterfaceConfig { wall: IInterfaceWallConfig; + queries: any; } type ValidTypes = IInterfaceConfig | undefined; interface ILocalForage<T> { data: T; - setData: React.Dispatch<React.SetStateAction<T>>; + setData: Dispatch<SetStateAction<T>>; error: Error | null; + loading: boolean; } function useLocalForage(item: string): ILocalForage<ValidTypes> { const [json, setJson] = React.useState<ValidTypes>(undefined); + const [err, setErr] = React.useState(null); + const [loaded, setLoaded] = React.useState<boolean>(false); const prevJson = React.useRef<ValidTypes>(undefined); React.useEffect(() => { @@ -29,7 +33,6 @@ function useLocalForage(item: string): ILocalForage<ValidTypes> { runAsync(); }); - const [err, setErr] = React.useState(null); React.useEffect(() => { async function runAsync() { try { @@ -42,26 +45,27 @@ function useLocalForage(item: string): ILocalForage<ValidTypes> { } catch (error) { setErr(error); } + setLoaded(true); } runAsync(); }); - return { data: json, setData: setJson, error: err }; + return {data: json, setData: setJson, error: err, loading: !loaded}; } -export function useInterfaceLocalForage(): ILocalForage< - IInterfaceConfig | undefined -> { +export function useInterfaceLocalForage(): [ILocalForage<IInterfaceConfig | undefined>, Dispatch<SetStateAction<IInterfaceConfig | undefined>>] { const result = useLocalForage("interface"); - // Set defaults - React.useEffect(() => { - if (result.data === undefined) { - result.setData({ - wall: { - // nothing here currently - } - }); - } - }); - return result; + + let returnVal = result; + if(!result.data?.queries) { + returnVal = { + ...result, + data: { + wall: {}, + queries: {} + } + }; + } + + return [returnVal, result.setData];; }