Skip to content

Commit

Permalink
Refactor ServerData as context, optimize some unnecessary renders
Browse files Browse the repository at this point in the history
  • Loading branch information
qu1ck committed Jul 17, 2023
1 parent 5b3c41a commit 54eb674
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 163 deletions.
64 changes: 35 additions & 29 deletions src/components/details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,39 @@ function ServerStats() {
);
}

const DetailsPanels = React.memo(function DetailsPanels({ torrent }: { torrent: Torrent | undefined }) {
return (<>
<Tabs.Panel value="general" h="100%">
{torrent !== undefined
? <GeneralPane torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="files" h="100%">
{torrent !== undefined
? <FileTreePane torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="pieces" h="100%">
{torrent !== undefined
? <PiecesCanvas torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="peers" h="100%">
{torrent !== undefined
? <PeersTable torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="trackers" h="100%">
{torrent !== undefined
? <TrackersTable torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="serverstats" h="100%">
<ServerStats />
</Tabs.Panel>
</>);
});

function Details(props: DetailsProps) {
const config = useContext(ConfigContext);
const peersTableVisibility = config.getTableColumnVisibility("peers");
Expand All @@ -388,7 +421,7 @@ function Details(props: DetailsProps) {

return (
<Tabs variant="outline" defaultValue="general" keepMounted={false}
h="100%" w="100%" style={{ display: "flex", flexDirection: "column" }}>
h="100%" w="100%" sx={{ display: "flex", flexDirection: "column" }}>
<Tabs.List px="sm" pt="xs">
<Tabs.Tab value="general" disabled={torrent === undefined}>
<Group>
Expand Down Expand Up @@ -432,34 +465,7 @@ function Details(props: DetailsProps) {
visible={props.torrentId !== undefined && isLoading} transitionDuration={500}
loaderProps={{ size: "xl" }}
overlayOpacity={0.35} />
<Tabs.Panel value="general" h="100%">
{torrent !== undefined
? <GeneralPane torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="files" h="100%">
{torrent !== undefined
? <FileTreePane torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="pieces" h="100%">
{torrent !== undefined
? <PiecesCanvas torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="peers" h="100%">
{torrent !== undefined
? <PeersTable torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="trackers" h="100%">
{torrent !== undefined
? <TrackersTable torrent={torrent} />
: <></>}
</Tabs.Panel>
<Tabs.Panel value="serverstats" h="100%">
<ServerStats />
</Tabs.Panel>
<DetailsPanels torrent={torrent} />
</div>
</Tabs>
);
Expand Down
10 changes: 4 additions & 6 deletions src/components/filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ function flattenTree(root: Directory): Directory[] {
return result;
}

export function Filters(props: FiltersProps) {
export const Filters = React.memo(function Filters(props: FiltersProps) {
const config = useContext(ConfigContext);
const serverConfig = useContext(ServerConfigContext);
const forceRender = useForceRender();
Expand All @@ -274,11 +274,9 @@ export function Filters(props: FiltersProps) {
() => props.torrents.map((t) => t.downloadDir as string).sort(),
[props.torrents]);

const [dirs, setDirs] = useState<Directory[]>([]);

useEffect(() => {
const dirs = useMemo<Directory[]>(() => {
const tree = buildDirTree(paths, serverConfig.expandedDirFilters);
setDirs(flattenTree(tree));
return flattenTree(tree);
}, [paths, serverConfig.expandedDirFilters]);

const allFilters = useMemo<AllFilters>(() => {
Expand Down Expand Up @@ -350,4 +348,4 @@ export function Filters(props: FiltersProps) {
</div>}
</Flex>
);
}
});
58 changes: 24 additions & 34 deletions src/components/modals/add.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@

import { Box, Button, Checkbox, Divider, Flex, Group, Menu, Overlay, SegmentedControl, Text, TextInput, useMantineTheme } from "@mantine/core";
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import type { ActionModalState, LabelsData, LocationData } from "./common";
import type { ModalState, LocationData } from "./common";
import { HkModal, TorrentLabels, TorrentLocation, limitTorrentNames, useTorrentLocation } from "./common";
import type { PriorityNumberType } from "rpc/transmission";
import { PriorityColors, PriorityStrings } from "rpc/transmission";
import type { Torrent } from "rpc/torrent";
import { useServerTorrentData, type Torrent } from "rpc/torrent";
import { CachedFileTree } from "cachedfiletree";
import { FileTreeTable, useUnwantedFiles } from "components/tables/filetreetable";
import { notifications } from "@mantine/notifications";
Expand All @@ -35,7 +35,8 @@ const { TAURI, dialogOpen, invoke } = await import(/* webpackChunkName: "taurish

interface AddCommonProps extends React.PropsWithChildren {
location: LocationData,
labelsData: LabelsData,
labels: string[],
setLabels: React.Dispatch<string[]>,
start: boolean,
setStart: (b: boolean) => void,
priority: PriorityNumberType,
Expand All @@ -46,7 +47,7 @@ interface AddCommonProps extends React.PropsWithChildren {
function AddCommon(props: AddCommonProps) {
return <>
<TorrentLocation {...props.location} inputLabel="Download directory" disabled={props.disabled} />
<TorrentLabels {...props.labelsData} inputLabel="Labels" disabled={props.disabled} />
<TorrentLabels labels={props.labels} setLabels={props.setLabels} inputLabel="Labels" disabled={props.disabled} />
<Group>
<Checkbox
label="Start torrent"
Expand All @@ -69,47 +70,34 @@ function AddCommon(props: AddCommonProps) {
</>;
}

interface AddCommonModalProps extends ActionModalState {
interface AddCommonModalProps extends ModalState {
serverName: string,
uri: string | File | undefined,
tabsRef: React.RefObject<ServerTabsRef>,
}

function useCommonProps(modalProps: AddCommonModalProps) {
function useCommonProps() {
const location = useTorrentLocation();
const [labels, setLabels] = useState<string[]>([]);
const [labelsData, setLabelData] = useState<LabelsData>({
labels,
setLabels,
allLabels: modalProps.serverData.current.allLabels,
});
const [start, setStart] = useState<boolean>(true);
const [priority, setPriority] = useState<PriorityNumberType>(0);

useEffect(() => {
setLabelData({
labels,
setLabels,
allLabels: modalProps.serverData.current.allLabels,
});
}, [labels, modalProps.opened, modalProps.serverData]);

const props = useMemo<AddCommonProps>(() => ({
location,
labelsData,
labels,
setLabels,
start,
setStart,
priority,
setPriority,
}), [location, labelsData, start, priority]);
}), [location, labels, start, priority]);

return {
return useMemo(() => ({
location,
labels,
start,
priority,
props,
};
}), [location, priority, props, start]);
}

function TabSwitchDropdown({ tabsRef }: { tabsRef: React.RefObject<ServerTabsRef> }) {
Expand Down Expand Up @@ -147,6 +135,7 @@ function TabSwitchDropdown({ tabsRef }: { tabsRef: React.RefObject<ServerTabsRef
}

export function AddMagnet(props: AddCommonModalProps) {
const serverData = useServerTorrentData();
const [magnet, setMagnet] = useState<string>("");

useEffect(() => {
Expand All @@ -166,14 +155,14 @@ export function AddMagnet(props: AddCommonModalProps) {

useEffect(() => {
if (magnetData !== undefined && magnetData.hash !== "") {
const torrent = props.serverData.current?.torrents.find((t) => t.hashString === magnetData.hash);
const torrent = serverData.torrents.find((t) => t.hashString === magnetData.hash);
setExistingTorrent(torrent);
} else {
setExistingTorrent(undefined);
}
}, [props.serverData, props.serverName, magnetData]);
}, [serverData, props.serverName, magnetData]);

const common = useCommonProps(props);
const common = useCommonProps();
const { close } = props;
const addMutation = useAddTorrent(
useCallback((response: any) => {
Expand Down Expand Up @@ -211,7 +200,7 @@ export function AddMagnet(props: AddCommonModalProps) {
{
url: magnet,
downloadDir: common.location.path,
labels: common.labels,
labels: common.props.labels,
paused: !common.start,
priority: common.priority,
},
Expand All @@ -231,7 +220,7 @@ export function AddMagnet(props: AddCommonModalProps) {
);
}
close();
}, [existingTorrent, close, addMutation, magnet, common.location, common.labels, common.start, common.priority, trackersMutation, magnetData]);
}, [existingTorrent, close, addMutation, magnet, common, trackersMutation, magnetData]);

return (
<HkModal opened={props.opened} onClose={close} centered size="lg"
Expand All @@ -248,7 +237,7 @@ export function AddMagnet(props: AddCommonModalProps) {
error={existingTorrent === undefined
? undefined
: "Torrent already exists"} />
<AddCommon {...common.props} disabled={existingTorrent !== undefined}/>
<AddCommon {...common.props} disabled={existingTorrent !== undefined} />
<Divider my="sm" />
<Group position="center" spacing="md">
<Button onClick={onAdd} variant="filled"
Expand Down Expand Up @@ -331,7 +320,8 @@ interface TorrentFileData {

export function AddTorrent(props: AddCommonModalProps) {
const config = useContext(ConfigContext);
const common = useCommonProps(props);
const serverData = useServerTorrentData();
const common = useCommonProps();
const [torrentData, setTorrentData] = useState<TorrentFileData[]>();

const filesInputRef = useRef<HTMLInputElement>(null);
Expand All @@ -344,10 +334,10 @@ export function AddTorrent(props: AddCommonModalProps) {

useEffect(() => {
if (torrentData !== undefined && torrentData.length === 1) {
const torrent = props.serverData.current?.torrents.find((t) => t.hashString === torrentData[0].hash);
const torrent = serverData.torrents.find((t) => t.hashString === torrentData[0].hash);
setExistingTorrent(torrent);
}
}, [props.serverData, props.serverName, torrentData]);
}, [serverData, props.serverName, torrentData]);

useEffect(() => {
if (!TAURI && props.opened) {
Expand Down Expand Up @@ -485,7 +475,7 @@ export function AddTorrent(props: AddCommonModalProps) {
{
metainfo: td.metadata,
downloadDir: common.location.path,
labels: common.labels,
labels: common.props.labels,
paused: !common.start,
priority: common.priority,
unwanted: (td.files == null || torrentData.length > 1) ? undefined : fileTree.getUnwanted(),
Expand Down
20 changes: 9 additions & 11 deletions src/components/modals/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { ConfigContext, ServerConfigContext } from "config";
import React, { useCallback, useContext, useEffect, useMemo, useState } from "react";
import { pathMapFromServer, pathMapToServer } from "trutil";
import * as Icon from "react-bootstrap-icons";
import type { ServerTorrentData } from "rpc/torrent";
import { useServerTorrentData } from "rpc/torrent";
import { useHotkeysContext } from "hotkeys";
const { TAURI, dialogOpen } = await import(/* webpackChunkName: "taurishim" */"taurishim");

Expand All @@ -46,10 +46,6 @@ export function HkModal(props: ModalProps) {
return <Modal {...props}>{props.children}</Modal>;
}

export interface ActionModalState extends ModalState {
serverData: React.MutableRefObject<ServerTorrentData>,
}

interface SaveCancelModalProps extends ModalProps {
onSave: () => void,
onClose: () => void,
Expand Down Expand Up @@ -80,14 +76,16 @@ export function limitTorrentNames(allNames: string[], limit: number = 5) {
return names;
}

export function TorrentsNames({ serverData }: { serverData: React.RefObject<ServerTorrentData> }) {
export function TorrentsNames() {
const serverData = useServerTorrentData();

const allNames = useMemo<string[]>(() => {
if (serverData.current == null || serverData.current.selected.size === 0) {
if (serverData.current == null || serverData.selected.size === 0) {
return ["No torrent selected"];
}

const selected = serverData.current.torrents.filter(
(t) => serverData.current?.selected.has(t.id));
const selected = serverData.torrents.filter(
(t) => serverData.selected.has(t.id));

const allNames: string[] = [];
selected.forEach((t) => allNames.push(t.name));
Expand Down Expand Up @@ -181,7 +179,6 @@ export function TorrentLocation(props: LocationData) {
}

export interface LabelsData {
allLabels: string[],
labels: string[],
setLabels: React.Dispatch<string[]>,
inputLabel?: string,
Expand Down Expand Up @@ -215,7 +212,8 @@ function Label({
}

export function TorrentLabels(props: LabelsData) {
const [data, setData] = useState<string[]>(props.allLabels);
const serverData = useServerTorrentData();
const [data, setData] = useState<string[]>(serverData.allLabels);

return (
<MultiSelect
Expand Down
Loading

0 comments on commit 54eb674

Please sign in to comment.