Skip to content

Commit

Permalink
refactor: Various smaller improvements for the new frontend (#1567)
Browse files Browse the repository at this point in the history
* fix: Use FocusTrap on LyricsContainer

* refactor: Extract getBestThumbUrl into helper

* refactor: Move createStyles into separate .styles files

* refactor: Ensure that .styles files end with .ts

* refactor: Remove outdated imports

* refactor: Extract thumb url creation code

* chores: Remove outdated TODOs

* fix: Remove markdown from tag tooltip content

* feat: Render markdown in comments

* chores: Remove outdated TODOs

* fix: Use extendedUserLanguageCultures for LyricsTab

* perf: Remove decimal.js-light
  • Loading branch information
FinnRG authored Jul 28, 2023
1 parent 28ff438 commit ced7a0b
Show file tree
Hide file tree
Showing 34 changed files with 391 additions and 333 deletions.
9 changes: 5 additions & 4 deletions VocaDbWeb/New/Helpers/BpmHelper.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import Decimal from 'decimal.js-light';
// TODO: Check if we can implement this algorithm without decimal.js
const div = (num: number): number => {
return Math.round(num / 1000);
};

export const formatFromMilliBpm = (minMilliBpm?: number, maxMilliBpm?: number): string => {
if (minMilliBpm && maxMilliBpm && maxMilliBpm > minMilliBpm) {
return `${new Decimal(minMilliBpm).div(1000)} - ${new Decimal(maxMilliBpm).div(1000)}`;
return `${div(minMilliBpm)} - ${div(maxMilliBpm)}`;
}

if (minMilliBpm) return `${new Decimal(minMilliBpm).div(1000)}`;
if (minMilliBpm) return `${div(minMilliBpm)}`;

return '';
};
Expand Down
32 changes: 32 additions & 0 deletions VocaDbWeb/New/Helpers/getBestThumbUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { PVContract } from '@/types/DataContracts/PVs/PVContract';

const PREFERRED_SERVICES = ['Youtube', 'NicoNicoDouga', 'Bilibili', 'Vimeo'];

export const getBestThumbUrl = (pvs: PVContract[] | undefined): string | undefined => {
if (pvs === undefined) {
return undefined;
}

return pvs
.filter((pv) => !pv.disabled && pv.url !== undefined)
.reduce((currPV: PVContract | undefined, nextPV) => {
const currPos = PREFERRED_SERVICES.indexOf(currPV?.service ?? '');
const nextPos = PREFERRED_SERVICES.indexOf(nextPV.service ?? '');
if (
currPV === undefined ||
(PREFERRED_SERVICES.includes(nextPV.service) && nextPos < currPos)
) {
return nextPV;
}
return currPV;
}, undefined)?.url;
};

export const getBestThumbImageUrl = (pvs: PVContract[] | undefined): string => {
const bestThumbUrl = getBestThumbUrl(pvs);

return bestThumbUrl === undefined
? `/unknown.webp`
: `/api/pvs/thumbnail?pvUrl=${bestThumbUrl}`;
};

27 changes: 27 additions & 0 deletions VocaDbWeb/New/Helpers/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,30 @@ export default function parse(html: string): string | JSX.Element | JSX.Element[
});
}

// https://github.com/danestves/markdown-to-text/blob/main/index.ts
export const unmark = (markdown: string | undefined): string => {
if (markdown === undefined) return '';

return markdown
.replace(/^(-\s*?|\*\s*?|_\s*?){3,}\s*$/gm, '')
.replace(/\n={2,}/g, '\n')
.replace(/~{3}.*\n/g, '')
.replace(/~~/g, '')
.replace(/`{3}.*\n/g, '')
.replace(/<[^>]*>/g, '')
.replace(/^[=\-]{2,}\s*$/g, '')
.replace(/\[\^.+?\](\: .*?$)?/g, '')
.replace(/\s{0,2}\[.*?\]: .*?$/g, '')
.replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, '$1')
.replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1')
.replace(/^\s{0,3}>\s?/g, '')
.replace(/(^|\n)\s{0,3}>\s?/g, '\n\n')
.replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, '')
.replace(/^(\n)?\s{0,}#{1,6}\s+| {0,}(\n)?\s{0,}#{0,} {0,}(\n)?\s{0,}$/gm, '$1$2$3')
.replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, '$2')
.replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, '$2')
.replace(/(`{3,})(.*?)\1/gm, '$2')
.replace(/`(.+?)`/g, '$1')
.replace(/\n{2,}/g, '\n\n');
};

