refactor(Selector, HomePage, MessageGroupSettings, NutstoreSettings, WebDavSettings): replace Select components with Selector for improved consistency

- Updated Selector component to handle value checks more robustly.
- Removed unused ContentContainer styles in HomePage for cleaner code.
- Replaced Select components with Selector in MessageGroupSettings, NutstoreSettings, and WebDavSettings for a unified UI experience.
- Enhanced option handling in Selector for better integration with existing settings.
This commit is contained in:
Teo 2025-06-13 14:03:30 +08:00
parent 5339f4a9a3
commit 2757fcf6b9
5 changed files with 66 additions and 48 deletions

View File

@ -35,7 +35,7 @@ const Selector = <V extends string | number>({
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const label = useMemo(() => { const label = useMemo(() => {
if (value) { if (value !== undefined && value !== null) {
const findLabel = (opts: SelectorOption<V>[]): string | ReactNode | undefined => { const findLabel = (opts: SelectorOption<V>[]): string | ReactNode | undefined => {
for (const opt of opts) { for (const opt of opts) {
if (opt.value === value) { if (opt.value === value) {

View File

@ -38,11 +38,6 @@ const Container = styled.div`
flex-direction: column; flex-direction: column;
` `
const ContentContainer = styled.div` const ContentContainer = styled.div``
overflow: hidden;
display: flex;
flex: 1;
flex-direction: row;
`
export default HomePage export default HomePage

View File

@ -1,10 +1,11 @@
import { SettingOutlined } from '@ant-design/icons' import { SettingOutlined } from '@ant-design/icons'
import Selector from '@renderer/components/Selector'
import { useSettings } from '@renderer/hooks/useSettings' import { useSettings } from '@renderer/hooks/useSettings'
import { SettingDivider } from '@renderer/pages/settings' import { SettingDivider } from '@renderer/pages/settings'
import { SettingRow } from '@renderer/pages/settings' import { SettingRow } from '@renderer/pages/settings'
import { useAppDispatch } from '@renderer/store' import { useAppDispatch } from '@renderer/store'
import { setGridColumns, setGridPopoverTrigger } from '@renderer/store/settings' import { setGridColumns, setGridPopoverTrigger } from '@renderer/store/settings'
import { Col, Row, Select, Slider } from 'antd' import { Col, Row, Slider } from 'antd'
import { Popover } from 'antd' import { Popover } from 'antd'
import { FC, useState } from 'react' import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@ -18,19 +19,22 @@ const MessageGroupSettings: FC = () => {
return ( return (
<Popover <Popover
arrow={false}
trigger={undefined} trigger={undefined}
showArrow showArrow
content={ content={
<div style={{ padding: 10 }}> <div style={{ padding: 10 }}>
<SettingRow> <SettingRow>
<div style={{ marginRight: 10 }}>{t('settings.messages.grid_popover_trigger')}</div> <div style={{ marginRight: 10 }}>{t('settings.messages.grid_popover_trigger')}</div>
<Select <Selector
size={14}
value={gridPopoverTrigger || 'hover'} value={gridPopoverTrigger || 'hover'}
onChange={(value) => dispatch(setGridPopoverTrigger(value as 'hover' | 'click'))} onChange={(value) => dispatch(setGridPopoverTrigger(value as 'hover' | 'click'))}
size="small"> options={[
<Select.Option value="hover">{t('settings.messages.grid_popover_trigger.hover')}</Select.Option> { label: t('settings.messages.grid_popover_trigger.hover'), value: 'hover' },
<Select.Option value="click">{t('settings.messages.grid_popover_trigger.click')}</Select.Option> { label: t('settings.messages.grid_popover_trigger.click'), value: 'click' }
</Select> ]}
/>
</SettingRow> </SettingRow>
<SettingDivider /> <SettingDivider />
<SettingRow> <SettingRow>

View File

@ -1,6 +1,7 @@
import { CheckOutlined, FolderOutlined, LoadingOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons' import { CheckOutlined, FolderOutlined, LoadingOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons'
import { HStack } from '@renderer/components/Layout' import { HStack } from '@renderer/components/Layout'
import NutstorePathPopup from '@renderer/components/Popups/NutsorePathPopup' import NutstorePathPopup from '@renderer/components/Popups/NutsorePathPopup'
import Selector from '@renderer/components/Selector'
import { WebdavBackupManager } from '@renderer/components/WebdavBackupManager' import { WebdavBackupManager } from '@renderer/components/WebdavBackupManager'
import { useWebdavBackupModal, WebdavBackupModal } from '@renderer/components/WebdavModals' import { useWebdavBackupModal, WebdavBackupModal } from '@renderer/components/WebdavModals'
import { useTheme } from '@renderer/context/ThemeProvider' import { useTheme } from '@renderer/context/ThemeProvider'
@ -23,7 +24,7 @@ import {
} from '@renderer/store/nutstore' } from '@renderer/store/nutstore'
import { modalConfirm } from '@renderer/utils' import { modalConfirm } from '@renderer/utils'
import { NUTSTORE_HOST } from '@shared/config/nutstore' import { NUTSTORE_HOST } from '@shared/config/nutstore'
import { Button, Input, Select, Switch, Tooltip, Typography } from 'antd' import { Button, Input, Switch, Tooltip, Typography } from 'antd'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { FC, useCallback, useEffect, useState } from 'react' import { FC, useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@ -279,18 +280,23 @@ const NutstoreSettings: FC = () => {
<SettingDivider /> <SettingDivider />
<SettingRow> <SettingRow>
<SettingRowTitle>{t('settings.data.webdav.autoSync')}</SettingRowTitle> <SettingRowTitle>{t('settings.data.webdav.autoSync')}</SettingRowTitle>
<Select value={syncInterval} onChange={onSyncIntervalChange} style={{ width: 120 }}> <Selector
<Select.Option value={0}>{t('settings.data.webdav.autoSync.off')}</Select.Option> size={14}
<Select.Option value={1}>{t('settings.data.webdav.minute_interval', { count: 1 })}</Select.Option> value={syncInterval}
<Select.Option value={5}>{t('settings.data.webdav.minute_interval', { count: 5 })}</Select.Option> onChange={onSyncIntervalChange}
<Select.Option value={15}>{t('settings.data.webdav.minute_interval', { count: 15 })}</Select.Option> options={[
<Select.Option value={30}>{t('settings.data.webdav.minute_interval', { count: 30 })}</Select.Option> { label: t('settings.data.webdav.autoSync.off'), value: 0 },
<Select.Option value={60}>{t('settings.data.webdav.hour_interval', { count: 1 })}</Select.Option> { label: t('settings.data.webdav.minute_interval', { count: 1 }), value: 1 },
<Select.Option value={120}>{t('settings.data.webdav.hour_interval', { count: 2 })}</Select.Option> { label: t('settings.data.webdav.minute_interval', { count: 5 }), value: 5 },
<Select.Option value={360}>{t('settings.data.webdav.hour_interval', { count: 6 })}</Select.Option> { label: t('settings.data.webdav.minute_interval', { count: 15 }), value: 15 },
<Select.Option value={720}>{t('settings.data.webdav.hour_interval', { count: 12 })}</Select.Option> { label: t('settings.data.webdav.minute_interval', { count: 30 }), value: 30 },
<Select.Option value={1440}>{t('settings.data.webdav.hour_interval', { count: 24 })}</Select.Option> { label: t('settings.data.webdav.hour_interval', { count: 1 }), value: 60 },
</Select> { label: t('settings.data.webdav.hour_interval', { count: 2 }), value: 120 },
{ label: t('settings.data.webdav.hour_interval', { count: 6 }), value: 360 },
{ label: t('settings.data.webdav.hour_interval', { count: 12 }), value: 720 },
{ label: t('settings.data.webdav.hour_interval', { count: 24 }), value: 1440 }
]}
/>
</SettingRow> </SettingRow>
{nutstoreAutoSync && syncInterval > 0 && ( {nutstoreAutoSync && syncInterval > 0 && (
<> <>

View File

@ -1,5 +1,6 @@
import { FolderOpenOutlined, SaveOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons' import { FolderOpenOutlined, SaveOutlined, SyncOutlined, WarningOutlined } from '@ant-design/icons'
import { HStack } from '@renderer/components/Layout' import { HStack } from '@renderer/components/Layout'
import Selector from '@renderer/components/Selector'
import { WebdavBackupManager } from '@renderer/components/WebdavBackupManager' import { WebdavBackupManager } from '@renderer/components/WebdavBackupManager'
import { useWebdavBackupModal, WebdavBackupModal } from '@renderer/components/WebdavModals' import { useWebdavBackupModal, WebdavBackupModal } from '@renderer/components/WebdavModals'
import { useTheme } from '@renderer/context/ThemeProvider' import { useTheme } from '@renderer/context/ThemeProvider'
@ -16,7 +17,7 @@ import {
setWebdavSyncInterval as _setWebdavSyncInterval, setWebdavSyncInterval as _setWebdavSyncInterval,
setWebdavUser as _setWebdavUser setWebdavUser as _setWebdavUser
} from '@renderer/store/settings' } from '@renderer/store/settings'
import { Button, Input, Select, Switch, Tooltip } from 'antd' import { Button, Input, Switch, Tooltip } from 'antd'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { FC, useState } from 'react' import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@ -173,31 +174,43 @@ const WebDavSettings: FC = () => {
<SettingDivider /> <SettingDivider />
<SettingRow> <SettingRow>
<SettingRowTitle>{t('settings.data.webdav.autoSync')}</SettingRowTitle> <SettingRowTitle>{t('settings.data.webdav.autoSync')}</SettingRowTitle>
<Select value={syncInterval} onChange={onSyncIntervalChange} disabled={!webdavHost} style={{ width: 120 }}> <Selector
<Select.Option value={0}>{t('settings.data.webdav.autoSync.off')}</Select.Option> size={14}
<Select.Option value={1}>{t('settings.data.webdav.minute_interval', { count: 1 })}</Select.Option> value={syncInterval}
<Select.Option value={5}>{t('settings.data.webdav.minute_interval', { count: 5 })}</Select.Option> onChange={onSyncIntervalChange}
<Select.Option value={15}>{t('settings.data.webdav.minute_interval', { count: 15 })}</Select.Option> disabled={!webdavHost}
<Select.Option value={30}>{t('settings.data.webdav.minute_interval', { count: 30 })}</Select.Option> options={[
<Select.Option value={60}>{t('settings.data.webdav.hour_interval', { count: 1 })}</Select.Option> { label: t('settings.data.webdav.autoSync.off'), value: 0 },
<Select.Option value={120}>{t('settings.data.webdav.hour_interval', { count: 2 })}</Select.Option> { label: t('settings.data.webdav.minute_interval', { count: 1 }), value: 1 },
<Select.Option value={360}>{t('settings.data.webdav.hour_interval', { count: 6 })}</Select.Option> { label: t('settings.data.webdav.minute_interval', { count: 5 }), value: 5 },
<Select.Option value={720}>{t('settings.data.webdav.hour_interval', { count: 12 })}</Select.Option> { label: t('settings.data.webdav.minute_interval', { count: 15 }), value: 15 },
<Select.Option value={1440}>{t('settings.data.webdav.hour_interval', { count: 24 })}</Select.Option> { label: t('settings.data.webdav.minute_interval', { count: 30 }), value: 30 },
</Select> { label: t('settings.data.webdav.hour_interval', { count: 1 }), value: 60 },
{ label: t('settings.data.webdav.hour_interval', { count: 2 }), value: 120 },
{ label: t('settings.data.webdav.hour_interval', { count: 6 }), value: 360 },
{ label: t('settings.data.webdav.hour_interval', { count: 12 }), value: 720 },
{ label: t('settings.data.webdav.hour_interval', { count: 24 }), value: 1440 }
]}
/>
</SettingRow> </SettingRow>
<SettingDivider /> <SettingDivider />
<SettingRow> <SettingRow>
<SettingRowTitle>{t('settings.data.webdav.maxBackups')}</SettingRowTitle> <SettingRowTitle>{t('settings.data.webdav.maxBackups')}</SettingRowTitle>
<Select value={maxBackups} onChange={onMaxBackupsChange} disabled={!webdavHost} style={{ width: 120 }}> <Selector
<Select.Option value={0}>{t('settings.data.webdav.maxBackups.unlimited')}</Select.Option> size={14}
<Select.Option value={1}>1</Select.Option> value={maxBackups}
<Select.Option value={3}>3</Select.Option> onChange={onMaxBackupsChange}
<Select.Option value={5}>5</Select.Option> disabled={!webdavHost}
<Select.Option value={10}>10</Select.Option> options={[
<Select.Option value={20}>20</Select.Option> { label: t('settings.data.webdav.maxBackups.unlimited'), value: 0 },
<Select.Option value={50}>50</Select.Option> { label: '1', value: 1 },
</Select> { label: '3', value: 3 },
{ label: '5', value: 5 },
{ label: '10', value: 10 },
{ label: '20', value: 20 },
{ label: '50', value: 50 }
]}
/>
</SettingRow> </SettingRow>
<SettingDivider /> <SettingDivider />
<SettingRow> <SettingRow>