diff options
author | LASER-Yi <[email protected]> | 2021-08-17 02:28:18 +0800 |
---|---|---|
committer | LASER-Yi <[email protected]> | 2021-08-17 02:28:18 +0800 |
commit | c5fdea4a76593f66706eb145b06fb4f4d91fc607 (patch) | |
tree | cc99822f99f627cc2b10f837c8ffbd5a9cca4222 /frontend | |
parent | 82a687c8c8f68dea27181bc5edb1359c455d656d (diff) | |
download | bazarr-c5fdea4a76593f66706eb145b06fb4f4d91fc607.tar.gz bazarr-c5fdea4a76593f66706eb145b06fb4f4d91fc607.zip |
no log: Fix issues on new modal system
Diffstat (limited to 'frontend')
-rw-r--r-- | frontend/src/@redux/hooks/series.ts | 1 | ||||
-rw-r--r-- | frontend/src/Settings/Languages/modal.tsx | 8 | ||||
-rw-r--r-- | frontend/src/Settings/Notifications/components.tsx | 39 | ||||
-rw-r--r-- | frontend/src/Settings/Providers/components.tsx | 11 | ||||
-rw-r--r-- | frontend/src/System/Logs/modal.tsx | 4 | ||||
-rw-r--r-- | frontend/src/components/modals/BaseModal.tsx | 12 | ||||
-rw-r--r-- | frontend/src/components/modals/HistoryModal.tsx | 6 | ||||
-rw-r--r-- | frontend/src/components/modals/ItemEditorModal.tsx | 24 | ||||
-rw-r--r-- | frontend/src/components/modals/ManualSearchModal.tsx | 4 | ||||
-rw-r--r-- | frontend/src/components/modals/MovieUploadModal.tsx | 25 | ||||
-rw-r--r-- | frontend/src/components/modals/SeriesUploadModal.tsx | 17 | ||||
-rw-r--r-- | frontend/src/components/modals/SubtitleToolModal.tsx | 16 | ||||
-rw-r--r-- | frontend/src/components/modals/hooks.tsx | 76 |
13 files changed, 138 insertions, 105 deletions
diff --git a/frontend/src/@redux/hooks/series.ts b/frontend/src/@redux/hooks/series.ts index 77bfb74f5..0de8df2cc 100644 --- a/frontend/src/@redux/hooks/series.ts +++ b/frontend/src/@redux/hooks/series.ts @@ -37,7 +37,6 @@ export function useSerieBy(id: number) { const serie = useEntityItemById(series, String(id)); const update = useCallback(() => { - console.log("try loading", id); if (!isNaN(id)) { action([id]); } diff --git a/frontend/src/Settings/Languages/modal.tsx b/frontend/src/Settings/Languages/modal.tsx index 4fe24a813..d5aaf1f34 100644 --- a/frontend/src/Settings/Languages/modal.tsx +++ b/frontend/src/Settings/Languages/modal.tsx @@ -16,8 +16,7 @@ import { LanguageSelector, Selector, SimpleTable, - useCloseModal, - usePayload, + useModalInformation, } from "../../components"; import { BuildKey } from "../../utilites"; import { Input, Message } from "../components"; @@ -40,9 +39,8 @@ const LanguagesProfileModal: FunctionComponent<Props & BaseModalProps> = ( ) => { const { update, ...modal } = props; - const profile = usePayload<Language.Profile>(modal.modalKey); - - const closeModal = useCloseModal(); + const { payload: profile, closeModal } = + useModalInformation<Language.Profile>(modal.modalKey); const languages = useEnabledLanguagesContext(); diff --git a/frontend/src/Settings/Notifications/components.tsx b/frontend/src/Settings/Notifications/components.tsx index f16e0bf70..c8db22159 100644 --- a/frontend/src/Settings/Notifications/components.tsx +++ b/frontend/src/Settings/Notifications/components.tsx @@ -11,9 +11,8 @@ import { BaseModal, BaseModalProps, Selector, - useCloseModal, + useModalInformation, useOnModalShow, - usePayload, useShowModal, } from "../../components"; import { BuildKey } from "../../utilites"; @@ -44,26 +43,29 @@ const NotificationModal: FunctionComponent<ModalProps & BaseModalProps> = ({ "name" ); - const payload = usePayload<Settings.NotificationInfo>(modal.modalKey); + const { payload, closeModal } = + useModalInformation<Settings.NotificationInfo>(modal.modalKey); - const [current, setCurrent] = useState<Nullable<Settings.NotificationInfo>>( - payload ?? null - ); + const [current, setCurrent] = + useState<Nullable<Settings.NotificationInfo>>(payload); - useOnModalShow(() => setCurrent(payload ?? null), modal.modalKey); + useOnModalShow<Settings.NotificationInfo>( + (p) => setCurrent(p), + modal.modalKey + ); - const updateUrl = useCallback( - (s: string) => { + const updateUrl = useCallback((url: string) => { + setCurrent((current) => { if (current) { - const newCurrent = { ...current }; - newCurrent.url = s; - setCurrent(newCurrent); + return { + ...current, + url, + }; + } else { + return current; } - }, - [current] - ); - - const closeModal = useCloseModal(); + }); + }, []); const canSave = current !== null && current?.url !== null && current?.url.length !== 0; @@ -102,8 +104,7 @@ const NotificationModal: FunctionComponent<ModalProps & BaseModalProps> = ({ disabled={!canSave} onClick={() => { if (current) { - current.enabled = true; - update(current); + update({ ...current, enabled: true }); } closeModal(); }} diff --git a/frontend/src/Settings/Providers/components.tsx b/frontend/src/Settings/Providers/components.tsx index 3522ccab6..9d08aa6f3 100644 --- a/frontend/src/Settings/Providers/components.tsx +++ b/frontend/src/Settings/Providers/components.tsx @@ -11,9 +11,8 @@ import { SelectComponents } from "react-select/src/components"; import { BaseModal, Selector, - useCloseModal, + useModalInformation, useOnModalShow, - usePayload, useShowModal, } from "../../components"; import { BuildKey, isReactText } from "../../utilites"; @@ -78,18 +77,16 @@ export const ProviderView: FunctionComponent = () => { }; export const ProviderModal: FunctionComponent = () => { - const payload = usePayload<ProviderInfo>(ModalKey); + const { payload, closeModal } = useModalInformation<ProviderInfo>(ModalKey); const [staged, setChange] = useState<LooseObject>({}); - const [info, setInfo] = useState<Nullable<ProviderInfo>>(payload ?? null); + const [info, setInfo] = useState<Nullable<ProviderInfo>>(payload); - useOnModalShow(() => setInfo(payload ?? null), ModalKey); + useOnModalShow<ProviderInfo>((p) => setInfo(p), ModalKey); const providers = useLatest<string[]>(ProviderKey, isArray); - const closeModal = useCloseModal(); - const updateGlobal = useMultiUpdate(); const deletePayload = useCallback(() => { diff --git a/frontend/src/System/Logs/modal.tsx b/frontend/src/System/Logs/modal.tsx index 86c479778..cce24cb46 100644 --- a/frontend/src/System/Logs/modal.tsx +++ b/frontend/src/System/Logs/modal.tsx @@ -1,10 +1,10 @@ import React, { FunctionComponent, useMemo } from "react"; -import { BaseModal, BaseModalProps, usePayload } from "../../components"; +import { BaseModal, BaseModalProps, useModalPayload } from "../../components"; interface Props extends BaseModalProps {} const SystemLogModal: FunctionComponent<Props> = ({ ...modal }) => { - const stack = usePayload<string>(modal.modalKey); + const stack = useModalPayload<string>(modal.modalKey); const result = useMemo( () => stack?.split("\\n").map((v, idx) => ( diff --git a/frontend/src/components/modals/BaseModal.tsx b/frontend/src/components/modals/BaseModal.tsx index 8a717699b..c80681ba2 100644 --- a/frontend/src/components/modals/BaseModal.tsx +++ b/frontend/src/components/modals/BaseModal.tsx @@ -1,7 +1,6 @@ import React, { FunctionComponent, useCallback, useState } from "react"; import { Modal } from "react-bootstrap"; -import { useIsModalShow } from "."; -import { useCloseModal } from "./hooks"; +import { useModalInformation } from "./hooks"; export interface BaseModalProps { modalKey: string; @@ -15,8 +14,7 @@ export const BaseModal: FunctionComponent<BaseModalProps> = (props) => { const { size, modalKey, title, children, footer } = props; const [needExit, setExit] = useState(false); - const show = useIsModalShow(modalKey); - const close = useCloseModal(); + const { isShow, closeModal } = useModalInformation(modalKey); const closeable = props.closeable !== false; @@ -25,15 +23,15 @@ export const BaseModal: FunctionComponent<BaseModalProps> = (props) => { }, []); const exit = useCallback(() => { - close(); + closeModal(modalKey); setExit(false); - }, [close]); + }, [closeModal, modalKey]); return ( <Modal centered size={size} - show={show && !needExit} + show={isShow && !needExit} onHide={hide} onExited={exit} backdrop={closeable ? undefined : "static"} diff --git a/frontend/src/components/modals/HistoryModal.tsx b/frontend/src/components/modals/HistoryModal.tsx index 6172d7db7..79f14b9ff 100644 --- a/frontend/src/components/modals/HistoryModal.tsx +++ b/frontend/src/components/modals/HistoryModal.tsx @@ -6,12 +6,12 @@ import { EpisodesApi, MoviesApi, useAsyncRequest } from "../../apis"; import { BlacklistButton } from "../../generic/blacklist"; import { AsyncOverlay } from "../async"; import BaseModal, { BaseModalProps } from "./BaseModal"; -import { usePayload } from "./hooks"; +import { useModalPayload } from "./hooks"; export const MovieHistoryModal: FunctionComponent<BaseModalProps> = (props) => { const { ...modal } = props; - const movie = usePayload<Item.Movie>(modal.modalKey); + const movie = useModalPayload<Item.Movie>(modal.modalKey); const [history, updateHistory] = useAsyncRequest( MoviesApi.history.bind(MoviesApi), @@ -111,7 +111,7 @@ interface EpisodeHistoryProps {} export const EpisodeHistoryModal: FunctionComponent< BaseModalProps & EpisodeHistoryProps > = (props) => { - const episode = usePayload<Item.Episode>(props.modalKey); + const episode = useModalPayload<Item.Episode>(props.modalKey); const [history, updateHistory] = useAsyncRequest( EpisodesApi.history.bind(EpisodesApi), diff --git a/frontend/src/components/modals/ItemEditorModal.tsx b/frontend/src/components/modals/ItemEditorModal.tsx index 04f5021dd..c32c5e247 100644 --- a/frontend/src/components/modals/ItemEditorModal.tsx +++ b/frontend/src/components/modals/ItemEditorModal.tsx @@ -4,7 +4,7 @@ import { AsyncButton, Selector } from "../"; import { useLanguageProfiles } from "../../@redux/hooks"; import { GetItemId } from "../../utilites"; import BaseModal, { BaseModalProps } from "./BaseModal"; -import { useCloseModal, usePayload } from "./hooks"; +import { useModalInformation } from "./hooks"; interface Props { submit: (form: FormType.ModifyItem) => Promise<void>; @@ -16,9 +16,9 @@ const Editor: FunctionComponent<Props & BaseModalProps> = (props) => { const profiles = useLanguageProfiles(); - const item = usePayload<Item.Base>(modal.modalKey); - - const closeModal = useCloseModal(); + const { payload, closeModal } = useModalInformation<Item.Base>( + modal.modalKey + ); const profileOptions = useMemo<SelectorOption<number>[]>( () => @@ -37,8 +37,8 @@ const Editor: FunctionComponent<Props & BaseModalProps> = (props) => { noReset onChange={setUpdating} promise={() => { - if (item) { - const itemId = GetItemId(item); + if (payload) { + const itemId = GetItemId(payload); return submit({ id: [itemId], profileid: [id], @@ -49,20 +49,20 @@ const Editor: FunctionComponent<Props & BaseModalProps> = (props) => { }} onSuccess={() => { closeModal(); - onSuccess && item && onSuccess(item); + onSuccess && payload && onSuccess(payload); }} > Save </AsyncButton> ), - [closeModal, id, item, onSuccess, submit] + [closeModal, id, payload, onSuccess, submit] ); return ( <BaseModal closeable={!updating} footer={footer} - title={item?.title} + title={payload?.title} {...modal} > <Container fluid> @@ -72,7 +72,9 @@ const Editor: FunctionComponent<Props & BaseModalProps> = (props) => { <Form.Control type="text" disabled - defaultValue={item?.audio_language.map((v) => v.name).join(", ")} + defaultValue={payload?.audio_language + .map((v) => v.name) + .join(", ")} ></Form.Control> </Form.Group> <Form.Group> @@ -80,7 +82,7 @@ const Editor: FunctionComponent<Props & BaseModalProps> = (props) => { <Selector clearable options={profileOptions} - defaultValue={item?.profileId} + defaultValue={payload?.profileId} onChange={(v) => setId(v === undefined ? null : v)} ></Selector> </Form.Group> diff --git a/frontend/src/components/modals/ManualSearchModal.tsx b/frontend/src/components/modals/ManualSearchModal.tsx index 31e116fd9..3c173a476 100644 --- a/frontend/src/components/modals/ManualSearchModal.tsx +++ b/frontend/src/components/modals/ManualSearchModal.tsx @@ -31,7 +31,7 @@ import { LanguageText, LoadingIndicator, PageTable, - usePayload, + useModalPayload, } from ".."; import { ProvidersApi } from "../../apis"; import { isMovie } from "../../utilites"; @@ -58,7 +58,7 @@ export const ManualSearchModal: FunctionComponent<Props & BaseModalProps> = ( const [result, setResult] = useState<SearchResultType[]>([]); const [searchState, setSearchState] = useState(SearchState.Ready); - const item = usePayload<SupportType>(modal.modalKey); + const item = useModalPayload<SupportType>(modal.modalKey); const search = useCallback(async () => { if (item) { diff --git a/frontend/src/components/modals/MovieUploadModal.tsx b/frontend/src/components/modals/MovieUploadModal.tsx index c247db567..1369c13c4 100644 --- a/frontend/src/components/modals/MovieUploadModal.tsx +++ b/frontend/src/components/modals/MovieUploadModal.tsx @@ -1,12 +1,6 @@ import React, { FunctionComponent, useEffect, useMemo, useState } from "react"; import { Container, Form } from "react-bootstrap"; -import { - AsyncButton, - FileForm, - LanguageSelector, - useCloseModal, - usePayload, -} from ".."; +import { AsyncButton, FileForm, LanguageSelector } from ".."; import { useEnabledLanguages, useLanguageBy, @@ -14,6 +8,7 @@ import { } from "../../@redux/hooks"; import { MoviesApi } from "../../apis"; import BaseModal, { BaseModalProps } from "./BaseModal"; +import { useModalInformation } from "./hooks"; interface MovieProps {} const MovieUploadModal: FunctionComponent<MovieProps & BaseModalProps> = ( @@ -23,15 +18,15 @@ const MovieUploadModal: FunctionComponent<MovieProps & BaseModalProps> = ( const availableLanguages = useEnabledLanguages(); - const movie = usePayload<Item.Movie>(modal.modalKey); - - const closeModal = useCloseModal(); + const { payload, closeModal } = useModalInformation<Item.Movie>( + modal.modalKey + ); const [uploading, setUpload] = useState(false); const [language, setLanguage] = useState<Nullable<Language.Info>>(null); - const profile = useProfileBy(movie?.profileId); + const profile = useProfileBy(payload?.profileId); const defaultLanguage = useLanguageBy(profile?.items[0]?.language); @@ -50,8 +45,8 @@ const MovieUploadModal: FunctionComponent<MovieProps & BaseModalProps> = ( disabled={!canUpload} onChange={setUpload} promise={() => { - if (file && movie && language) { - return MoviesApi.uploadSubtitles(movie.radarrId, { + if (file && payload && language) { + return MoviesApi.uploadSubtitles(payload.radarrId, { file: file, forced, hi: false, @@ -61,7 +56,7 @@ const MovieUploadModal: FunctionComponent<MovieProps & BaseModalProps> = ( return null; } }} - onSuccess={closeModal} + onSuccess={() => closeModal()} > Upload </AsyncButton> @@ -69,7 +64,7 @@ const MovieUploadModal: FunctionComponent<MovieProps & BaseModalProps> = ( return ( <BaseModal - title={`Upload - ${movie?.title}`} + title={`Upload - ${payload?.title}`} closeable={!uploading} footer={footer} {...modal} diff --git a/frontend/src/components/modals/SeriesUploadModal.tsx b/frontend/src/components/modals/SeriesUploadModal.tsx index 0d04a8d6b..097d7300c 100644 --- a/frontend/src/components/modals/SeriesUploadModal.tsx +++ b/frontend/src/components/modals/SeriesUploadModal.tsx @@ -21,13 +21,12 @@ import { LanguageSelector, MessageIcon, SimpleTable, - useCloseModal, - usePayload, } from ".."; import { useProfileBy, useProfileItemsToLanguages } from "../../@redux/hooks"; import { EpisodesApi, SubtitlesApi } from "../../apis"; import { Selector } from "../inputs"; import BaseModal, { BaseModalProps } from "./BaseModal"; +import { useModalInformation } from "./hooks"; enum State { Update, @@ -63,17 +62,17 @@ const SeriesUploadModal: FunctionComponent<SerieProps & BaseModalProps> = ({ episodes, ...modal }) => { - const series = usePayload<Item.Series>(modal.modalKey); + const { payload, closeModal } = useModalInformation<Item.Series>( + modal.modalKey + ); const [uploading, setUpload] = useState(false); - const closeModal = useCloseModal(); - const [pending, setPending] = useState<PendingSubtitle[]>([]); const [processState, setProcessState] = useState<ProcessState>({}); - const profile = useProfileBy(series?.profileId); + const profile = useProfileBy(payload?.profileId); const avaliableLanguages = useProfileItemsToLanguages(profile); @@ -173,11 +172,11 @@ const SeriesUploadModal: FunctionComponent<SerieProps & BaseModalProps> = ({ ); const uploadSubtitles = useCallback(async () => { - if (series === null || language === null) { + if (payload === null || language === null) { return; } - const { sonarrSeriesId: seriesid } = series; + const { sonarrSeriesId: seriesid } = payload; let uploadStates = pending.reduce<ProcessState>((prev, curr) => { prev[curr.file.name] = { state: State.Update, infos: [] }; @@ -223,7 +222,7 @@ const SeriesUploadModal: FunctionComponent<SerieProps & BaseModalProps> = ({ if (exception) { throw new Error("Error when uploading subtitles"); } - }, [series, pending, language]); + }, [payload, pending, language]); const canUpload = useMemo( () => diff --git a/frontend/src/components/modals/SubtitleToolModal.tsx b/frontend/src/components/modals/SubtitleToolModal.tsx index 4b8dd9538..aebd67e19 100644 --- a/frontend/src/components/modals/SubtitleToolModal.tsx +++ b/frontend/src/components/modals/SubtitleToolModal.tsx @@ -39,7 +39,8 @@ import { LanguageText, Selector, SimpleTable, - usePayload, + useCloseModalIfCovered, + useModalPayload, useShowModal, } from ".."; import { useEnabledLanguages } from "../../@redux/hooks"; @@ -48,7 +49,6 @@ import { isMovie, submodProcessColor } from "../../utilites"; import { log } from "../../utilites/logger"; import { useCustomSelection } from "../tables/plugins"; import BaseModal, { BaseModalProps } from "./BaseModal"; -import { useCloseModalUntil } from "./hooks"; import { availableTranslation, colorOptions } from "./toolOptions"; type SupportType = Item.Episode | Item.Movie; @@ -331,18 +331,18 @@ const TranslateModal: FunctionComponent<BaseModalProps & ToolModalProps> = ({ interface STMProps {} const STM: FunctionComponent<BaseModalProps & STMProps> = ({ ...props }) => { - const items = usePayload<SupportType[]>(props.modalKey); + const payload = useModalPayload<SupportType[]>(props.modalKey); const [updating, setUpdate] = useState<boolean>(false); const [processState, setProcessState] = useState<ProcessState>({}); const [selections, setSelections] = useState<TableColumnType[]>([]); - const closeUntil = useCloseModalUntil(); + const closeModal = useCloseModalIfCovered(); const process = useCallback( async (action: string, override?: Partial<FormType.ModifySubtitle>) => { log("info", "executing action", action); - closeUntil(props.modalKey); + closeModal(props.modalKey); setUpdate(true); let states = selections.reduce<ProcessState>( @@ -374,7 +374,7 @@ const STM: FunctionComponent<BaseModalProps & STMProps> = ({ ...props }) => { } setUpdate(false); }, - [closeUntil, selections, props.modalKey] + [closeModal, selections, props.modalKey] ); const showModal = useShowModal(); @@ -431,7 +431,7 @@ const STM: FunctionComponent<BaseModalProps & STMProps> = ({ ...props }) => { const data = useMemo<TableColumnType[]>( () => - items?.flatMap((item) => { + payload?.flatMap((item) => { const [id, type] = getIdAndType(item); return item.subtitles.flatMap((v) => { if (v.path !== null) { @@ -449,7 +449,7 @@ const STM: FunctionComponent<BaseModalProps & STMProps> = ({ ...props }) => { } }); }) ?? [], - [items] + [payload] ); const plugins = [useRowSelect, useCustomSelection]; diff --git a/frontend/src/components/modals/hooks.tsx b/frontend/src/components/modals/hooks.tsx index 6208599bc..ce2c3010b 100644 --- a/frontend/src/components/modals/hooks.tsx +++ b/frontend/src/components/modals/hooks.tsx @@ -3,6 +3,27 @@ import { useDidUpdate } from "rooks"; import { log } from "../../utilites/logger"; import { ModalContext } from "./provider"; +interface ModalInformation<T> { + isShow: boolean; + payload: T | null; + closeModal: ReturnType<typeof useCloseModal>; +} + +export function useModalInformation<T>(key: string): ModalInformation<T> { + const isShow = useIsModalShow(key); + const payload = useModalPayload<T>(key); + const closeModal = useCloseModal(); + + return useMemo( + () => ({ + isShow, + payload, + closeModal, + }), + [isShow, payload, closeModal] + ); +} + export function useShowModal() { const { control: { push }, @@ -20,30 +41,46 @@ export function useShowModal() { export function useCloseModal() { const { - control: { pop }, + control: { pop, peek }, } = useContext(ModalContext); - return pop; + return useCallback( + (key?: string) => { + const modal = peek(); + if (key) { + if (modal?.key === key) { + pop(); + } + } else { + pop(); + } + }, + [pop, peek] + ); } -export function useCloseModalUntil() { +export function useCloseModalIfCovered() { const { control: { pop, peek }, } = useContext(ModalContext); return useCallback( (key: string) => { let modal = peek(); - while (modal) { - if (modal.key === key) { - break; - } else { - modal = pop(); - } + if (modal && modal.key !== key) { + pop(); } }, [pop, peek] ); } +export function useModalIsCovered(key: string) { + const { modals } = useContext(ModalContext); + return useMemo(() => { + const idx = modals.findIndex((v) => v.key === key); + return idx !== -1 && idx !== 0; + }, [modals, key]); +} + export function useIsModalShow(key: string) { const { control: { peek }, @@ -52,23 +89,30 @@ export function useIsModalShow(key: string) { return key === modal?.key; } -export function useOnModalShow(callback: () => void, key: string) { - const isShow = useIsModalShow(key); +export function useOnModalShow<T>( + callback: (payload: T | null) => void, + key: string +) { + const { + modals, + control: { peek }, + } = useContext(ModalContext); useDidUpdate(() => { - if (isShow) { - callback(); + const modal = peek(); + if (modal && modal.key === key) { + callback(modal.payload ?? null); } - }, [isShow]); + }, [modals.length, key]); } -export function usePayload<T>(key: string): T | null { +export function useModalPayload<T>(key: string): T | null { const { control: { peek }, } = useContext(ModalContext); return useMemo(() => { const modal = peek(); if (modal && modal.key === key) { - return modal.payload as T; + return (modal.payload as T) ?? null; } else { return null; } |