1 change: 0 additions & 1 deletion VocaDbWeb/New/Model/Repos/AntiforgeryRepository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { apiFetch, readCookie } from '@/Helpers/FetchApiHelper';

export const getXsrfToken = async () => {
// TODO: Convert this back to apiFetch, once we use the correct domain
await apiFetch('/api/antiforgery/token');

const xsrfToken = readCookie(document.cookie, 'XSRF-TOKEN');
Expand Down
14 changes: 14 additions & 0 deletions VocaDbWeb/New/components/AppShell/AppShell.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createStyles } from '@mantine/core';

export const useStyles = createStyles((theme) => ({
box: {
padding: theme.spacing.md,
position: 'relative',
height: 'calc(100vh - 70px - 64px)',
overflowY: 'scroll',
[theme.fn.smallerThan('sm')]: {
height: 'calc(100vh - 50px - 64px)',
},
},
}));

20 changes: 7 additions & 13 deletions VocaDbWeb/New/components/AppShell/AppShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react';
import Header from './Header';
import { useRouter } from 'next/router';
import dynamic from 'next/dynamic';
import { useStyles } from './AppShell.styles';

const Navbar = dynamic(() => import('./Navbar'), {
ssr: false,
Expand All @@ -28,6 +29,7 @@ interface CustomAppShellProps {
const CustomAppShell = ({ children }: CustomAppShellProps): React.ReactElement => {
const router = useRouter();
const [opened, setOpened] = useState(false);
const { classes } = useStyles();

// Close burger menu on navigation
useEffect(() => {
Expand All @@ -51,19 +53,11 @@ const CustomAppShell = ({ children }: CustomAppShellProps): React.ReactElement =
})}
padding={0}
>
<MediaQuery smallerThan="sm" styles={{ height: 'calc(100vh - 50px - 64px)' }}>
<Box
id="main-content"
p="md"
pos="relative"
h="calc(100vh - 70px - 64px)"
style={{ overflowY: 'scroll' }}
>
{children}
<LyricsContainer />
<PVPlayer />
</Box>
</MediaQuery>
<Box id="main-content" className={classes.box}>
{children}
<LyricsContainer />
<PVPlayer />
</Box>
<Footer />
</AppShell>
);
Expand Down
38 changes: 38 additions & 0 deletions VocaDbWeb/New/components/AppShell/CollapsibleLinkGroup.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { createStyles, rem } from '@mantine/core';

export const useStyles = createStyles((theme) => ({
control: {
display: 'block',
width: '100%',
padding: `${theme.spacing.xs} `,
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.black,
fontSize: theme.fontSizes.sm,

'&:hover': {
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
},
},

link: {
display: 'block',
padding: `${theme.spacing.xs}`,
paddingLeft: rem(31),
marginLeft: rem(30),
fontSize: theme.fontSizes.sm,
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.gray[7],
borderLeft: `${rem(1)} solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,

'&:hover': {
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
},
},
iconWrapper: {
display: 'flex',
alignItems: 'center',
},
}));

37 changes: 3 additions & 34 deletions VocaDbWeb/New/components/AppShell/CollapsibleLinkGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,10 @@
// From https://ui.mantine.dev/component/navbar-links-group
import { PermissionToken } from '@/types/Models/LoginManager';
import { Group, Box, ThemeIcon, Text, UnstyledButton, createStyles, rem } from '@mantine/core';
import { Group, Box, ThemeIcon, Text, UnstyledButton } from '@mantine/core';
import Link from 'next/link';
import { hasPermission } from '@/Helpers/PermissionsHelper';
import { useVdbStore } from '@/stores/useVdbStore';

const useStyles = createStyles((theme) => ({
control: {
display: 'block',
width: '100%',
padding: `${theme.spacing.xs} `,
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.black,
fontSize: theme.fontSizes.sm,

'&:hover': {
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
},
},

link: {
display: 'block',
padding: `${theme.spacing.xs}`,
paddingLeft: rem(31),
marginLeft: rem(30),
fontSize: theme.fontSizes.sm,
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.gray[7],
borderLeft: `${rem(1)} solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,

'&:hover': {
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
},
},
}));
import { useStyles } from './CollapsibleLinkGroup.styles';

export interface LinksGroupProps {
icon: React.FC<any>;
Expand Down Expand Up @@ -69,7 +38,7 @@ export function NavbarLinksGroup({ icon: Icon, label, links, link, permission }:
<>
<UnstyledButton component={Link} href={link} className={classes.control}>
<Group position="apart" spacing={0}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Box className={classes.iconWrapper}>
<ThemeIcon color={theme.primaryColor} size={30}>
<Icon size="1.1rem" />
</ThemeIcon>
Expand Down
26 changes: 26 additions & 0 deletions VocaDbWeb/New/components/AppShell/Footer.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createStyles, rem } from '@mantine/core';

export const useStyles = createStyles((theme) => ({
base: {
position: 'fixed',
height: 65,
right: 0,
bottom: 0,
left: 300,
[theme.fn.smallerThan('lg')]: {
left: 220,
},
[theme.fn.smallerThan('sm')]: {
left: 0,
},
borderTop: `${rem(1)} solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
},
footer: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
height: '100%',
},
}));
46 changes: 6 additions & 40 deletions VocaDbWeb/New/components/AppShell/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import {
ActionIcon,
Group,
Paper,
Slider,
Text,
createStyles,
rem,
useMantineTheme,
} from '@mantine/core';
import { ActionIcon, Group, Paper, Slider, Text } from '@mantine/core';
import PlayerControls from './PlayerControls';
import { usePlayerStore } from '@/nostalgic-darling/stores/usePlayerStore';
import React, { useRef, useState } from 'react';
import React, { useState } from 'react';
import { IconMicrophone2, IconVolume, IconVolumeOff } from '@tabler/icons-react';
import { useMediaQuery, usePrevious } from '@mantine/hooks';
import MobilePlayer from './MobilePlayer';
import { useStyles } from './Footer.styles';

interface SongInfoProps {
showMobileLayout?: boolean;
Expand Down Expand Up @@ -92,43 +84,17 @@ const VolumeControl = () => {
);
};

const useStyles = createStyles((theme) => ({
base: {
position: 'fixed',
height: 65,
right: 0,
bottom: 0,
left: 300,
[theme.fn.smallerThan('lg')]: {
left: 220,
},
[theme.fn.smallerThan('sm')]: {
left: 0,
},
borderTop: `${rem(1)} solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[3]
}`,
},
footer: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
height: '100%',
},
}));

const CustomFooter = () => {
const theme = useMantineTheme();
const styles = useStyles();
const { classes, theme } = useStyles();
const [expanded, setExpanded] = useState(false);
const isMobile = useMediaQuery(`(max-width: ${theme.breakpoints['sm']})`);

return (
<div className={styles.classes.base}>
<div className={classes.base}>
<Paper
onClick={() => setExpanded(isMobile && !expanded)}
px="md"
className={styles.classes.footer}
className={classes.footer}
component="footer"
>
<SongInfo showMobileLayout={isMobile} />
Expand Down
26 changes: 26 additions & 0 deletions VocaDbWeb/New/components/AppShell/Header.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createStyles } from '@mantine/core';

export const useStyles = createStyles((theme) => ({
header: {
display: 'flex',
justifyContent: 'space-between',
},

image: {
objectFit: 'contain',
height: '100%',
},

rightSectionWrapper: {
display: 'flex',
alignItems: 'center',
height: '100%',
},

burger: {
[theme.fn.largerThan('sm')]: {
display: 'none',
},
},
}));

Loading

0 comments on commit ced7a0b

Please sign in to comment.