diff --git a/src/features/migration/components/MIgrationEntryGroup.tsx b/src/features/migration/components/MIgrationEntryGroup.tsx index e17c151f..0bd4857e 100644 --- a/src/features/migration/components/MIgrationEntryGroup.tsx +++ b/src/features/migration/components/MIgrationEntryGroup.tsx @@ -11,58 +11,60 @@ import type { ButtonProps } from '@mui/material/Button'; import Button from '@mui/material/Button'; import Collapse from '@mui/material/Collapse'; import Stack from '@mui/material/Stack'; -import {} from 'react'; +import { memo } from 'react'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ExpandLessIcon from '@mui/icons-material/ExpandLess'; import { MigrationEntry } from '@/features/migration/components/migration-entry/MigrationEntry.tsx'; import { MigrationManager } from '@/features/migration/MigrationManager.ts'; -export const MigrationEntryGroup = ({ - status, - title, - entries, - color, - isMigrating = false, -}: { - status: MigrationEntryStatus; - title: string; - entries: TMigrationEntry[]; - color: ButtonProps['color']; - isMigrating?: boolean; -}) => { - const isExpanded = MigrationManager.useGroupExpandState(status); +export const MigrationEntryGroup = memo( + ({ + status, + title, + entries, + color, + isMigrating = false, + }: { + status: MigrationEntryStatus; + title: string; + entries: TMigrationEntry[]; + color: ButtonProps['color']; + isMigrating?: boolean; + }) => { + const isExpanded = MigrationManager.useGroupExpandState(status); - if (!entries.length) { - return null; - } + if (!entries.length) { + return null; + } - return ( - - - - - {entries.map((entry) => ( - - ))} - - - - ); -}; + return ( + + + + + {entries.map((entry) => ( + + ))} + + + + ); + }, +); diff --git a/src/features/migration/components/MigrationCard.tsx b/src/features/migration/components/MigrationCard.tsx index 64f7cfd6..5e80471b 100644 --- a/src/features/migration/components/MigrationCard.tsx +++ b/src/features/migration/components/MigrationCard.tsx @@ -21,8 +21,9 @@ import { Sources } from '@/features/source/services/Sources'; import type { TMigratableSource } from '@/features/migration/Migration.types.ts'; import { ReactRouter } from '@/lib/react-router/ReactRouter.ts'; import { AppRoutes } from '@/base/AppRoute.constants.ts'; +import { memo } from 'react'; -export const MigrationCard = (source: TMigratableSource) => { +export const MigrationCard = memo((source: TMigratableSource) => { const { id, name, lang, iconUrl, mangaCount } = source; const { t } = useLingui(); @@ -66,4 +67,4 @@ export const MigrationCard = (source: TMigratableSource) => { ); -}; +}); diff --git a/src/features/migration/components/MigrationSourceList.tsx b/src/features/migration/components/MigrationSourceList.tsx index 1e9347dc..cbc5e83f 100644 --- a/src/features/migration/components/MigrationSourceList.tsx +++ b/src/features/migration/components/MigrationSourceList.tsx @@ -6,7 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { useCallback, useMemo, useState } from 'react'; +import { memo, useCallback, useMemo, useState } from 'react'; import Box from '@mui/material/Box'; import Card from '@mui/material/Card'; import Chip from '@mui/material/Chip'; @@ -36,55 +36,57 @@ import { languageCodeToName } from '@/base/utils/Languages.ts'; import { DEFAULT_FULL_FAB_HEIGHT } from '@/base/components/buttons/StyledFab.tsx'; import Stack from '@mui/material/Stack'; -const SourceCard = ({ - source, - onToggle, - isCurrentSource, - isSelected, - isDragging, -}: { - source: SourceItem; - onToggle: (id: SourceIdInfo['id']) => void; - isCurrentSource: boolean; - isSelected: boolean; - isDragging?: boolean; -}) => { - const { t } = useLingui(); +const SourceCard = memo( + ({ + source, + onToggle, + isCurrentSource, + isSelected, + isDragging, + }: { + source: SourceItem; + onToggle: (id: SourceIdInfo['id']) => void; + isCurrentSource: boolean; + isSelected: boolean; + isDragging?: boolean; + }) => { + const { t } = useLingui(); - return ( - - - onToggle(source.id)}> - - - - - - {source.name} - - {languageCodeToName(source.lang)} - - - - {isCurrentSource && ( - - )} - {isSelected && ( - - + return ( + + + onToggle(source.id)}> + + + + + + {source.name} + + {languageCodeToName(source.lang)} - )} - - - - - - ); -}; + + + {isCurrentSource && ( + + )} + {isSelected && ( + + + + )} + + + + + + ); + }, +); export const MigrationSourceList = ({ sources, diff --git a/src/features/migration/components/migration-entry/MigrationEntry.tsx b/src/features/migration/components/migration-entry/MigrationEntry.tsx index d3cb52db..0ad96d45 100644 --- a/src/features/migration/components/migration-entry/MigrationEntry.tsx +++ b/src/features/migration/components/migration-entry/MigrationEntry.tsx @@ -9,7 +9,7 @@ import type { MigrationMatch, TMigrationEntry } from '@/features/migration/Migration.types.ts'; import { MigrationManager } from '@/features/migration/MigrationManager.ts'; import Paper from '@mui/material/Paper'; -import { useMemo } from 'react'; +import { memo, useMemo } from 'react'; import { MediaQuery } from '@/base/utils/MediaQuery.tsx'; import { applyStyles } from '@/base/utils/ApplyStyles.ts'; import { MigrationSourceEntry } from '@/features/migration/components/migration-entry/MigrationSourceEntry.tsx'; @@ -28,214 +28,227 @@ import Divider from '@mui/material/Divider'; import { MigrationEntryStatusIndicator } from '@/features/migration/components/migration-entry/MigrationEntryStatusIndicator.tsx'; import Box from '@mui/material/Box'; -const MigrationEntryMobile = ({ - entry, - entry: { mangaId, mangaTitle, status, error, isExcluded }, - destinationEntry, - otherSearchMatches, - isExpanded, - setIsExpanded, - isMigrating, -}: { - entry: TMigrationEntry; - destinationEntry: MigrationMatch | undefined; - otherSearchMatches: MigrationMatch[]; - isExpanded: boolean; - setIsExpanded: (expanded: boolean) => void; - isMigrating: boolean; -}) => { - const { t } = useLingui(); +const MigrationEntryMobile = memo( + ({ + entry, + entry: { mangaId, mangaTitle, status, error, isExcluded }, + destinationEntry, + otherSearchMatches, + isExpanded, + setIsExpanded, + isMigrating, + }: { + entry: TMigrationEntry; + destinationEntry: MigrationMatch | undefined; + otherSearchMatches: MigrationMatch[]; + isExpanded: boolean; + setIsExpanded: (expanded: boolean) => void; + isMigrating: boolean; + }) => { + const { t } = useLingui(); - return ( - <> - - - - - - - {t`Matches`} - - - - {otherSearchMatches.map((searchMatch) => { - if (destinationEntry?.id === searchMatch.id) { - return null; - } - - return ( - - ); - })} - - - - {!isMigrating && ( - + + - )} - - ); -}; -export const MigrationEntryDesktop = ({ - entry, - entry: { mangaId, mangaTitle, status, error }, - destinationEntry, - otherSearchMatches, - isExpanded, - setIsExpanded, - isMigrating, -}: { - entry: TMigrationEntry; - destinationEntry: MigrationMatch | undefined; - otherSearchMatches: MigrationMatch[]; - isExpanded: boolean; - setIsExpanded: (expanded: boolean) => void; - isMigrating: boolean; -}) => { - const { t } = useLingui(); + + + + {t`Matches`} + + + + {otherSearchMatches.map((searchMatch) => { + if (destinationEntry?.id === searchMatch.id) { + return null; + } - return ( - <> - + ); + })} + + + + {!isMigrating && ( + + )} + + ); + }, +); + +export const MigrationEntryDesktop = memo( + ({ + entry, + entry: { mangaId, mangaTitle, status, error }, + destinationEntry, + otherSearchMatches, + isExpanded, + setIsExpanded, + isMigrating, + }: { + entry: TMigrationEntry; + destinationEntry: MigrationMatch | undefined; + otherSearchMatches: MigrationMatch[]; + isExpanded: boolean; + setIsExpanded: (expanded: boolean) => void; + isMigrating: boolean; + }) => { + const { t } = useLingui(); + + return ( + <> + + + + + + + + + + {!isMigrating && ( + + )} + + + + + + {t`Matches`} + + {otherSearchMatches.map((searchMatch) => { + if (destinationEntry?.id === searchMatch.id) { + return null; + } + + return ( + + ); + })} + + + + ); + }, +); + +export const MigrationEntry = memo( + ({ entry: propEntry, isMigrating }: { entry: TMigrationEntry; isMigrating: boolean }) => { + const isTabletWidth = MediaQuery.useIsTabletWidth(); + + const entry = useMemo(() => MigrationManager.getUpToDateMigrationEntry(propEntry), [propEntry]); + + const destinationEntry = useMemo(() => { + const match = entry.searchMatches.find((matchEntry) => matchEntry.id === entry.selectedMatchMangaId); + const manualMatch = entry.manualMatches.find((matchEntry) => matchEntry.id === entry.selectedMatchMangaId); + + return match ?? manualMatch; + }, [entry.searchMatches, entry.selectedMatchMangaId]); + const otherMatches = useMemo( + () => + entry.searchMatches + .filter((searchMatch) => searchMatch.id !== entry.selectedMatchMangaId) + .sort((a, b) => (b.latestChapterNumber ?? 0) - (a.latestChapterNumber ?? 0)), + [entry.searchMatches, entry.selectedMatchMangaId], + ); + + const MigrationComponent = useMemo( + () => (isTabletWidth ? MigrationEntryMobile : MigrationEntryDesktop), + [isTabletWidth], + ); + + return ( + - - - - - - - - - {!isMigrating && ( - - )} - - - - - - {t`Matches`} - - {otherSearchMatches.map((searchMatch) => { - if (destinationEntry?.id === searchMatch.id) { - return null; - } - - return ( - - ); - })} - - - - ); -}; - -export const MigrationEntry = ({ entry: propEntry, isMigrating }: { entry: TMigrationEntry; isMigrating: boolean }) => { - const isTabletWidth = MediaQuery.useIsTabletWidth(); - - const entry = useMemo(() => MigrationManager.getUpToDateMigrationEntry(propEntry), [propEntry]); - - const destinationEntry = useMemo(() => { - const match = entry.searchMatches.find((matchEntry) => matchEntry.id === entry.selectedMatchMangaId); - const manualMatch = entry.manualMatches.find((matchEntry) => matchEntry.id === entry.selectedMatchMangaId); - - return match ?? manualMatch; - }, [entry.searchMatches, entry.selectedMatchMangaId]); - const otherMatches = useMemo( - () => - entry.searchMatches - .filter((searchMatch) => searchMatch.id !== entry.selectedMatchMangaId) - .sort((a, b) => (b.latestChapterNumber ?? 0) - (a.latestChapterNumber ?? 0)), - [entry.searchMatches, entry.selectedMatchMangaId], - ); - - const MigrationComponent = useMemo( - () => (isTabletWidth ? MigrationEntryMobile : MigrationEntryDesktop), - [isTabletWidth], - ); - - return ( - - - MigrationManager.setEntryMatchesExpandState(entry.mangaId, !entry.areMatchesExpanded) - } - otherSearchMatches={otherMatches} - isMigrating={isMigrating} - /> - - ); -}; + + MigrationManager.setEntryMatchesExpandState(entry.mangaId, !entry.areMatchesExpanded) + } + otherSearchMatches={otherMatches} + isMigrating={isMigrating} + /> + + ); + }, +); diff --git a/src/features/migration/components/migration-entry/MigrationMatchedEntry.tsx b/src/features/migration/components/migration-entry/MigrationMatchedEntry.tsx index 3501a889..ab59ab31 100644 --- a/src/features/migration/components/migration-entry/MigrationMatchedEntry.tsx +++ b/src/features/migration/components/migration-entry/MigrationMatchedEntry.tsx @@ -24,69 +24,67 @@ import Button from '@mui/material/Button'; import CardActionArea from '@mui/material/CardActionArea'; import Link from '@mui/material/Link'; import { Link as RouterLink } from 'react-router-dom'; +import { memo } from 'react'; -export const MigrationMatchedEntry = ({ - sourceMangaId, - entry, -}: { - sourceMangaId: MangaIdInfo['id']; - entry: MigrationMatch; -}) => { - const { t } = useLingui(); +export const MigrationMatchedEntry = memo( + ({ sourceMangaId, entry }: { sourceMangaId: MangaIdInfo['id']; entry: MigrationMatch }) => { + const { t } = useLingui(); - return ( - - MigrationManager.selectMatch(sourceMangaId, entry.id, entry.sourceId)}> - - {(() => ( - <> - e.stopPropagation()} - > - - - - - {entry.sourceTitle} - + return ( + + MigrationManager.selectMatch(sourceMangaId, entry.id, entry.sourceId)}> + + {(() => ( + <> e.stopPropagation()} > - - {entry.title} - + - - - - ))()} - {(() => ( - - ))()} - - - - ); -}; + + + {entry.sourceTitle} + + e.stopPropagation()} + > + + {entry.title} + + + + + + ))()} + {(() => ( + + ))()} + + + + ); + }, +); diff --git a/src/features/migration/components/migration-entry/MigrationSourceEntry.tsx b/src/features/migration/components/migration-entry/MigrationSourceEntry.tsx index 8c2ca2c2..f45a0f1d 100644 --- a/src/features/migration/components/migration-entry/MigrationSourceEntry.tsx +++ b/src/features/migration/components/migration-entry/MigrationSourceEntry.tsx @@ -20,8 +20,9 @@ import { useLingui } from '@lingui/react/macro'; import Stack from '@mui/material/Stack'; import Link from '@mui/material/Link'; import { Link as RouterLink } from 'react-router-dom'; +import { memo } from 'react'; -export const MigrationSourceEntry = (entry: TMigrationEntry) => { +export const MigrationSourceEntry = memo((entry: TMigrationEntry) => { const { mangaId, mangaThumbnailUrl, @@ -94,4 +95,4 @@ export const MigrationSourceEntry = (entry: TMigrationEntry) => { ); -}; +});