Merge pull request #771 from ajnart/mantine-v6

🎉 Move to Mantine v6
This commit is contained in:
Thomas Camlong
2023-03-28 16:05:09 +09:00
committed by GitHub
33 changed files with 275 additions and 173 deletions

View File

@@ -57,7 +57,12 @@ export default function ConfigChanger() {
size="lg"
radius="md"
>
<Notification loading title={t('configSelect.loadingNew')} radius="md" disallowClose>
<Notification
loading
title={t('configSelect.loadingNew')}
radius="md"
withCloseButton={false}
>
{t('configSelect.pleaseWait')}
</Notification>
</Dialog>

View File

@@ -29,7 +29,7 @@ export const GenericAvailableElementType = ({
: image;
return (
<Grid.Col span={3}>
<Grid.Col span="auto">
<Card style={{ height: '100%' }}>
<Stack justify="space-between" style={{ height: '100%' }}>
<Stack spacing="xs">

View File

@@ -19,7 +19,7 @@ export const AvailableStaticTypes = ({ onClickBack }: AvailableStaticTypesProps)
they don&apos;t integrate with any apps and their content never changes.
</Text>
<Grid>
<Grid grow>
<GenericAvailableElementType
name="Static Text"
description="Display a fixed string on your dashboard"

View File

@@ -93,12 +93,10 @@ export const AppTile = ({ className, app }: AppTileProps) => {
const useStyles = createStyles((theme, _params, getRef) => ({
image: {
ref: getRef('image'),
maxHeight: '90%',
maxWidth: '90%',
},
appName: {
ref: getRef('appName'),
wordBreak: 'break-word',
},
button: {

View File

@@ -18,12 +18,11 @@ interface GridstackStoreType {
export const useNamedWrapperColumnCount = (): 'small' | 'medium' | 'large' | null => {
const mainAreaWidth = useGridstackStore((x) => x.mainAreaWidth);
const { sm, xl } = useMantineTheme().breakpoints;
if (!mainAreaWidth) return null;
if (mainAreaWidth >= xl) return 'large';
if (mainAreaWidth >= 1400) return 'large';
if (mainAreaWidth >= sm) return 'medium';
if (mainAreaWidth >= 800) return 'medium';
return 'small';
};

View File

@@ -18,7 +18,7 @@ export default function CommonSettings() {
);
}
return (
<ScrollArea style={{ height: height - 100 }} offsetScrollbars>
<ScrollArea style={{ height: height - 100 }} scrollbarSize={5}>
<Stack>
<SearchEngineSelector searchEngine={config.settings.common.searchEngine} />
<Space />

View File

@@ -60,6 +60,7 @@ export const SearchEngineSelector = ({ searchEngine }: Props) => {
<Space mb="md" />
<TextInput
label={t('customEngine.label')}
name={t('configurationName')}
description={t('tips.placeholderTip')}
placeholder={t('customEngine.placeholder')}
value={searchUrl}

View File

@@ -8,7 +8,7 @@ export default function CustomizationSettings() {
const { t } = useTranslation('settings/customization/general');
return (
<ScrollArea style={{ height: height - 100 }} offsetScrollbars>
<ScrollArea style={{ height: height - 100 }} scrollbarSize={5}>
<Stack mt="xs" mb="md" spacing="xs">
<Text color="dimmed">{t('text')}</Text>
<CustomizationSettingsAccordeon />

View File

@@ -41,7 +41,7 @@ export function SettingsDrawer({
return (
<Drawer
size="xl"
size="lg"
padding="lg"
position="right"
title={<Title order={5}>{t('title')}</Title>}

View File

@@ -181,7 +181,6 @@ export function Search() {
shadow="md"
radius="md"
zIndex={100}
transition="pop-top-right"
>
<Popover.Target>
<Autocomplete
@@ -297,7 +296,7 @@ export function Search() {
setSearchEngine(item);
showNotification({
radius: 'lg',
disallowClose: true,
withCloseButton: false,
id: 'spotlight',
autoClose: 1000,
icon: <ActionIcon size="sm">{item.icon}</ActionIcon>,

View File

@@ -16,8 +16,8 @@ const ConfigContext = createContext<ConfigContextType>({
name: 'unknown',
config: undefined,
configVersion: undefined,
increaseVersion: () => console.error('Provider not set'),
setConfigName: () => console.error('Provider not set'),
increaseVersion: () => {},
setConfigName: () => {},
});
export const ConfigProvider = ({ children }: { children: ReactNode }) => {

View File

@@ -0,0 +1 @@
export const MIN_WIDTH_MOBILE = 500;

View File

@@ -1,8 +1,9 @@
import { MantineSize, useMantineTheme } from '@mantine/core';
import { useMediaQuery } from '@mantine/hooks';
import { MIN_WIDTH_MOBILE } from '../constants/constants';
export const useScreenLargerThan = (size: MantineSize | number) => {
const { breakpoints } = useMantineTheme();
const pixelCount = typeof size === 'string' ? breakpoints[size] : size;
return useMediaQuery(`(min-width: ${pixelCount}px)`);
return useMediaQuery(`(min-width: ${MIN_WIDTH_MOBILE})`);
};

View File

@@ -35,7 +35,7 @@ function sendDockerCommand(
title: `${t(`actions.${action}.start`)} ${containerName}`,
message: undefined,
autoClose: false,
disallowClose: true,
withCloseButton: false,
});
axios
.get(`/api/docker/container/${containerId}?action=${action}`)

View File

@@ -1,4 +1,4 @@
import { Badge, BadgeVariant, MantineSize } from '@mantine/core';
import { Badge, BadgeProps, MantineSize } from '@mantine/core';
import { useTranslation } from 'next-i18next';
import Dockerode from 'dockerode';
@@ -14,7 +14,7 @@ export default function ContainerState(props: ContainerStateProps) {
const options: {
size: MantineSize;
radius: MantineSize;
variant: BadgeVariant;
variant: BadgeProps['variant'];
} = {
size: 'md',
radius: 'md',

View File

@@ -66,10 +66,13 @@ export default function DockerMenuButton(props: any) {
onClose={() => setOpened(false)}
padding="xl"
position="right"
size="full"
size="100%"
title={<ContainerActionBar selected={selection} reload={reload} />}
transitionProps={{
transition: 'pop',
}}
styles={{
drawer: {
content: {
display: 'flex',
flexDirection: 'column',
},

View File

@@ -14,6 +14,7 @@ import { IconSearch } from '@tabler/icons';
import Dockerode from 'dockerode';
import { useTranslation } from 'next-i18next';
import { useEffect, useState } from 'react';
import { MIN_WIDTH_MOBILE } from '../../constants/constants';
import ContainerState from './ContainerState';
const useStyles = createStyles((theme) => ({
@@ -34,7 +35,6 @@ export default function DockerTable({
containers: Dockerode.ContainerInfo[];
selection: Dockerode.ContainerInfo[];
}) {
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
const [usedContainers, setContainers] = useState<Dockerode.ContainerInfo[]>(containers);
const { classes, cx } = useStyles();
const [search, setSearch] = useState('');

View File

@@ -221,7 +221,7 @@ function askForMedia(type: MediaType, id: number, name: string, seasons?: number
color: 'orange',
loading: true,
autoClose: false,
disallowClose: true,
withCloseButton: false,
icon: <IconAlertCircle />,
});
axios

View File

@@ -56,7 +56,7 @@ const useStyles = createStyles((theme) => ({
maxWidth: 540,
margin: 'auto',
marginTop: theme.spacing.xl,
marginBottom: theme.spacing.xl * 1.5,
marginBottom: `calc(${theme.spacing.xl} * 1.5)`,
},
}));

View File

@@ -2,7 +2,6 @@ import { ColorScheme, ColorSchemeProvider, MantineProvider, MantineTheme } from
import { useColorScheme, useHotkeys, useLocalStorage } from '@mantine/hooks';
import { ModalsProvider } from '@mantine/modals';
import Consola from 'consola';
import { NotificationsProvider } from '@mantine/notifications';
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { getCookie } from 'cookies-next';
@@ -11,6 +10,7 @@ import { appWithTranslation } from 'next-i18next';
import { AppProps } from 'next/app';
import Head from 'next/head';
import { useEffect, useState } from 'react';
import { Notifications } from '@mantine/notifications';
import 'video.js/dist/video-js.css';
import { ChangeAppPositionModal } from '../components/Dashboard/Modals/ChangePosition/ChangeAppPositionModal';
import { ChangeWidgetPositionModal } from '../components/Dashboard/Modals/ChangePosition/ChangeWidgetPositionModal';
@@ -112,21 +112,20 @@ function App(
withNormalizeCSS
>
<ConfigProvider>
<NotificationsProvider limit={4} position="bottom-left">
<ModalsProvider
modals={{
editApp: EditAppModal,
selectElement: SelectElementModal,
integrationOptions: WidgetsEditModal,
integrationRemove: WidgetsRemoveModal,
categoryEditModal: CategoryEditModal,
changeAppPositionModal: ChangeAppPositionModal,
changeIntegrationPositionModal: ChangeWidgetPositionModal,
}}
>
<Component {...pageProps} />
</ModalsProvider>
</NotificationsProvider>
<Notifications limit={4} position="bottom-left" />
<ModalsProvider
modals={{
editApp: EditAppModal,
selectElement: SelectElementModal,
integrationOptions: WidgetsEditModal,
integrationRemove: WidgetsRemoveModal,
categoryEditModal: CategoryEditModal,
changeAppPositionModal: ChangeAppPositionModal,
changeIntegrationPositionModal: ChangeWidgetPositionModal,
}}
>
<Component {...pageProps} />
</ModalsProvider>
</ConfigProvider>
</MantineProvider>
</ColorTheme.Provider>

View File

@@ -62,7 +62,7 @@ export default function AuthenticationTitle() {
title: t('notifications.checking.title'),
message: t('notifications.checking.message'),
autoClose: false,
disallowClose: true,
withCloseButton: false,
});
axios
.post('/api/configs/tryPassword', {

View File

@@ -56,7 +56,7 @@ const useStyles = createStyles((theme) => ({
fontWeight: 900,
fontSize: 110,
lineHeight: 1,
marginBottom: theme.spacing.xl * 1.5,
marginBottom: `calc(${theme.spacing.xl} * 1.5)`,
[theme.fn.smallerThan('sm')]: {
fontSize: 60,
@@ -90,7 +90,7 @@ const useStyles = createStyles((theme) => ({
maxWidth: 700,
margin: 'auto',
marginTop: theme.spacing.xl,
marginBottom: theme.spacing.xl * 1.5,
marginBottom: `calc(${theme.spacing.xl} * 1.5)`,
},
}));

View File

@@ -1,5 +1,6 @@
import { Box, Indicator, IndicatorProps, Popover } from '@mantine/core';
import { Box, Indicator, IndicatorProps, Popover, useMantineTheme } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { isToday } from '../../tools/isToday';
import { MediaList } from './MediaList';
import { MediasType } from './type';
@@ -22,12 +23,24 @@ export const CalendarDay = ({ date, medias }: CalendarDayProps) => {
withinPortal
radius="lg"
shadow="sm"
transition="pop"
transitionProps={{
transition: 'pop',
}}
onClose={close}
opened={opened}
>
<Popover.Target>
<Box onClick={open}>
<Box
onClick={open}
sx={(theme) => ({
margin: 5,
backgroundColor: isToday(date)
? theme.colorScheme === 'dark'
? theme.colors.dark[5]
: theme.colors.gray[0]
: undefined,
})}
>
<DayIndicator color="red" position="bottom-start" medias={medias.books}>
<DayIndicator color="yellow" position="top-start" medias={medias.movies}>
<DayIndicator color="blue" position="top-end" medias={medias.tvShows}>

View File

@@ -72,39 +72,15 @@ function CalendarTile({ widget }: CalendarTileProps) {
return (
<Group grow style={{ height: '100%' }}>
<Calendar
m={0}
p={0}
month={month}
// Should be offset 5px to the left
style={{ position: 'relative', top: -15 }}
onMonthChange={setMonth}
defaultDate={new Date()}
onPreviousMonth={setMonth}
onNextMonth={setMonth}
size="xs"
locale={i18n?.resolvedLanguage ?? 'en'}
fullWidth
onChange={() => {}}
firstDayOfWeek={widget.properties.sundayStart ? 'sunday' : 'monday'}
dayStyle={(date) => ({
margin: -1,
backgroundColor: isToday(date)
? colorScheme === 'dark'
? colors.dark[5]
: colors.gray[0]
: undefined,
})}
firstDayOfWeek={widget.properties.sundayStart ? 0 : 1}
hideWeekdays
styles={{
weekdayCell: {
margin: 0,
padding: 0,
},
calendarHeader: {
position: 'relative',
margin: 0,
padding: 0,
},
}}
allowLevelChange={false}
dayClassName={(_, modifiers) => cx({ [classes.weekend]: modifiers.weekend })}
date={month}
hasNextLevel={false}
renderDay={(date) => (
<CalendarDay date={date} medias={getReleasedMediasForDate(medias, date, widget)} />
)}

View File

@@ -1,4 +1,4 @@
import { createStyles, Title, useMantineTheme } from '@mantine/core';
import { createStyles, Title, useMantineTheme, getStylesRef } from '@mantine/core';
import { useTranslation } from 'next-i18next';
import { DashDotCompactNetwork, DashDotInfo } from './DashDotCompactNetwork';
import { DashDotCompactStorage } from './DashDotCompactStorage';
@@ -77,7 +77,7 @@ const useIframeSrc = (
);
};
export const useStyles = createStyles((theme, _params, getRef) => ({
export const useStyles = createStyles((theme, _params) => ({
iframe: {
flex: '1 0 auto',
maxWidth: '100%',
@@ -87,7 +87,7 @@ export const useStyles = createStyles((theme, _params, getRef) => ({
colorScheme: 'light', // fixes white borders around iframe
},
graphTitle: {
ref: getRef('graphTitle'),
ref: getStylesRef('graphTitle'),
position: 'absolute',
right: 0,
bottom: 0,
@@ -99,7 +99,7 @@ export const useStyles = createStyles((theme, _params, getRef) => ({
},
graphContainer: {
position: 'relative',
[`&:hover .${getRef('graphTitle')}`]: {
[`&:hover .${getStylesRef('graphTitle')}`]: {
opacity: 0.5,
},
},

View File

@@ -232,7 +232,7 @@ const fetchDashDotInfo = async (configName: string | undefined) => {
export const useDashDotTileStyles = createStyles((theme) => ({
graphsContainer: {
marginRight: theme.spacing.sm * -1, // fix because margin collapses weirdly
marginRight: `calc(${theme.spacing.sm} * -1)`,
},
}));

View File

@@ -35,7 +35,7 @@ interface TorrentQueueItemProps {
export const BitTorrrentQueueItem = ({ torrent, app }: TorrentQueueItemProps) => {
const [popoverOpened, { open: openPopover, close: closePopover }] = useDisclosure(false);
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
const theme = useMantineTheme();
const { width } = useElementSize();
const { t } = useTranslation('modules/torrents-status');
@@ -75,17 +75,17 @@ export const BitTorrrentQueueItem = ({ torrent, app }: TorrentQueueItemProps) =>
<td>
<Text size="xs">{humanFileSize(size, false)}</Text>
</td>
{width > MIN_WIDTH_MOBILE && (
{theme.fn.largerThan('xs') && (
<td>
<Text size="xs">{downloadSpeed > 0 ? `${downloadSpeed.toFixed(1)} Mb/s` : '-'}</Text>
</td>
)}
{width > MIN_WIDTH_MOBILE && (
{theme.fn.largerThan('xs') && (
<td>
<Text size="xs">{uploadSpeed > 0 ? `${uploadSpeed.toFixed(1)} Mb/s` : '-'}</Text>
</td>
)}
{width > MIN_WIDTH_MOBILE && (
{theme.fn.largerThan('xs') && (
<td>
<Text size="xs">{torrent.eta <= 0 ? '∞' : calculateETA(torrent.eta)}</Text>
</td>

View File

@@ -17,6 +17,7 @@ import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import relativeTime from 'dayjs/plugin/relativeTime';
import { useTranslation } from 'next-i18next';
import { MIN_WIDTH_MOBILE } from '../../constants/constants';
import { useGetDownloadClientsQueue } from '../../hooks/widgets/download-speed/useGetNetworkSpeed';
import { NormalizedDownloadQueueResponse } from '../../types/api/downloads/queue/NormalizedDownloadQueueResponse';
import { AppIntegrationType } from '../../types/app';
@@ -59,7 +60,6 @@ interface TorrentTileProps {
function TorrentTile({ widget }: TorrentTileProps) {
const { t } = useTranslation('modules/torrents-status');
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
const { width } = useElementSize();
const {

View File

@@ -28,6 +28,7 @@ import { defineWidget } from '../helper';
import { IWidget } from '../widgets';
import { UsenetHistoryList } from './UsenetHistoryList';
import { UsenetQueueList } from './UsenetQueueList';
import { MIN_WIDTH_MOBILE } from '../../constants/constants';
dayjs.extend(duration);
@@ -59,7 +60,6 @@ function UseNetTile({ widget }: UseNetTileProps) {
config?.apps.filter((x) => x.integration && downloadAppTypes.includes(x.integration.type)) ??
[];
const { ref, width, height } = useElementSize();
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
const [selectedAppId, setSelectedApp] = useState<string | null>(downloadApps[0]?.id);
const { data } = useGetUsenetInfo({ appId: selectedAppId! });

View File

@@ -128,7 +128,7 @@ export const UsenetHistoryList: FunctionComponent<UsenetHistoryListProps> = ({ a
position="center"
mt="md"
total={totalPages}
page={page}
value={page}
onChange={setPage}
/>
)}

View File

@@ -35,7 +35,7 @@ const PAGE_SIZE = 13;
export const UsenetQueueList: FunctionComponent<UsenetQueueListProps> = ({ appId }) => {
const theme = useMantineTheme();
const { t } = useTranslation('modules/usenet');
const progressbarBreakpoint = theme.breakpoints.xs;
const progressbarBreakpoint = parseInt(theme.breakpoints.xs, 10);
const progressBreakpoint = 400;
const sizeBreakpoint = 300;
const { ref, width } = useElementSize();
@@ -177,7 +177,7 @@ export const UsenetQueueList: FunctionComponent<UsenetQueueListProps> = ({ appId
size="sm"
position="center"
total={totalPages}
page={page}
value={page}
onChange={setPage}
/>
)}