From ffa1fbda7f6ee58f32b24a71878cbd4cc8b448b2 Mon Sep 17 00:00:00 2001 From: InfiniteTF Date: Sun, 23 Aug 2020 04:54:52 +0200 Subject: [PATCH] Fix infinite load issue (#756) * Remove subcomponents to resolve infinite load issue --- ui/v2.5/src/components/List/ListFilter.tsx | 5 ++- .../components/Movies/MovieDetails/Movie.tsx | 1 - .../Movies/MovieDetails/MovieScenesPanel.tsx | 2 +- ui/v2.5/src/components/Movies/MovieList.tsx | 1 + ui/v2.5/src/components/Movies/Movies.tsx | 2 +- .../Performers/PerformerDetails/Performer.tsx | 17 +++++++--- .../PerformerDetailsPanel.tsx | 2 -- .../PerformerDetails/PerformerScenesPanel.tsx | 2 +- .../components/Performers/PerformerList.tsx | 1 + .../src/components/Performers/Performers.tsx | 2 +- .../Scenes/SceneDetails/SceneEditPanel.tsx | 2 -- ui/v2.5/src/components/Scenes/SceneList.tsx | 6 ++-- .../src/components/Scenes/SceneMarkerList.tsx | 7 +--- ui/v2.5/src/components/Scenes/Scenes.tsx | 6 +++- .../Studios/StudioDetails/Studio.tsx | 24 ++++++++++---- .../StudioDetails/StudioScenesPanel.tsx | 2 +- ui/v2.5/src/components/Studios/StudioList.tsx | 1 - ui/v2.5/src/components/Studios/Studios.tsx | 2 +- .../src/components/Tags/TagDetails/Tag.tsx | 23 +++++++++---- .../Tags/TagDetails/TagMarkersPanel.tsx | 2 +- .../Tags/TagDetails/TagScenesPanel.tsx | 2 +- ui/v2.5/src/components/Tags/TagList.tsx | 1 + ui/v2.5/src/components/Tags/Tags.tsx | 2 +- ui/v2.5/src/hooks/ListHook.tsx | 32 ++++++++++--------- 24 files changed, 88 insertions(+), 59 deletions(-) diff --git a/ui/v2.5/src/components/List/ListFilter.tsx b/ui/v2.5/src/components/List/ListFilter.tsx index c6581a6e3..b6a0bf67c 100644 --- a/ui/v2.5/src/components/List/ListFilter.tsx +++ b/ui/v2.5/src/components/List/ListFilter.tsx @@ -29,7 +29,6 @@ interface IListFilterOperation { } interface IListFilterProps { - subComponent?: boolean; onFilterUpdate: (newFilter: ListFilterModel) => void; zoomIndex?: number; onChangeZoom?: (zoomIndex: number) => void; @@ -105,7 +104,7 @@ export const ListFilter: React.FC = ( Mousetrap.bind("s a", () => onSelectAll()); Mousetrap.bind("s n", () => onSelectNone()); - if (!props.subComponent && props.itemsSelected) { + if (props.itemsSelected) { Mousetrap.bind("e", () => { if (props.onEdit) { props.onEdit(); @@ -130,7 +129,7 @@ export const ListFilter: React.FC = ( Mousetrap.unbind("s a"); Mousetrap.unbind("s n"); - if (!props.subComponent && props.itemsSelected) { + if (props.itemsSelected) { Mousetrap.unbind("e"); Mousetrap.unbind("d d"); } diff --git a/ui/v2.5/src/components/Movies/MovieDetails/Movie.tsx b/ui/v2.5/src/components/Movies/MovieDetails/Movie.tsx index 68964ebc1..436456259 100644 --- a/ui/v2.5/src/components/Movies/MovieDetails/Movie.tsx +++ b/ui/v2.5/src/components/Movies/MovieDetails/Movie.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/no-this-in-sfc */ import React, { useEffect, useState, useCallback } from "react"; import { useIntl } from "react-intl"; import * as GQL from "src/core/generated-graphql"; diff --git a/ui/v2.5/src/components/Movies/MovieDetails/MovieScenesPanel.tsx b/ui/v2.5/src/components/Movies/MovieDetails/MovieScenesPanel.tsx index a705942df..8a6f8c7be 100644 --- a/ui/v2.5/src/components/Movies/MovieDetails/MovieScenesPanel.tsx +++ b/ui/v2.5/src/components/Movies/MovieDetails/MovieScenesPanel.tsx @@ -42,7 +42,7 @@ export const MovieScenesPanel: React.FC = ({ movie }) => { } if (movie && movie.id) { - return ; + return ; } return <>; }; diff --git a/ui/v2.5/src/components/Movies/MovieList.tsx b/ui/v2.5/src/components/Movies/MovieList.tsx index f58e02771..a8a5cdba3 100644 --- a/ui/v2.5/src/components/Movies/MovieList.tsx +++ b/ui/v2.5/src/components/Movies/MovieList.tsx @@ -8,6 +8,7 @@ import { MovieCard } from "./MovieCard"; export const MovieList: React.FC = () => { const listData = useMoviesList({ renderContent, + persistState: true, }); function renderContent( diff --git a/ui/v2.5/src/components/Movies/Movies.tsx b/ui/v2.5/src/components/Movies/Movies.tsx index 387f6391c..6649d63f0 100644 --- a/ui/v2.5/src/components/Movies/Movies.tsx +++ b/ui/v2.5/src/components/Movies/Movies.tsx @@ -6,7 +6,7 @@ import { MovieList } from "./MovieList"; const Movies = () => ( - + ); diff --git a/ui/v2.5/src/components/Performers/PerformerDetails/Performer.tsx b/ui/v2.5/src/components/Performers/PerformerDetails/Performer.tsx index 1ef5fe40a..2b2b414a5 100644 --- a/ui/v2.5/src/components/Performers/PerformerDetails/Performer.tsx +++ b/ui/v2.5/src/components/Performers/PerformerDetails/Performer.tsx @@ -20,7 +20,7 @@ import { PerformerScenesPanel } from "./PerformerScenesPanel"; export const Performer: React.FC = () => { const Toast = useToast(); const history = useHistory(); - const { id = "new" } = useParams(); + const { tab = "details", id = "new" } = useParams(); const isNew = id === "new"; // Performer state @@ -42,13 +42,22 @@ export const Performer: React.FC = () => { // Network state const [isLoading, setIsLoading] = useState(false); - const [activeTabKey, setActiveTabKey] = useState("details"); - const { data, error } = useFindPerformer(id); const [updatePerformer] = usePerformerUpdate(); const [createPerformer] = usePerformerCreate(); const [deletePerformer] = usePerformerDestroy(); + const activeTabKey = + tab === "scenes" || tab === "edit" || tab === "operations" + ? tab + : "details"; + const setActiveTabKey = (newTab: string) => { + if (tab !== newTab) { + const tabParam = newTab === "details" ? "" : `/${newTab}`; + history.replace(`/performers/${id}${tabParam}`); + } + }; + useEffect(() => { setIsLoading(false); if (data?.findPerformer) setPerformer(data.findPerformer); @@ -128,7 +137,7 @@ export const Performer: React.FC = () => { const renderTabs = () => ( setActiveTabKey(k)} + onSelect={setActiveTabKey} id="performer-details" unmountOnExit > diff --git a/ui/v2.5/src/components/Performers/PerformerDetails/PerformerDetailsPanel.tsx b/ui/v2.5/src/components/Performers/PerformerDetails/PerformerDetailsPanel.tsx index c23443e1f..900015bc3 100644 --- a/ui/v2.5/src/components/Performers/PerformerDetails/PerformerDetailsPanel.tsx +++ b/ui/v2.5/src/components/Performers/PerformerDetails/PerformerDetailsPanel.tsx @@ -1,5 +1,3 @@ -/* eslint-disable react/no-this-in-sfc */ - import React, { useEffect, useState } from "react"; import { useIntl } from "react-intl"; import { Button, Popover, OverlayTrigger, Table } from "react-bootstrap"; diff --git a/ui/v2.5/src/components/Performers/PerformerDetails/PerformerScenesPanel.tsx b/ui/v2.5/src/components/Performers/PerformerDetails/PerformerScenesPanel.tsx index 1ca04cef4..dabe47153 100644 --- a/ui/v2.5/src/components/Performers/PerformerDetails/PerformerScenesPanel.tsx +++ b/ui/v2.5/src/components/Performers/PerformerDetails/PerformerScenesPanel.tsx @@ -43,5 +43,5 @@ export const PerformerScenesPanel: React.FC = ({ return filter; } - return ; + return ; }; diff --git a/ui/v2.5/src/components/Performers/PerformerList.tsx b/ui/v2.5/src/components/Performers/PerformerList.tsx index dc637d097..a0f45d2c4 100644 --- a/ui/v2.5/src/components/Performers/PerformerList.tsx +++ b/ui/v2.5/src/components/Performers/PerformerList.tsx @@ -35,6 +35,7 @@ export const PerformerList: React.FC = () => { otherOperations, renderContent, addKeybinds, + persistState: true, }); async function getRandom( diff --git a/ui/v2.5/src/components/Performers/Performers.tsx b/ui/v2.5/src/components/Performers/Performers.tsx index fd2c77b91..cac8dfdc8 100644 --- a/ui/v2.5/src/components/Performers/Performers.tsx +++ b/ui/v2.5/src/components/Performers/Performers.tsx @@ -6,7 +6,7 @@ import { PerformerList } from "./PerformerList"; const Performers = () => ( - + ); diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx index 78cb7f32b..ab7ea6b3d 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneEditPanel.tsx @@ -1,5 +1,3 @@ -/* eslint-disable react/no-this-in-sfc */ - import React, { useEffect, useState } from "react"; import { Button, diff --git a/ui/v2.5/src/components/Scenes/SceneList.tsx b/ui/v2.5/src/components/Scenes/SceneList.tsx index 40a4fc374..572554905 100644 --- a/ui/v2.5/src/components/Scenes/SceneList.tsx +++ b/ui/v2.5/src/components/Scenes/SceneList.tsx @@ -18,13 +18,13 @@ import { DeleteScenesDialog } from "./DeleteScenesDialog"; import { SceneGenerateDialog } from "./SceneGenerateDialog"; interface ISceneList { - subComponent?: boolean; filterHook?: (filter: ListFilterModel) => ListFilterModel; + persistState?: boolean; } export const SceneList: React.FC = ({ - subComponent, filterHook, + persistState, }) => { const history = useHistory(); const [isGenerateDialogOpen, setIsGenerateDialogOpen] = useState(false); @@ -61,9 +61,9 @@ export const SceneList: React.FC = ({ renderContent, renderEditDialog: renderEditScenesDialog, renderDeleteDialog: renderDeleteScenesDialog, - subComponent, filterHook, addKeybinds, + persistState, }); async function playRandom( diff --git a/ui/v2.5/src/components/Scenes/SceneMarkerList.tsx b/ui/v2.5/src/components/Scenes/SceneMarkerList.tsx index defe959cc..10a9cb364 100644 --- a/ui/v2.5/src/components/Scenes/SceneMarkerList.tsx +++ b/ui/v2.5/src/components/Scenes/SceneMarkerList.tsx @@ -10,14 +10,10 @@ import { DisplayMode } from "src/models/list-filter/types"; import { WallPanel } from "../Wall/WallPanel"; interface ISceneMarkerList { - subComponent?: boolean; filterHook?: (filter: ListFilterModel) => ListFilterModel; } -export const SceneMarkerList: React.FC = ({ - subComponent, - filterHook, -}) => { +export const SceneMarkerList: React.FC = ({ filterHook }) => { const history = useHistory(); const otherOperations = [ { @@ -42,7 +38,6 @@ export const SceneMarkerList: React.FC = ({ const listData = useSceneMarkersList({ otherOperations, renderContent, - subComponent, filterHook, addKeybinds, }); diff --git a/ui/v2.5/src/components/Scenes/Scenes.tsx b/ui/v2.5/src/components/Scenes/Scenes.tsx index da5ec7fd5..95bbb46f2 100644 --- a/ui/v2.5/src/components/Scenes/Scenes.tsx +++ b/ui/v2.5/src/components/Scenes/Scenes.tsx @@ -6,7 +6,11 @@ import { SceneMarkerList } from "./SceneMarkerList"; const Scenes = () => ( - + } + /> diff --git a/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx b/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx index 0acad3bb2..22bfece5b 100644 --- a/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx +++ b/ui/v2.5/src/components/Studios/StudioDetails/Studio.tsx @@ -1,5 +1,3 @@ -/* eslint-disable react/no-this-in-sfc */ - import { Table, Tabs, Tab } from "react-bootstrap"; import React, { useEffect, useState } from "react"; import { useParams, useHistory } from "react-router-dom"; @@ -27,7 +25,7 @@ import { StudioChildrenPanel } from "./StudioChildrenPanel"; export const Studio: React.FC = () => { const history = useHistory(); const Toast = useToast(); - const { id = "new" } = useParams(); + const { tab = "details", id = "new" } = useParams(); const isNew = id === "new"; // Editing state @@ -192,6 +190,14 @@ export const Studio: React.FC = () => { ); } + const activeTabKey = tab === "childstudios" ? tab : "scenes"; + const setActiveTabKey = (newTab: string) => { + if (tab !== newTab) { + const tabParam = newTab === "scenes" ? "" : `/${newTab}`; + history.replace(`/studios/${id}${tabParam}`); + } + }; + return (
{
{!isNew && (
- - + + - + diff --git a/ui/v2.5/src/components/Studios/StudioDetails/StudioScenesPanel.tsx b/ui/v2.5/src/components/Studios/StudioDetails/StudioScenesPanel.tsx index a8fd30f1e..952c0d33a 100644 --- a/ui/v2.5/src/components/Studios/StudioDetails/StudioScenesPanel.tsx +++ b/ui/v2.5/src/components/Studios/StudioDetails/StudioScenesPanel.tsx @@ -41,5 +41,5 @@ export const StudioScenesPanel: React.FC = ({ studio }) => { return filter; } - return ; + return ; }; diff --git a/ui/v2.5/src/components/Studios/StudioList.tsx b/ui/v2.5/src/components/Studios/StudioList.tsx index 10d2dde7f..b6a5d5cd0 100644 --- a/ui/v2.5/src/components/Studios/StudioList.tsx +++ b/ui/v2.5/src/components/Studios/StudioList.tsx @@ -16,7 +16,6 @@ export const StudioList: React.FC = ({ }) => { const listData = useStudiosList({ renderContent, - subComponent: fromParent, filterHook, }); diff --git a/ui/v2.5/src/components/Studios/Studios.tsx b/ui/v2.5/src/components/Studios/Studios.tsx index be3526977..e466319e9 100644 --- a/ui/v2.5/src/components/Studios/Studios.tsx +++ b/ui/v2.5/src/components/Studios/Studios.tsx @@ -6,7 +6,7 @@ import { StudioList } from "./StudioList"; const Studios = () => ( - + ); diff --git a/ui/v2.5/src/components/Tags/TagDetails/Tag.tsx b/ui/v2.5/src/components/Tags/TagDetails/Tag.tsx index 1572f6628..ee409875e 100644 --- a/ui/v2.5/src/components/Tags/TagDetails/Tag.tsx +++ b/ui/v2.5/src/components/Tags/TagDetails/Tag.tsx @@ -1,5 +1,3 @@ -/* eslint-disable react/no-this-in-sfc */ - import { Table, Tabs, Tab } from "react-bootstrap"; import React, { useEffect, useState } from "react"; import { useParams, useHistory } from "react-router-dom"; @@ -26,7 +24,7 @@ import { TagMarkersPanel } from "./TagMarkersPanel"; export const Tag: React.FC = () => { const history = useHistory(); const Toast = useToast(); - const { id = "new" } = useParams(); + const { tab = "scenes", id = "new" } = useParams(); const isNew = id === "new"; // Editing state @@ -46,6 +44,14 @@ export const Tag: React.FC = () => { const [createTag] = useTagCreate(getTagInput() as GQL.TagUpdateInput); const [deleteTag] = useTagDestroy(getTagInput() as GQL.TagUpdateInput); + const activeTabKey = tab === "markers" ? tab : "scenes"; + const setActiveTabKey = (newTab: string) => { + if (tab !== newTab) { + const tabParam = newTab === "scenes" ? "" : `/${newTab}`; + history.replace(`/tags/${id}${tabParam}`); + } + }; + // set up hotkeys useEffect(() => { if (isEditing) { @@ -222,11 +228,16 @@ export const Tag: React.FC = () => {
{!isNew && (
- - + + - + diff --git a/ui/v2.5/src/components/Tags/TagDetails/TagMarkersPanel.tsx b/ui/v2.5/src/components/Tags/TagDetails/TagMarkersPanel.tsx index 38380eb86..e8595cfab 100644 --- a/ui/v2.5/src/components/Tags/TagDetails/TagMarkersPanel.tsx +++ b/ui/v2.5/src/components/Tags/TagDetails/TagMarkersPanel.tsx @@ -41,5 +41,5 @@ export const TagMarkersPanel: React.FC = ({ tag }) => { return filter; } - return ; + return ; }; diff --git a/ui/v2.5/src/components/Tags/TagDetails/TagScenesPanel.tsx b/ui/v2.5/src/components/Tags/TagDetails/TagScenesPanel.tsx index 9654750f7..1b29ebda7 100644 --- a/ui/v2.5/src/components/Tags/TagDetails/TagScenesPanel.tsx +++ b/ui/v2.5/src/components/Tags/TagDetails/TagScenesPanel.tsx @@ -41,5 +41,5 @@ export const TagScenesPanel: React.FC = ({ tag }) => { return filter; } - return ; + return ; }; diff --git a/ui/v2.5/src/components/Tags/TagList.tsx b/ui/v2.5/src/components/Tags/TagList.tsx index 80d48471a..6044506a7 100644 --- a/ui/v2.5/src/components/Tags/TagList.tsx +++ b/ui/v2.5/src/components/Tags/TagList.tsx @@ -30,6 +30,7 @@ export const TagList: React.FC = ({ filterHook }) => { filterHook, zoomable: true, defaultZoomIndex: 0, + persistState: true, }); function getDeleteTagInput() { diff --git a/ui/v2.5/src/components/Tags/Tags.tsx b/ui/v2.5/src/components/Tags/Tags.tsx index 4865972f1..9c80d44c2 100644 --- a/ui/v2.5/src/components/Tags/Tags.tsx +++ b/ui/v2.5/src/components/Tags/Tags.tsx @@ -6,7 +6,7 @@ import { TagList } from "./TagList"; const Tags = () => ( - + ); diff --git a/ui/v2.5/src/hooks/ListHook.tsx b/ui/v2.5/src/hooks/ListHook.tsx index ba2ed3424..4d8f5736d 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, { useCallback, useState, useEffect } from "react"; +import React, { useCallback, useRef, useState, useEffect } from "react"; import { ApolloError } from "apollo-client"; import { useHistory, useLocation } from "react-router-dom"; import { @@ -59,7 +59,7 @@ interface IListHookOperation { } interface IListHookOptions { - subComponent?: boolean; + persistState?: boolean; filterHook?: (filter: ListFilterModel) => ListFilterModel; zoomable?: boolean; selectable?: boolean; @@ -112,10 +112,7 @@ const useList = ( const history = useHistory(); const location = useLocation(); const [filter, setFilter] = useState( - new ListFilterModel( - options.filterMode, - options.subComponent ? undefined : queryString.parse(location.search) - ) + new ListFilterModel(options.filterMode, queryString.parse(location.search)) ); const [isEditDialogOpen, setIsEditDialogOpen] = useState(false); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); @@ -124,6 +121,8 @@ const useList = ( const [zoomIndex, setZoomIndex] = useState( options.defaultZoomIndex ?? 1 ); + // Store initial pathname to prevent hooks from operating outside this page + const originalPathName = useRef(location.pathname); const result = options.useData(getFilter()); const totalCount = options.getCount(result); @@ -194,11 +193,15 @@ const useList = ( ); useEffect(() => { - if (interfaceState.loading) return; + if ( + interfaceState.loading || + // Only update query params on page the hook was mounted on + history.location.pathname !== originalPathName.current + ) + return; if (!forageInitialised) setForageInitialised(true); - // Don't use query parameters for sub-components - if (options.subComponent) return; + if (!options.persistState) return; const storedQuery = interfaceState.data?.queries?.[options.filterMode]; if (!storedQuery) return; @@ -236,10 +239,10 @@ const useList = ( interfaceState.loading, history, location.search, - options.subComponent, options.filterMode, forageInitialised, updateInterfaceConfig, + options.persistState, ]); function getFilter() { @@ -254,10 +257,10 @@ const useList = ( function updateQueryParams(listFilter: ListFilterModel) { setFilter(listFilter); - if (!options.subComponent) { - const newLocation = { ...location }; - newLocation.search = listFilter.makeQueryParameters(); - history.replace(newLocation); + const newLocation = { ...location }; + newLocation.search = listFilter.makeQueryParameters(); + history.replace(newLocation); + if (options.persistState) { updateInterfaceConfig(listFilter); } } @@ -425,7 +428,6 @@ const useList = ( const template = (