Add rooks package and rewrite some components to increase performance

This commit is contained in:
LASER-Yi 2021-05-09 01:13:10 +08:00
parent e796422021
commit 66d4648c66
15 changed files with 138 additions and 165 deletions

View file

@ -1,62 +1,63 @@
{
"name": "bazarr",
"version": "1.0.0",
"version": "1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "bazarr",
"version": "1.0.0",
"license": "GPL-3.0",
"version": "1",
"license": "GPL-3",
"dependencies": {
"@fontsource/roboto": "^4.2.2",
"@fortawesome/fontawesome-svg-core": "^1.2.0",
"@fortawesome/free-brands-svg-icons": "^5.15.0",
"@fortawesome/free-regular-svg-icons": "^5.15.0",
"@fortawesome/free-solid-svg-icons": "^5.15.0",
"@fortawesome/fontawesome-svg-core": "^1.2",
"@fortawesome/free-brands-svg-icons": "^5.15",
"@fortawesome/free-regular-svg-icons": "^5.15",
"@fortawesome/free-solid-svg-icons": "^5.15",
"@fortawesome/react-fontawesome": "^0.1.11",
"@types/bootstrap": "^5.0.0",
"@types/lodash": "^4.0.0",
"@types/node": "^14.0.0",
"@types/rc-slider": "^8.6.6",
"@types/react": "^16.0.0",
"@types/react-dom": "^16.0.0",
"@types/react-helmet": "^6.1.0",
"@types/react-redux": "^7.0.0",
"@types/react-router-dom": "^5.0.0",
"@types/bootstrap": "^5",
"@types/lodash": "^4",
"@types/node": "^14",
"@types/rc-slider": "^8.6",
"@types/react": "^16",
"@types/react-dom": "^16",
"@types/react-helmet": "^6.1",
"@types/react-redux": "^7",
"@types/react-router-dom": "^5",
"@types/react-select": "^4.0.3",
"@types/react-table": "^7.0.0",
"@types/redux-actions": "^2.0.0",
"@types/redux-logger": "^3.0.0",
"@types/redux-promise": "^0.5.0",
"axios": "^0.21.0",
"bootstrap": "^4.0.0",
"http-proxy-middleware": "^0.19.1",
"lodash": "^4.0.0",
"rc-slider": "^9.7.1",
"react": "^16.0.0",
"react-bootstrap": "^1.0.0",
"react-dom": "^16.0.0",
"react-helmet": "^6.1.0",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.0",
"react-select": "^4.0.0",
"react-table": "^7.0.0",
"@types/react-table": "^7",
"@types/redux-actions": "^2",
"@types/redux-logger": "^3",
"@types/redux-promise": "^0.5",
"axios": "^0.21",
"bootstrap": "^4",
"http-proxy-middleware": "^0.19",
"lodash": "^4",
"rc-slider": "^9.7",
"react": "^16",
"react-bootstrap": "^1",
"react-dom": "^16",
"react-helmet": "^6.1",
"react-redux": "^7.2",
"react-router-dom": "^5.2",
"react-scripts": "^4",
"react-select": "^4",
"react-table": "^7",
"recharts": "^2.0.8",
"redux-actions": "^2.0.0",
"redux-logger": "^3.0.6",
"redux-promise": "^0.6.0",
"redux-thunk": "^2.3.0",
"sass": "^1.0.0",
"socket.io-client": "^4.0.0",
"typescript": "^4.0.0"
"redux-actions": "^2",
"redux-logger": "^3",
"redux-promise": "^0.6",
"redux-thunk": "^2.3",
"rooks": "^5",
"sass": "^1",
"socket.io-client": "^4",
"typescript": "^4"
},
"devDependencies": {
"husky": "^4.0.0",
"prettier": "^2.1.2",
"prettier-plugin-organize-imports": "^1.1.1",
"pretty-quick": "^3.1.0"
"husky": "^4",
"prettier": "^2",
"prettier-plugin-organize-imports": "^1",
"pretty-quick": "^3.1"
}
},
"node_modules/@babel/code-frame": {
@ -17296,6 +17297,15 @@
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="
},
"node_modules/rooks": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/rooks/-/rooks-5.0.2.tgz",
"integrity": "sha512-GPydrZ6Sd0g1INCK6RrzM+xnu5I2Fiir/3WRGDw1XeaU026xibPiTl/lOct5Q9ErRerSi0ETHwzdpcHuCw7NlA==",
"dependencies": {
"lodash.debounce": "^4.0.8",
"raf": "^3.4.1"
}
},
"node_modules/rsvp": {
"version": "4.8.5",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
@ -35748,6 +35758,15 @@
}
}
},
"rooks": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/rooks/-/rooks-5.0.2.tgz",
"integrity": "sha512-GPydrZ6Sd0g1INCK6RrzM+xnu5I2Fiir/3WRGDw1XeaU026xibPiTl/lOct5Q9ErRerSi0ETHwzdpcHuCw7NlA==",
"requires": {
"lodash.debounce": "^4.0.8",
"raf": "^3.4.1"
}
},
"rsvp": {
"version": "4.8.5",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",

View file

@ -1,66 +1,67 @@
{
"name": "bazarr",
"version": "1.0.0",
"version": "1",
"description": "Bazarr is a companion application to Sonarr and Radarr. It manages and downloads subtitles based on your requirements. You define your preferences by TV show or movie and Bazarr takes care of everything for you.",
"repository": {
"type": "git",
"url": "git+https://github.com/morpheus65535/bazarr.git"
},
"author": "morpheus65535",
"license": "GPL-3.0",
"license": "GPL-3",
"bugs": {
"url": "https://github.com/morpheus65535/bazarr/issues"
},
"homepage": "./",
"dependencies": {
"@fontsource/roboto": "^4.2.2",
"@fortawesome/fontawesome-svg-core": "^1.2.0",
"@fortawesome/free-brands-svg-icons": "^5.15.0",
"@fortawesome/free-regular-svg-icons": "^5.15.0",
"@fortawesome/free-solid-svg-icons": "^5.15.0",
"@fortawesome/fontawesome-svg-core": "^1.2",
"@fortawesome/free-brands-svg-icons": "^5.15",
"@fortawesome/free-regular-svg-icons": "^5.15",
"@fortawesome/free-solid-svg-icons": "^5.15",
"@fortawesome/react-fontawesome": "^0.1.11",
"@types/bootstrap": "^5.0.0",
"@types/lodash": "^4.0.0",
"@types/node": "^14.0.0",
"@types/rc-slider": "^8.6.6",
"@types/react": "^16.0.0",
"@types/react-dom": "^16.0.0",
"@types/react-helmet": "^6.1.0",
"@types/react-redux": "^7.0.0",
"@types/react-router-dom": "^5.0.0",
"@types/bootstrap": "^5",
"@types/lodash": "^4",
"@types/node": "^14",
"@types/rc-slider": "^8.6",
"@types/react": "^16",
"@types/react-dom": "^16",
"@types/react-helmet": "^6.1",
"@types/react-redux": "^7",
"@types/react-router-dom": "^5",
"@types/react-select": "^4.0.3",
"@types/react-table": "^7.0.0",
"@types/redux-actions": "^2.0.0",
"@types/redux-logger": "^3.0.0",
"@types/redux-promise": "^0.5.0",
"axios": "^0.21.0",
"bootstrap": "^4.0.0",
"http-proxy-middleware": "^0.19.1",
"lodash": "^4.0.0",
"rc-slider": "^9.7.1",
"react": "^16.0.0",
"react-bootstrap": "^1.0.0",
"react-dom": "^16.0.0",
"react-helmet": "^6.1.0",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.0",
"react-select": "^4.0.0",
"react-table": "^7.0.0",
"@types/react-table": "^7",
"@types/redux-actions": "^2",
"@types/redux-logger": "^3",
"@types/redux-promise": "^0.5",
"axios": "^0.21",
"bootstrap": "^4",
"http-proxy-middleware": "^0.19",
"lodash": "^4",
"rc-slider": "^9.7",
"react": "^16",
"react-bootstrap": "^1",
"react-dom": "^16",
"react-helmet": "^6.1",
"react-redux": "^7.2",
"react-router-dom": "^5.2",
"react-scripts": "^4",
"react-select": "^4",
"react-table": "^7",
"recharts": "^2.0.8",
"redux-actions": "^2.0.0",
"redux-logger": "^3.0.6",
"redux-promise": "^0.6.0",
"redux-thunk": "^2.3.0",
"sass": "^1.0.0",
"socket.io-client": "^4.0.0",
"typescript": "^4.0.0"
"redux-actions": "^2",
"redux-logger": "^3",
"redux-promise": "^0.6",
"redux-thunk": "^2.3",
"rooks": "^5",
"sass": "^1",
"socket.io-client": "^4",
"typescript": "^4"
},
"devDependencies": {
"husky": "^4.0.0",
"prettier": "^2.1.2",
"prettier-plugin-organize-imports": "^1.1.1",
"pretty-quick": "^3.1.0"
"husky": "^4",
"prettier": "^2",
"prettier-plugin-organize-imports": "^1",
"pretty-quick": "^3.1"
},
"scripts": {
"start": "react-scripts start",

View file

@ -9,7 +9,6 @@ import {
SITE_NOTIFICATIONS_REMOVE,
SITE_NOTIFICATIONS_REMOVE_BY_TIMESTAMP,
SITE_OFFLINE_UPDATE,
SITE_SAVE_LOCALSTORAGE,
SITE_SIDEBAR_UPDATE,
} from "../constants";
import { createAsyncAction, createCallbackAction } from "./factory";
@ -31,11 +30,6 @@ export const badgeUpdateAll = createAsyncAction(SITE_BADGE_UPDATE, () =>
BadgesApi.all()
);
export const siteSaveLocalstorage = createAction(
SITE_SAVE_LOCALSTORAGE,
(settings: LooseObject) => settings
);
export const siteAddNotification = createAction(
SITE_NOTIFICATIONS_ADD,
(err: ReduxStore.Notification) => err

View file

@ -34,7 +34,6 @@ export const MOVIES_UPDATE_BLACKLIST = "UPDATE_MOVIES_BLACKLIST";
export const SITE_NEED_AUTH = "SITE_NEED_AUTH";
export const SITE_INITIALIZED = "SITE_SYSTEM_INITIALIZED";
export const SITE_INITIALIZE_FAILED = "SITE_INITIALIZE_FAILED";
export const SITE_SAVE_LOCALSTORAGE = "SITE_SAVE_LOCALSTORAGE";
export const SITE_NOTIFICATIONS_ADD = "SITE_NOTIFICATIONS_ADD";
export const SITE_NOTIFICATIONS_REMOVE = "SITE_NOTIFICATIONS_REMOVE";
export const SITE_NOTIFICATIONS_REMOVE_BY_TIMESTAMP =

View file

@ -1,5 +1,4 @@
import { Action, handleActions } from "redux-actions";
import { storage } from "../../@storage/local";
import apis from "../../apis";
import {
SITE_BADGE_UPDATE,
@ -10,17 +9,10 @@ import {
SITE_NOTIFICATIONS_REMOVE,
SITE_NOTIFICATIONS_REMOVE_BY_TIMESTAMP,
SITE_OFFLINE_UPDATE,
SITE_SAVE_LOCALSTORAGE,
SITE_SIDEBAR_UPDATE,
} from "../constants";
import { AsyncAction } from "../types";
function updateLocalStorage(): Partial<ReduxStore.Site> {
return {
pageSize: storage.pageSize,
};
}
const reducer = handleActions<ReduxStore.Site, any>(
{
[SITE_NEED_AUTH]: (state) => {
@ -40,17 +32,6 @@ const reducer = handleActions<ReduxStore.Site, any>(
...state,
initialized: "An Error Occurred When Initializing Bazarr UI",
}),
[SITE_SAVE_LOCALSTORAGE]: (state, action: Action<LooseObject>) => {
const settings = action.payload;
for (const key in settings) {
const value = settings[key];
localStorage.setItem(key, value);
}
return {
...state,
...updateLocalStorage(),
};
},
[SITE_NOTIFICATIONS_ADD]: (
state,
action: Action<ReduxStore.Notification>
@ -94,7 +75,6 @@ const reducer = handleActions<ReduxStore.Site, any>(
{
initialized: false,
auth: true,
pageSize: 50,
notifications: [],
sidebar: "",
badges: {
@ -104,7 +84,6 @@ const reducer = handleActions<ReduxStore.Site, any>(
status: 0,
},
offline: false,
...updateLocalStorage(),
}
);

View file

@ -17,7 +17,6 @@ namespace ReduxStore {
// Initialization state or error message
initialized: boolean | string;
auth: boolean;
pageSize: number;
notifications: Notification[];
sidebar: string;
badges: Badge;

View file

@ -1,10 +1,17 @@
import { useCallback } from "react";
import { useLocalstorage } from "rooks";
export const uiPageSizeKey = "storage-ui-pageSize";
export const storage: LocalStorageType = {
get pageSize(): number {
return parseInt(localStorage.getItem(uiPageSizeKey) ?? "50");
},
set pageSize(v: number) {
localStorage.setItem(uiPageSizeKey, v.toString());
},
};
export function useUpdateLocalStorage() {
return useCallback((newVals: LooseObject) => {
for (const key in newVals) {
const value = newVals[key];
localStorage.setItem(key, value);
}
}, []);
}
export function usePageSize() {
return useLocalstorage(uiPageSizeKey, 50);
}

View file

@ -42,7 +42,7 @@ const App: FunctionComponent<Props> = () => {
}, [initialized, hasUpdate, notify]);
const [sidebar, setSidebar] = useState(false);
const toggleSidebar = useCallback(() => setSidebar(!sidebar), [sidebar]);
const toggleSidebar = useCallback(() => setSidebar((s) => !s), []);
if (!auth) {
return <Redirect to="/login"></Redirect>;

View file

@ -1,9 +1,10 @@
import React, { FunctionComponent } from "react";
import { uiPageSizeKey } from "../../@storage/local";
import { uiPageSizeKey, usePageSize } from "../../@storage/local";
import { Group, Input, Selector, SettingsProvider } from "../components";
import { pageSizeOptions } from "./options";
const SettingsUIView: FunctionComponent = () => {
const [pageSize] = usePageSize();
return (
<SettingsProvider title="Interface - Bazarr (Settings)">
<Group header="UI">
@ -11,7 +12,7 @@ const SettingsUIView: FunctionComponent = () => {
<Selector
options={pageSizeOptions}
settingKey={uiPageSizeKey}
override={(_, s) => s.site.pageSize}
override={(_) => pageSize}
></Selector>
</Input>
</Group>

View file

@ -1,6 +1,5 @@
import { isArray, uniqBy } from "lodash";
import { useCallback, useContext, useMemo } from "react";
import { useStore } from "react-redux";
import { useSystemSettings } from "../../@redux/hooks";
import { log } from "../../utilites/logger";
import { StagedChangesContext } from "./provider";
@ -45,7 +44,7 @@ export function useMultiUpdate() {
type ValidateFuncType<T> = (v: any) => v is T;
export type OverrideFuncType<T> = (settings: Settings, store: ReduxStore) => T;
export type OverrideFuncType<T> = (settings: Settings) => T;
export function useExtract<T>(
key: string,
@ -55,8 +54,6 @@ export function useExtract<T>(
const [systemSettings] = useSystemSettings();
const settings = systemSettings.data;
const store = useStore<ReduxStore>();
const extractValue = useMemo(() => {
let value: Nullable<T> = null;
@ -89,7 +86,7 @@ export function useExtract<T>(
if (override && settings !== undefined) {
// TODO: Temporarily override
return override(settings, store.getState());
return override(settings);
} else {
return extractValue;
}

View file

@ -10,9 +10,8 @@ import React, {
import { Container, Row } from "react-bootstrap";
import { Helmet } from "react-helmet";
import { Prompt } from "react-router";
import { siteSaveLocalstorage } from "../../@redux/actions";
import { useSystemSettings } from "../../@redux/hooks";
import { useReduxAction } from "../../@redux/hooks/base";
import { useUpdateLocalStorage } from "../../@storage/local";
import { SystemApi } from "../../apis";
import { ContentHeader } from "../../components";
import { useWhenLoadingFinish } from "../../utilites";
@ -54,7 +53,7 @@ interface Props {
const SettingsProvider: FunctionComponent<Props> = (props) => {
const { children, title } = props;
const updateStorage = useReduxAction(siteSaveLocalstorage);
const updateStorage = useUpdateLocalStorage();
const [stagedChange, setChange] = useState<LooseObject>({});
const [updating, setUpdating] = useState(false);

View file

@ -1,4 +1,3 @@
import { throttle } from "lodash";
import React, {
FunctionComponent,
useCallback,
@ -8,6 +7,7 @@ import React, {
} from "react";
import { Dropdown, Form } from "react-bootstrap";
import { useHistory } from "react-router";
import { useThrottle } from "rooks";
export interface SearchResult {
name: string;
@ -44,7 +44,7 @@ export const SearchBar: FunctionComponent<Props> = ({
[onSearch]
);
const debounceSearch = useMemo(() => throttle(search, 500), [search]);
const [debounceSearch] = useThrottle(search, 500);
useEffect(() => {
debounceSearch(text);

View file

@ -2,7 +2,7 @@ import { isNull } from "lodash";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { PluginHook, TableOptions, useTable } from "react-table";
import { LoadingIndicator } from "..";
import { useReduxStore } from "../../@redux/hooks/base";
import { usePageSize } from "../../@storage/local";
import { buildOrderListFrom, isNonNullable, ScrollToTop } from "../../utilites";
import BaseTable, { TableStyleProps, useStyleAndOptions } from "./BaseTable";
import PageControl from "./PageControl";
@ -32,7 +32,7 @@ export default function AsyncPageTable<T extends object>(props: Props<T>) {
// Impl a new pagination system instead of hooking into the existing one
const [pageIndex, setIndex] = useState(0);
const pageSize = useReduxStore((s) => s.site.pageSize);
const [pageSize] = usePageSize();
const totalRows = order.length;
const pageCount = Math.ceil(totalRows / pageSize);

View file

@ -1,4 +1,3 @@
import { isUndefined } from "lodash";
import React, { useEffect } from "react";
import {
PluginHook,
@ -7,7 +6,6 @@ import {
useRowSelect,
useTable,
} from "react-table";
import { useReduxStore } from "../../@redux/hooks/base";
import { ScrollToTop } from "../../utilites";
import BaseTable, { TableStyleProps, useStyleAndOptions } from "./BaseTable";
import PageControl from "./PageControl";
@ -51,12 +49,9 @@ export default function PageTable<T extends object>(props: Props<T>) {
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = instance;
const globalPageSize = useReduxStore((s) => s.site.pageSize);
// Scroll to top when page is changed
useEffect(() => {
if (autoScroll) {
@ -64,23 +59,6 @@ export default function PageTable<T extends object>(props: Props<T>) {
}
}, [pageIndex, autoScroll]);
useEffect(() => {
const selecting = options.isSelecting;
if (canSelect && !isUndefined(selecting)) {
if (selecting) {
setPageSize(rows.length);
} else {
setPageSize(globalPageSize);
}
}
}, [
canSelect,
globalPageSize,
options.isSelecting,
rows.length,
setPageSize,
]);
return (
<React.Fragment>
<BaseTable

View file

@ -1,5 +1,5 @@
import { Hooks, TableOptions } from "react-table";
import { useReduxStore } from "../../../@redux/hooks/base";
import { usePageSize } from "../../../@storage/local";
const pluginName = "useLocalSettings";
@ -9,7 +9,7 @@ function useDefaultSettings<T extends object>(hooks: Hooks<T>) {
useDefaultSettings.pluginName = pluginName;
function useOptions<T extends object>(options: TableOptions<T>) {
const { pageSize } = useReduxStore((s) => s.site);
const [pageSize] = usePageSize();
if (options.autoResetPage === undefined) {
options.autoResetPage = false;