Fix/tracking updating score (#682)
* Use SelectSetting for updating track score * Create custom Select component
This commit is contained in:
19
src/components/atoms/Select.tsx
Normal file
19
src/components/atoms/Select.tsx
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Contributors to the Suwayomi project
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Select as MuiSelect, SelectVariants } from '@mui/material';
|
||||||
|
|
||||||
|
export const Select = <Value, Variant extends SelectVariants>({
|
||||||
|
children,
|
||||||
|
maxSelectionHeightPx = 250,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof MuiSelect<Value, Variant>> & { maxSelectionHeightPx?: number }) => (
|
||||||
|
<MuiSelect<any, any> MenuProps={{ PaperProps: { style: { maxHeight: maxSelectionHeightPx } } }} {...props}>
|
||||||
|
{children}
|
||||||
|
</MuiSelect>
|
||||||
|
);
|
||||||
@@ -18,7 +18,7 @@ import { useLocation, useNavigate } from 'react-router-dom';
|
|||||||
import Slide from '@mui/material/Slide';
|
import Slide from '@mui/material/Slide';
|
||||||
import Fade from '@mui/material/Fade';
|
import Fade from '@mui/material/Fade';
|
||||||
import Zoom from '@mui/material/Zoom';
|
import Zoom from '@mui/material/Zoom';
|
||||||
import { Divider, FormControl, MenuItem, Select, styled, Tooltip } from '@mui/material';
|
import { Divider, FormControl, MenuItem, styled, Tooltip } from '@mui/material';
|
||||||
import ListItem from '@mui/material/ListItem';
|
import ListItem from '@mui/material/ListItem';
|
||||||
import ListItemText from '@mui/material/ListItemText';
|
import ListItemText from '@mui/material/ListItemText';
|
||||||
import Collapse from '@mui/material/Collapse';
|
import Collapse from '@mui/material/Collapse';
|
||||||
@@ -27,6 +27,7 @@ import { AllowedMetadataValueTypes, ChapterOffset, IReaderSettings, TChapter, TM
|
|||||||
import { ReaderSettingsOptions } from '@/components/reader/ReaderSettingsOptions';
|
import { ReaderSettingsOptions } from '@/components/reader/ReaderSettingsOptions';
|
||||||
import { useBackButton } from '@/util/useBackButton.ts';
|
import { useBackButton } from '@/util/useBackButton.ts';
|
||||||
import { useSetDefaultBackTo } from '@/components/context/NavbarContext.tsx';
|
import { useSetDefaultBackTo } from '@/components/context/NavbarContext.tsx';
|
||||||
|
import { Select } from '@/components/atoms/Select.tsx';
|
||||||
|
|
||||||
const Root = styled('div')({
|
const Root = styled('div')({
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
@@ -101,8 +102,6 @@ const ChapterNavigation = styled('div')({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const MenuProps = { PaperProps: { style: { maxHeight: 150 } } };
|
|
||||||
|
|
||||||
const OpenDrawerButton = styled(IconButton)(({ theme }) => ({
|
const OpenDrawerButton = styled(IconButton)(({ theme }) => ({
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: 0 + 20,
|
top: 0 + 20,
|
||||||
@@ -280,7 +279,6 @@ export function ReaderNavBar(props: IProps) {
|
|||||||
disabled={disableChapterNavButtons || chapter.pageCount === -1}
|
disabled={disableChapterNavButtons || chapter.pageCount === -1}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
MenuProps={MenuProps}
|
|
||||||
value={chapter.pageCount > -1 ? `${curPage}` : ''}
|
value={chapter.pageCount > -1 ? `${curPage}` : ''}
|
||||||
displayEmpty
|
displayEmpty
|
||||||
onChange={({ target: { value: selectedPage } }) => {
|
onChange={({ target: { value: selectedPage } }) => {
|
||||||
@@ -315,7 +313,6 @@ export function ReaderNavBar(props: IProps) {
|
|||||||
disabled={disableChapterNavButtons || chapter.sourceOrder < 1}
|
disabled={disableChapterNavButtons || chapter.sourceOrder < 1}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
MenuProps={MenuProps}
|
|
||||||
value={chapter.sourceOrder >= 1 ? `${chapter.sourceOrder}` : ''}
|
value={chapter.sourceOrder >= 1 ? `${chapter.sourceOrder}` : ''}
|
||||||
displayEmpty
|
displayEmpty
|
||||||
onChange={({ target: { value: selectedChapter } }) => {
|
onChange={({ target: { value: selectedChapter } }) => {
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { List, ListItem, ListItemText, Switch } from '@mui/material';
|
import { List, ListItem, ListItemText, Switch } from '@mui/material';
|
||||||
import Select from '@mui/material/Select';
|
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AllowedMetadataValueTypes, IReaderSettings } from '@/typings';
|
import { AllowedMetadataValueTypes, IReaderSettings } from '@/typings';
|
||||||
import { NumberSetting } from '@/components/settings/NumberSetting.tsx';
|
import { NumberSetting } from '@/components/settings/NumberSetting.tsx';
|
||||||
import { isHorizontalReaderType } from '@/components/reader/Page.tsx';
|
import { isHorizontalReaderType } from '@/components/reader/Page.tsx';
|
||||||
|
import { Select } from '@/components/atoms/Select.tsx';
|
||||||
|
|
||||||
interface IProps extends IReaderSettings {
|
interface IProps extends IReaderSettings {
|
||||||
setSettingValue: (key: keyof IReaderSettings, value: AllowedMetadataValueTypes, persist?: boolean) => void;
|
setSettingValue: (key: keyof IReaderSettings, value: AllowedMetadataValueTypes, persist?: boolean) => void;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { List, ListItem, ListItemText, MenuItem, Select } from '@mui/material';
|
import { List, ListItem, ListItemText, MenuItem } from '@mui/material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useContext, useEffect } from 'react';
|
import { useContext, useEffect } from 'react';
|
||||||
import { updateMetadataServerSettings, useMetadataServerSettings } from '@/lib/metadata/metadataServerSettings.ts';
|
import { updateMetadataServerSettings, useMetadataServerSettings } from '@/lib/metadata/metadataServerSettings.ts';
|
||||||
@@ -15,6 +15,7 @@ import { makeToast } from '@/components/util/Toast.tsx';
|
|||||||
import { MutableListSetting } from '@/components/settings/MutableListSetting.tsx';
|
import { MutableListSetting } from '@/components/settings/MutableListSetting.tsx';
|
||||||
import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext.tsx';
|
import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext.tsx';
|
||||||
import { ActiveDevice, DEFAULT_DEVICE } from '@/util/device.ts';
|
import { ActiveDevice, DEFAULT_DEVICE } from '@/util/device.ts';
|
||||||
|
import { Select } from '@/components/atoms/Select.tsx';
|
||||||
|
|
||||||
export const DeviceSetting = () => {
|
export const DeviceSetting = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -75,11 +76,7 @@ export const DeviceSetting = () => {
|
|||||||
primary={t('settings.device.active_device.label.title')}
|
primary={t('settings.device.active_device.label.title')}
|
||||||
secondary={t('settings.device.active_device.label.description')}
|
secondary={t('settings.device.active_device.label.description')}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select value={activeDevice} onChange={({ target: { value: device } }) => setActiveDevice(device)}>
|
||||||
MenuProps={{ PaperProps: { style: { maxHeight: 150 } } }}
|
|
||||||
value={activeDevice}
|
|
||||||
onChange={({ target: { value: device } }) => setActiveDevice(device)}
|
|
||||||
>
|
|
||||||
{devices.map((device) => (
|
{devices.map((device) => (
|
||||||
<MenuItem key={device} value={device}>
|
<MenuItem key={device} value={device}>
|
||||||
{device}
|
{device}
|
||||||
|
|||||||
@@ -6,17 +6,7 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { Button, Dialog, DialogTitle, FormControl, ListItemText, MenuItem, Stack, Typography } from '@mui/material';
|
||||||
Button,
|
|
||||||
Dialog,
|
|
||||||
DialogTitle,
|
|
||||||
FormControl,
|
|
||||||
ListItemText,
|
|
||||||
MenuItem,
|
|
||||||
Select,
|
|
||||||
Stack,
|
|
||||||
Typography,
|
|
||||||
} from '@mui/material';
|
|
||||||
import DialogContent from '@mui/material/DialogContent';
|
import DialogContent from '@mui/material/DialogContent';
|
||||||
import DialogActions from '@mui/material/DialogActions';
|
import DialogActions from '@mui/material/DialogActions';
|
||||||
import ListItemButton from '@mui/material/ListItemButton';
|
import ListItemButton from '@mui/material/ListItemButton';
|
||||||
@@ -25,6 +15,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import DialogContentText from '@mui/material/DialogContentText';
|
import DialogContentText from '@mui/material/DialogContentText';
|
||||||
import InfoIcon from '@mui/icons-material/Info';
|
import InfoIcon from '@mui/icons-material/Info';
|
||||||
import { TranslationKey } from '@/typings.ts';
|
import { TranslationKey } from '@/typings.ts';
|
||||||
|
import { Select } from '@/components/atoms/Select.tsx';
|
||||||
|
|
||||||
export type SelectSettingValueDisplayInfo = {
|
export type SelectSettingValueDisplayInfo = {
|
||||||
text: TranslationKey | string;
|
text: TranslationKey | string;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||||
import PopupState, { bindDialog, bindMenu, bindTrigger } from 'material-ui-popup-state';
|
import PopupState, { bindDialog, bindMenu, bindTrigger } from 'material-ui-popup-state';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { Trackers, TTrackRecord, UNSET_DATE } from '@/lib/data/Trackers.ts';
|
import { Trackers, TTrackRecord, UNSET_DATE } from '@/lib/data/Trackers.ts';
|
||||||
import { ListPreference } from '@/components/sourceConfiguration/ListPreference.tsx';
|
import { ListPreference } from '@/components/sourceConfiguration/ListPreference.tsx';
|
||||||
@@ -37,6 +38,7 @@ import { makeToast } from '@/components/util/Toast.tsx';
|
|||||||
import { Menu } from '@/components/menu/Menu';
|
import { Menu } from '@/components/menu/Menu';
|
||||||
import { CARD_STYLING } from '@/components/tracker/constants.ts';
|
import { CARD_STYLING } from '@/components/tracker/constants.ts';
|
||||||
import { TypographyMaxLines } from '@/components/atoms/TypographyMaxLines.tsx';
|
import { TypographyMaxLines } from '@/components/atoms/TypographyMaxLines.tsx';
|
||||||
|
import { SelectSetting, SelectSettingValue } from '@/components/settings/SelectSetting.tsx';
|
||||||
|
|
||||||
const TrackerActiveLink = ({ children, url }: { children: React.ReactNode; url: string }) => (
|
const TrackerActiveLink = ({ children, url }: { children: React.ReactNode; url: string }) => (
|
||||||
<Link href={url} rel="noreferrer" target="_blank" underline="none" color="inherit">
|
<Link href={url} rel="noreferrer" target="_blank" underline="none" color="inherit">
|
||||||
@@ -198,6 +200,8 @@ const TrackerActiveCardInfoRow = ({ children }: { children: React.ReactNode }) =
|
|||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isUnsetScore = (score: string | number): boolean => !Math.trunc(Number(score));
|
||||||
|
|
||||||
export const TrackerActiveCard = ({
|
export const TrackerActiveCard = ({
|
||||||
trackRecord: { tracker, ...trackRecord },
|
trackRecord: { tracker, ...trackRecord },
|
||||||
onClick,
|
onClick,
|
||||||
@@ -207,6 +211,20 @@ export const TrackerActiveCard = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const isScoreUnset = isUnsetScore(trackRecord.displayScore);
|
||||||
|
const currentScore = isScoreUnset ? tracker.scores[0] : trackRecord.displayScore;
|
||||||
|
|
||||||
|
const selectSettingValues = useMemo(
|
||||||
|
() =>
|
||||||
|
tracker.scores.map(
|
||||||
|
(score) =>
|
||||||
|
[score, { text: isUnsetScore(score) ? '-' : score }] satisfies SelectSettingValue<
|
||||||
|
TTrackRecord['tracker']['scores'][number]
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
[tracker.scores],
|
||||||
|
);
|
||||||
|
|
||||||
const updateTrackerBind = (patch: Parameters<typeof requestManager.updateTrackerBind>[1]) => {
|
const updateTrackerBind = (patch: Parameters<typeof requestManager.updateTrackerBind>[1]) => {
|
||||||
requestManager
|
requestManager
|
||||||
.updateTrackerBind(trackRecord.id, patch)
|
.updateTrackerBind(trackRecord.id, patch)
|
||||||
@@ -245,25 +263,12 @@ export const TrackerActiveCard = ({
|
|||||||
handleUpdate={(lastChapterRead) => updateTrackerBind({ lastChapterRead })}
|
handleUpdate={(lastChapterRead) => updateTrackerBind({ lastChapterRead })}
|
||||||
/>
|
/>
|
||||||
<Divider orientation="vertical" flexItem />
|
<Divider orientation="vertical" flexItem />
|
||||||
<NumberSetting
|
<SelectSetting<string>
|
||||||
settingTitle={t('tracking.track_record.label.score')}
|
settingName={t('tracking.track_record.label.score')}
|
||||||
dialogTitle={t('manga.label.status')}
|
defaultValue={tracker.scores[0]}
|
||||||
settingValue={trackRecord.displayScore}
|
value={currentScore}
|
||||||
value={trackRecord.score ?? 0}
|
values={selectSettingValues}
|
||||||
minValue={0}
|
handleChange={(score) => updateTrackerBind({ scoreString: score })}
|
||||||
maxValue={Number(tracker.scores.slice(-1)[0])}
|
|
||||||
stepSize={Number(
|
|
||||||
(Number(tracker.scores[2] ?? 0) - Number(tracker.scores[1] ?? 0)).toFixed(1),
|
|
||||||
)}
|
|
||||||
valueUnit=""
|
|
||||||
handleUpdate={(newScore) =>
|
|
||||||
updateTrackerBind({
|
|
||||||
scoreString:
|
|
||||||
newScore === 0
|
|
||||||
? tracker.scores[0]
|
|
||||||
: tracker.scores.find((score) => Number(score) === newScore),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</TrackerActiveCardInfoRow>
|
</TrackerActiveCardInfoRow>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import ListItem from '@mui/material/ListItem';
|
|||||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||||
import ListItemText from '@mui/material/ListItemText';
|
import ListItemText from '@mui/material/ListItemText';
|
||||||
import Switch from '@mui/material/Switch';
|
import Switch from '@mui/material/Switch';
|
||||||
import { Link, ListItemButton, MenuItem, Select } from '@mui/material';
|
import { Link, ListItemButton, MenuItem } from '@mui/material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import LanguageIcon from '@mui/icons-material/Language';
|
import LanguageIcon from '@mui/icons-material/Language';
|
||||||
import CollectionsOutlinedBookmarkIcon from '@mui/icons-material/CollectionsBookmarkOutlined';
|
import CollectionsOutlinedBookmarkIcon from '@mui/icons-material/CollectionsBookmarkOutlined';
|
||||||
@@ -37,6 +37,7 @@ import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
|||||||
import { NumberSetting } from '@/components/settings/NumberSetting.tsx';
|
import { NumberSetting } from '@/components/settings/NumberSetting.tsx';
|
||||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { makeToast } from '@/components/util/Toast.tsx';
|
import { makeToast } from '@/components/util/Toast.tsx';
|
||||||
|
import { Select } from '@/components/atoms/Select.tsx';
|
||||||
|
|
||||||
export function Settings() {
|
export function Settings() {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
@@ -143,7 +144,6 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
MenuProps={{ PaperProps: { style: { maxHeight: 150 } } }}
|
|
||||||
value={i18n.language}
|
value={i18n.language}
|
||||||
onChange={({ target: { value: language } }) => i18n.changeLanguage(language)}
|
onChange={({ target: { value: language } }) => i18n.changeLanguage(language)}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user