mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-19 09:54:18 +02:00
Update look and feel
This commit is contained in:
+13
-2
@@ -45,7 +45,7 @@ export const App = () => {
|
|||||||
outlineOffset: '-1px',
|
outlineOffset: '-1px',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
fontFamily: 'Inter, sans-serif',
|
fontFamily: 'var(--content-font-family)',
|
||||||
fontSizes: {
|
fontSizes: {
|
||||||
lg: 16,
|
lg: 16,
|
||||||
md: 14,
|
md: 14,
|
||||||
@@ -74,7 +74,18 @@ export const App = () => {
|
|||||||
}}
|
}}
|
||||||
transitionDuration={200}
|
transitionDuration={200}
|
||||||
>
|
>
|
||||||
<ModalsProvider modals={{ base: BaseContextModal }}>
|
<ModalsProvider
|
||||||
|
modalProps={{
|
||||||
|
centered: true,
|
||||||
|
exitTransitionDuration: 300,
|
||||||
|
overflow: 'inside',
|
||||||
|
overlayBlur: 5,
|
||||||
|
overlayOpacity: 0.9,
|
||||||
|
transition: 'slide-down',
|
||||||
|
transitionDuration: 300,
|
||||||
|
}}
|
||||||
|
modals={{ base: BaseContextModal }}
|
||||||
|
>
|
||||||
<SelectRouter>
|
<SelectRouter>
|
||||||
<AppRouter />
|
<AppRouter />
|
||||||
</SelectRouter>
|
</SelectRouter>
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ type MenuDropdownProps = MantineMenuDropdownProps;
|
|||||||
const StyledMenu = styled(MantineMenu)<MenuProps>``;
|
const StyledMenu = styled(MantineMenu)<MenuProps>``;
|
||||||
|
|
||||||
const StyledMenuLabel = styled(MantineMenu.Label)<MenuLabelProps>`
|
const StyledMenuLabel = styled(MantineMenu.Label)<MenuLabelProps>`
|
||||||
font-family: var(--label-font-family);
|
font-family: var(--content-font-family);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledMenuItem = styled(MantineMenu.Item)<MenuItemProps>`
|
const StyledMenuItem = styled(MantineMenu.Item)<MenuItemProps>`
|
||||||
padding: 0.8rem;
|
padding: 0.8rem;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
font-family: var(--label-font-family);
|
font-family: var(--content-font-family);
|
||||||
background-color: var(--dropdown-menu-bg);
|
background-color: var(--dropdown-menu-bg);
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const StyledPopover = styled(MantinePopover)``;
|
|||||||
const StyledDropdown = styled(MantinePopover.Dropdown)<PopoverDropdownProps>`
|
const StyledDropdown = styled(MantinePopover.Dropdown)<PopoverDropdownProps>`
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
font-family: var(--label-font-family);
|
font-family: var(--content-font-family);
|
||||||
background-color: var(--dropdown-menu-bg);
|
background-color: var(--dropdown-menu-bg);
|
||||||
|
|
||||||
& .mantine-Menu-itemIcon {
|
& .mantine-Menu-itemIcon {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const StyledSegmentedControl = styled(
|
|||||||
)<MantineSegmentedControlProps>`
|
)<MantineSegmentedControlProps>`
|
||||||
& .mantine-SegmentedControl-label {
|
& .mantine-SegmentedControl-label {
|
||||||
color: var(--input-fg);
|
color: var(--input-fg);
|
||||||
font-family: var(--label-font-family);
|
font-family: var(--content-font-family);
|
||||||
}
|
}
|
||||||
|
|
||||||
background-color: var(--input-bg);
|
background-color: var(--input-bg);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ interface TextProps extends MantineTextDivProps {
|
|||||||
const BaseText = styled(MantineText)<TextProps>`
|
const BaseText = styled(MantineText)<TextProps>`
|
||||||
color: ${(props) =>
|
color: ${(props) =>
|
||||||
props.$secondary ? 'var(--main-fg-secondary)' : 'var(--main-fg)'};
|
props.$secondary ? 'var(--main-fg-secondary)' : 'var(--main-fg)'};
|
||||||
font-family: ${(props) => props.font};
|
font-family: ${(props) => props.font || 'var(--content-font-family)'};
|
||||||
cursor: ${(props) => (props.$link ? 'cursor' : 'default')};
|
cursor: ${(props) => (props.$link ? 'cursor' : 'default')};
|
||||||
user-select: ${(props) => (props.$noSelect ? 'none' : 'auto')};
|
user-select: ${(props) => (props.$noSelect ? 'none' : 'auto')};
|
||||||
${(props) => props.overflow === 'hidden' && textEllipsis}
|
${(props) => props.overflow === 'hidden' && textEllipsis}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { ListChildComponentProps } from 'react-window';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Text } from '@/renderer/components/text';
|
import { Text } from '@/renderer/components/text';
|
||||||
import { GridCardControls } from '@/renderer/components/virtual-grid/grid-card/grid-card-controls';
|
import { GridCardControls } from '@/renderer/components/virtual-grid/grid-card/grid-card-controls';
|
||||||
import { fadeIn } from '@/renderer/styles';
|
|
||||||
import {
|
import {
|
||||||
PlayQueueAddOptions,
|
PlayQueueAddOptions,
|
||||||
LibraryItem,
|
LibraryItem,
|
||||||
@@ -90,12 +89,7 @@ const ImageSection = styled.div<{ size?: number }>`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Image = styled(SimpleImg)`
|
const Image = styled(SimpleImg)`
|
||||||
object-fit: cover;
|
|
||||||
border: 0;
|
|
||||||
border-radius: var(--card-default-radius);
|
border-radius: var(--card-default-radius);
|
||||||
|
|
||||||
${fadeIn}
|
|
||||||
animation: fadein 0.3s ease-in-out;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ControlsContainer = styled.div`
|
const ControlsContainer = styled.div`
|
||||||
@@ -157,6 +151,8 @@ export const DefaultCard = ({
|
|||||||
const { handlePlayQueueAdd, itemType, cardRows, route, playButtonBehavior } =
|
const { handlePlayQueueAdd, itemType, cardRows, route, playButtonBehavior } =
|
||||||
controls;
|
controls;
|
||||||
|
|
||||||
|
const cardSize = itemWidth - 24;
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
return (
|
return (
|
||||||
<CardWrapper
|
<CardWrapper
|
||||||
@@ -184,10 +180,11 @@ export const DefaultCard = ({
|
|||||||
{data?.imageUrl ? (
|
{data?.imageUrl ? (
|
||||||
<Image
|
<Image
|
||||||
animationDuration={0.2}
|
animationDuration={0.2}
|
||||||
height={itemWidth - 24}
|
height={cardSize}
|
||||||
|
imgStyle={{ objectFit: 'cover' }}
|
||||||
placeholder="var(--card-default-bg)"
|
placeholder="var(--card-default-bg)"
|
||||||
src={data?.imageUrl}
|
src={data?.imageUrl}
|
||||||
width={itemWidth - 24}
|
width={cardSize}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Center
|
<Center
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ interface ImageProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Image = styled(SimpleImg)<ImageProps>`
|
const Image = styled(SimpleImg)<ImageProps>`
|
||||||
object-fit: cover;
|
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: var(--card-poster-radius);
|
border-radius: var(--card-poster-radius);
|
||||||
`;
|
`;
|
||||||
@@ -177,6 +176,7 @@ export const PosterCard = ({
|
|||||||
<Image
|
<Image
|
||||||
animationDuration={0.2}
|
animationDuration={0.2}
|
||||||
height={itemWidth}
|
height={itemWidth}
|
||||||
|
imgStyle={{ objectFit: 'cover' }}
|
||||||
placeholder="var(--card-default-bg)"
|
placeholder="var(--card-default-bg)"
|
||||||
src={data?.imageUrl}
|
src={data?.imageUrl}
|
||||||
width={itemWidth}
|
width={itemWidth}
|
||||||
|
|||||||
@@ -122,7 +122,9 @@ export const LeftControls = () => {
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
compact
|
compact
|
||||||
variant="subtle"
|
radius={0}
|
||||||
|
size="xs"
|
||||||
|
variant="default"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setSidebar({ image: true });
|
setSidebar({ image: true });
|
||||||
@@ -152,7 +154,12 @@ export const LeftControls = () => {
|
|||||||
{artists?.map((artist, index) => (
|
{artists?.map((artist, index) => (
|
||||||
<React.Fragment key={`bar-${artist.id}`}>
|
<React.Fragment key={`bar-${artist.id}`}>
|
||||||
{index > 0 && (
|
{index > 0 && (
|
||||||
<Text $secondary style={{ display: 'inline-block' }}>
|
<Text
|
||||||
|
$link
|
||||||
|
$secondary
|
||||||
|
size="xs"
|
||||||
|
style={{ display: 'inline-block' }}
|
||||||
|
>
|
||||||
,
|
,
|
||||||
</Text>
|
</Text>
|
||||||
)}{' '}
|
)}{' '}
|
||||||
@@ -160,7 +167,7 @@ export const LeftControls = () => {
|
|||||||
$link
|
$link
|
||||||
component={Link}
|
component={Link}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
size="sm"
|
size="xs"
|
||||||
to={
|
to={
|
||||||
artist.id
|
artist.id
|
||||||
? generatePath(AppRoute.LIBRARY_ARTISTS_DETAIL, {
|
? generatePath(AppRoute.LIBRARY_ARTISTS_DETAIL, {
|
||||||
@@ -180,8 +187,7 @@ export const LeftControls = () => {
|
|||||||
$link
|
$link
|
||||||
component={Link}
|
component={Link}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
size="sm"
|
size="xs"
|
||||||
sx={{ '&:hover': { textDecoration: 'underline' } }}
|
|
||||||
to={
|
to={
|
||||||
album?.id
|
album?.id
|
||||||
? generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, {
|
? generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
variant="filled"
|
variant="filled"
|
||||||
>
|
>
|
||||||
Submit
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export const EditServerForm = ({ server, onCancel }: EditServerFormProps) => {
|
|||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="submit" variant="filled">
|
<Button type="submit" variant="filled">
|
||||||
Update
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
import { Group } from '@mantine/core';
|
import { Group } from '@mantine/core';
|
||||||
import { openContextModal } from '@mantine/modals';
|
import { openContextModal } from '@mantine/modals';
|
||||||
import { RiServerFill } from 'react-icons/ri';
|
import { RiAddFill, RiServerFill } from 'react-icons/ri';
|
||||||
import {
|
import { Button, ContextModalVars, Accordion } from '@/renderer/components';
|
||||||
Text,
|
|
||||||
Button,
|
|
||||||
ContextModalVars,
|
|
||||||
Accordion,
|
|
||||||
} from '@/renderer/components';
|
|
||||||
import { ServerListItem } from '@/renderer/features/servers/components/server-list-item';
|
import { ServerListItem } from '@/renderer/features/servers/components/server-list-item';
|
||||||
import { useServerList } from '@/renderer/features/servers/queries/use-server-list';
|
import { useServerList } from '@/renderer/features/servers/queries/use-server-list';
|
||||||
import { usePermissions } from '@/renderer/features/shared';
|
import { usePermissions } from '@/renderer/features/shared';
|
||||||
import { Font } from '@/renderer/styles';
|
|
||||||
import { titleCase } from '@/renderer/utils';
|
import { titleCase } from '@/renderer/utils';
|
||||||
import { AddServerForm } from './add-server-form';
|
import { AddServerForm } from './add-server-form';
|
||||||
|
|
||||||
@@ -20,17 +14,13 @@ export const ServerList = () => {
|
|||||||
|
|
||||||
const handleAddServerModal = () => {
|
const handleAddServerModal = () => {
|
||||||
openContextModal({
|
openContextModal({
|
||||||
centered: true,
|
|
||||||
exitTransitionDuration: 300,
|
|
||||||
innerProps: {
|
innerProps: {
|
||||||
modalBody: (vars: ContextModalVars) => (
|
modalBody: (vars: ContextModalVars) => (
|
||||||
<AddServerForm onCancel={() => vars.context.closeModal(vars.id)} />
|
<AddServerForm onCancel={() => vars.context.closeModal(vars.id)} />
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
modal: 'base',
|
modal: 'base',
|
||||||
overflow: 'inside',
|
|
||||||
title: 'Add server',
|
title: 'Add server',
|
||||||
transition: 'slide-down',
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,15 +31,17 @@ export const ServerList = () => {
|
|||||||
position="right"
|
position="right"
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
right: 45,
|
right: 55,
|
||||||
transform: 'translateY(-35px)',
|
transform: 'translateY(-4rem)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{permissions.isAdmin && (
|
{permissions.isAdmin && (
|
||||||
<Button
|
<Button
|
||||||
autoFocus
|
autoFocus
|
||||||
compact
|
compact
|
||||||
variant="default"
|
leftIcon={<RiAddFill size={15} />}
|
||||||
|
size="sm"
|
||||||
|
variant="filled"
|
||||||
onClick={handleAddServerModal}
|
onClick={handleAddServerModal}
|
||||||
>
|
>
|
||||||
Add server
|
Add server
|
||||||
@@ -61,9 +53,7 @@ export const ServerList = () => {
|
|||||||
<Accordion.Item key={s.id} value={s.name}>
|
<Accordion.Item key={s.id} value={s.name}>
|
||||||
<Accordion.Control icon={<RiServerFill size={15} />}>
|
<Accordion.Control icon={<RiServerFill size={15} />}>
|
||||||
<Group position="apart">
|
<Group position="apart">
|
||||||
<Text font={Font.GOTHAM}>
|
{titleCase(s.type)} - {s.name}
|
||||||
{titleCase(s.type)} - {s.name}
|
|
||||||
</Text>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Accordion.Control>
|
</Accordion.Control>
|
||||||
<Accordion.Panel>
|
<Accordion.Panel>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const Container = styled.div``;
|
|||||||
|
|
||||||
const Section = styled.div`
|
const Section = styled.div`
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border: 1px solid var(--generic-border-color);
|
border: 1px dashed var(--generic-border-color);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ServerSection = ({ title, children }: ServerSectionProps) => {
|
export const ServerSection = ({ title, children }: ServerSectionProps) => {
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export const GeneralTab = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack mt="1rem" spacing="xl">
|
<Stack spacing="xl">
|
||||||
{options.map((option) => (
|
{options.map((option) => (
|
||||||
<SettingsOptions key={`general-${option.title}`} {...option} />
|
<SettingsOptions key={`general-${option.title}`} {...option} />
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ export const PlaybackTab = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack my={10} spacing="xl">
|
<Stack spacing="xl">
|
||||||
{playerOptions
|
{playerOptions
|
||||||
.filter((o) => !o.isHidden)
|
.filter((o) => !o.isHidden)
|
||||||
.map((option) => (
|
.map((option) => (
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Box } from '@mantine/core';
|
import { Box } from '@mantine/core';
|
||||||
|
import { Variants, motion } from 'framer-motion';
|
||||||
import { Tabs } from '@/renderer/components';
|
import { Tabs } from '@/renderer/components';
|
||||||
import { GeneralTab } from '@/renderer/features/settings/components/general-tab';
|
import { GeneralTab } from '@/renderer/features/settings/components/general-tab';
|
||||||
import { PlaybackTab } from '@/renderer/features/settings/components/playback-tab';
|
import { PlaybackTab } from '@/renderer/features/settings/components/playback-tab';
|
||||||
@@ -7,10 +8,26 @@ import { useSettingsStore } from '@/renderer/store/settings.store';
|
|||||||
export const Settings = () => {
|
export const Settings = () => {
|
||||||
const currentTab = useSettingsStore((state) => state.tab);
|
const currentTab = useSettingsStore((state) => state.tab);
|
||||||
const update = useSettingsStore((state) => state.setSettings);
|
const update = useSettingsStore((state) => state.setSettings);
|
||||||
|
|
||||||
|
const tabVariants: Variants = {
|
||||||
|
in: {
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
duration: 0.3,
|
||||||
|
},
|
||||||
|
x: 0,
|
||||||
|
},
|
||||||
|
out: {
|
||||||
|
opacity: 0,
|
||||||
|
x: 50,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box pr={15} sx={{ height: '800px', maxHeight: '50vh' }}>
|
<Box m={5} sx={{ height: '800px', maxHeight: '50vh', overflowX: 'hidden' }}>
|
||||||
<Tabs
|
<Tabs
|
||||||
orientation="horizontal"
|
keepMounted={false}
|
||||||
|
orientation="vertical"
|
||||||
styles={{
|
styles={{
|
||||||
tab: {
|
tab: {
|
||||||
fontSize: '1.1rem',
|
fontSize: '1.1rem',
|
||||||
@@ -18,8 +35,7 @@ export const Settings = () => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
value={currentTab}
|
value={currentTab}
|
||||||
variant="default"
|
variant="pills"
|
||||||
onChange={(e) => console.log(e)}
|
|
||||||
onTabChange={(e) => e && update({ tab: e })}
|
onTabChange={(e) => e && update({ tab: e })}
|
||||||
>
|
>
|
||||||
<Tabs.List>
|
<Tabs.List>
|
||||||
@@ -27,10 +43,14 @@ export const Settings = () => {
|
|||||||
<Tabs.Tab value="playback">Playback</Tabs.Tab>
|
<Tabs.Tab value="playback">Playback</Tabs.Tab>
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
<Tabs.Panel value="general">
|
<Tabs.Panel value="general">
|
||||||
<GeneralTab />
|
<motion.div animate="in" initial="out" variants={tabVariants}>
|
||||||
|
<GeneralTab />
|
||||||
|
</motion.div>
|
||||||
</Tabs.Panel>
|
</Tabs.Panel>
|
||||||
<Tabs.Panel value="playback">
|
<Tabs.Panel value="playback">
|
||||||
<PlaybackTab />
|
<motion.div animate="in" initial="out" variants={tabVariants}>
|
||||||
|
<PlaybackTab />
|
||||||
|
</motion.div>
|
||||||
</Tabs.Panel>
|
</Tabs.Panel>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ interface ListItemProps {
|
|||||||
const StyledItem = styled.div`
|
const StyledItem = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
font-family: var(--content-font-family);
|
||||||
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
border: 1px solid var(--primary-color);
|
border: 1px solid var(--primary-color);
|
||||||
@@ -22,6 +23,7 @@ const ItemStyle = css`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
color: var(--sidebar-btn-color);
|
color: var(--sidebar-btn-color);
|
||||||
|
font-family: var(--content-font-family);
|
||||||
border: 1px transparent solid;
|
border: 1px transparent solid;
|
||||||
transition: color 0.2s ease-in-out;
|
transition: color 0.2s ease-in-out;
|
||||||
|
|
||||||
|
|||||||
@@ -205,7 +205,8 @@ export const Sidebar = () => {
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
compact
|
compact
|
||||||
variant="subtle"
|
size="xs"
|
||||||
|
variant="default"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setSidebar({ image: false });
|
setSidebar({ image: false });
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export const ActivityMenu = () => {
|
|||||||
{isTaskRunning ? (
|
{isTaskRunning ? (
|
||||||
<StyledActivitySvg color="var(--primary-color)" size={15} />
|
<StyledActivitySvg color="var(--primary-color)" size={15} />
|
||||||
) : (
|
) : (
|
||||||
<FiActivity color="var(--titlebar-fg)" size={15} />
|
<FiActivity size={15} />
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</Popover.Target>
|
</Popover.Target>
|
||||||
|
|||||||
@@ -51,18 +51,13 @@ export const AppMenu = () => {
|
|||||||
|
|
||||||
const handleManageServersModal = () => {
|
const handleManageServersModal = () => {
|
||||||
openModal({
|
openModal({
|
||||||
centered: true,
|
|
||||||
children: <ServerList />,
|
children: <ServerList />,
|
||||||
exitTransitionDuration: 300,
|
|
||||||
overflow: 'inside',
|
|
||||||
title: 'Manage Servers',
|
title: 'Manage Servers',
|
||||||
transition: 'slide-down',
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEditProfileModal = () => {
|
const handleEditProfileModal = () => {
|
||||||
openModal({
|
openModal({
|
||||||
centered: true,
|
|
||||||
children: (
|
children: (
|
||||||
<EditUserForm
|
<EditUserForm
|
||||||
repeatPassword
|
repeatPassword
|
||||||
@@ -70,31 +65,21 @@ export const AppMenu = () => {
|
|||||||
onCancel={closeAllModals}
|
onCancel={closeAllModals}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
exitTransitionDuration: 300,
|
|
||||||
overflow: 'inside',
|
|
||||||
size: 'lg',
|
size: 'lg',
|
||||||
title: 'Edit Profile',
|
title: 'Edit Profile',
|
||||||
transition: 'slide-down',
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleManageUsersModal = () => {
|
const handleManageUsersModal = () => {
|
||||||
openModal({
|
openModal({
|
||||||
centered: true,
|
|
||||||
children: <UserList />,
|
children: <UserList />,
|
||||||
exitTransitionDuration: 300,
|
|
||||||
overflow: 'inside',
|
|
||||||
title: 'Manage Users',
|
title: 'Manage Users',
|
||||||
transition: 'slide-down',
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSettingsModal = () => {
|
const handleSettingsModal = () => {
|
||||||
openModal({
|
openModal({
|
||||||
centered: true,
|
|
||||||
children: <Settings />,
|
children: <Settings />,
|
||||||
exitTransitionDuration: 300,
|
|
||||||
overflow: 'inside',
|
|
||||||
size: 'xl',
|
size: 'xl',
|
||||||
title: (
|
title: (
|
||||||
<Group position="center">
|
<Group position="center">
|
||||||
@@ -102,7 +87,6 @@ export const AppMenu = () => {
|
|||||||
<Text>Settings</Text>
|
<Text>Settings</Text>
|
||||||
</Group>
|
</Group>
|
||||||
),
|
),
|
||||||
transition: 'slide-down',
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ export const AddUserForm = ({ onCancel }: AddUserFormProps) => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
variant="filled"
|
variant="filled"
|
||||||
>
|
>
|
||||||
Submit
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ export const EditUserForm = ({
|
|||||||
type="submit"
|
type="submit"
|
||||||
variant="filled"
|
variant="filled"
|
||||||
>
|
>
|
||||||
Submit
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -146,9 +146,7 @@ export const EditUserPermissionsForm = ({
|
|||||||
<Accordion.Item key={`server-permission-${s.id}`} value={s.name}>
|
<Accordion.Item key={`server-permission-${s.id}`} value={s.name}>
|
||||||
<Accordion.Control icon={<RiServerFill />}>
|
<Accordion.Control icon={<RiServerFill />}>
|
||||||
<Group>
|
<Group>
|
||||||
<Text>
|
{s.name} ({titleCase(s.type)})
|
||||||
{s.name} ({titleCase(s.type)})
|
|
||||||
</Text>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Accordion.Control>
|
</Accordion.Control>
|
||||||
<Accordion.Panel>
|
<Accordion.Panel>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import { Avatar, Group, Stack } from '@mantine/core';
|
import { Avatar, Group, Stack } from '@mantine/core';
|
||||||
import { openContextModal } from '@mantine/modals';
|
import { openContextModal } from '@mantine/modals';
|
||||||
import {
|
import {
|
||||||
|
RiAddFill,
|
||||||
RiAdminLine,
|
RiAdminLine,
|
||||||
RiDeleteBin2Line,
|
RiDeleteBin2Line,
|
||||||
RiEdit2Line,
|
RiEdit2Line,
|
||||||
@@ -29,24 +30,18 @@ export const UserList = () => {
|
|||||||
|
|
||||||
const handleAddUserModal = () => {
|
const handleAddUserModal = () => {
|
||||||
openContextModal({
|
openContextModal({
|
||||||
centered: true,
|
|
||||||
exitTransitionDuration: 300,
|
|
||||||
innerProps: {
|
innerProps: {
|
||||||
modalBody: (vars: ContextModalVars) => (
|
modalBody: (vars: ContextModalVars) => (
|
||||||
<AddUserForm onCancel={() => vars.context.closeModal(vars.id)} />
|
<AddUserForm onCancel={() => vars.context.closeModal(vars.id)} />
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
modal: 'base',
|
modal: 'base',
|
||||||
overflow: 'inside',
|
|
||||||
title: 'Add User',
|
title: 'Add User',
|
||||||
transition: 'slide-down',
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEditUserModal = (user: User) => {
|
const handleEditUserModal = (user: User) => {
|
||||||
openContextModal({
|
openContextModal({
|
||||||
centered: true,
|
|
||||||
exitTransitionDuration: 300,
|
|
||||||
innerProps: {
|
innerProps: {
|
||||||
modalBody: (vars: ContextModalVars) => (
|
modalBody: (vars: ContextModalVars) => (
|
||||||
<EditUserForm
|
<EditUserForm
|
||||||
@@ -56,10 +51,8 @@ export const UserList = () => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
modal: 'base',
|
modal: 'base',
|
||||||
overflow: 'inside',
|
|
||||||
size: 'lg',
|
size: 'lg',
|
||||||
title: `Edit User (${user.username})`,
|
title: `Edit User (${user.username})`,
|
||||||
transition: 'slide-down',
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,8 +75,6 @@ export const UserList = () => {
|
|||||||
|
|
||||||
const handleEdituserPermissionsModal = (user: User) => {
|
const handleEdituserPermissionsModal = (user: User) => {
|
||||||
openContextModal({
|
openContextModal({
|
||||||
centered: true,
|
|
||||||
exitTransitionDuration: 300,
|
|
||||||
innerProps: {
|
innerProps: {
|
||||||
modalBody: (vars: ContextModalVars) => (
|
modalBody: (vars: ContextModalVars) => (
|
||||||
<EditUserPermissionsForm
|
<EditUserPermissionsForm
|
||||||
@@ -93,9 +84,7 @@ export const UserList = () => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
modal: 'base',
|
modal: 'base',
|
||||||
overflow: 'inside',
|
|
||||||
title: `Edit Permissions (${user.username})`,
|
title: `Edit Permissions (${user.username})`,
|
||||||
transition: 'slide-down',
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -106,14 +95,16 @@ export const UserList = () => {
|
|||||||
position="right"
|
position="right"
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
right: 45,
|
right: 55,
|
||||||
transform: 'translateY(-35px)',
|
transform: 'translateY(-4rem)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
autoFocus
|
autoFocus
|
||||||
compact
|
compact
|
||||||
variant="default"
|
leftIcon={<RiAddFill size={15} />}
|
||||||
|
size="sm"
|
||||||
|
variant="filled"
|
||||||
onClick={handleAddUserModal}
|
onClick={handleAddUserModal}
|
||||||
>
|
>
|
||||||
Add user
|
Add user
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
|
import throttle from 'lodash/throttle';
|
||||||
import { Outlet } from 'react-router';
|
import { Outlet } from 'react-router';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { SideQueue } from '@/renderer/features/side-queue/components/side-queue';
|
import { SideQueue } from '@/renderer/features/side-queue/components/side-queue';
|
||||||
@@ -152,14 +153,16 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
|
|||||||
[isResizing, isResizingRight, setSidebar, sidebar.rightWidth]
|
[isResizing, isResizingRight, setSidebar, sidebar.rightWidth]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const throttledResize = useMemo(() => throttle(resize, 50), [resize]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('mousemove', resize);
|
window.addEventListener('mousemove', throttledResize);
|
||||||
window.addEventListener('mouseup', stopResizing);
|
window.addEventListener('mouseup', stopResizing);
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('mousemove', resize);
|
window.removeEventListener('mousemove', throttledResize);
|
||||||
window.removeEventListener('mouseup', stopResizing);
|
window.removeEventListener('mouseup', stopResizing);
|
||||||
};
|
};
|
||||||
}, [resize, stopResizing]);
|
}, [throttledResize, stopResizing]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ html {
|
|||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
color: var(--content-text-color);
|
color: var(--content-text-color);
|
||||||
background: var(--content-bg);
|
background: var(--content-bg);
|
||||||
|
font-family: var(--content-font-family);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
@use 'sass:color' as color;
|
@use 'sass:color' as color;
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--label-font-family: Poppins, sans-serif;
|
--content-font-family: Sora, sans-serif;
|
||||||
|
--header-font-family: Poppins, sans-serif;
|
||||||
|
|
||||||
--icon-color: rgb(255, 255, 255);
|
--icon-color: rgb(255, 255, 255);
|
||||||
|
|
||||||
--primary-color: rgb(58, 129, 237);
|
--primary-color: rgb(52, 109, 219);
|
||||||
--secondary-color: rgb(255, 120, 120);
|
--secondary-color: rgb(255, 120, 120);
|
||||||
--success-color: green;
|
--success-color: green;
|
||||||
--warning-color: orange;
|
--warning-color: orange;
|
||||||
@@ -13,7 +14,7 @@
|
|||||||
--generic-border-color: rgba(50, 50, 50, 0.7);
|
--generic-border-color: rgba(50, 50, 50, 0.7);
|
||||||
|
|
||||||
--main-bg: rgb(18, 18, 18);
|
--main-bg: rgb(18, 18, 18);
|
||||||
--main-fg: rgb(240, 240, 240);
|
--main-fg: rgb(245, 245, 245);
|
||||||
--main-fg-secondary: rgb(150, 150, 150);
|
--main-fg-secondary: rgb(150, 150, 150);
|
||||||
|
|
||||||
--titlebar-fg: rgb(255, 255, 255);
|
--titlebar-fg: rgb(255, 255, 255);
|
||||||
@@ -53,19 +54,19 @@
|
|||||||
--scrollbar-thumb-bg: #5a5a5a;
|
--scrollbar-thumb-bg: #5a5a5a;
|
||||||
|
|
||||||
--btn-primary-bg: var(--primary-color);
|
--btn-primary-bg: var(--primary-color);
|
||||||
--btn-primary-bg-hover: rgb(47, 122, 237);
|
--btn-primary-bg-hover: rgb(41, 100, 216);
|
||||||
--btn-primary-fg: #ffffff;
|
--btn-primary-fg: #ffffff;
|
||||||
--btn-primary-fg-hover: #ffffff;
|
--btn-primary-fg-hover: #ffffff;
|
||||||
|
|
||||||
--btn-default-bg: rgb(41, 41, 41);
|
--btn-default-bg: rgb(39, 39, 39);
|
||||||
--btn-default-bg-hover: rgb(51, 51, 51);
|
--btn-default-bg-hover: rgb(63, 63, 63);
|
||||||
--btn-default-fg: rgb(193, 193, 193);
|
--btn-default-fg: rgb(193, 193, 193);
|
||||||
--btn-default-fg-hover: rgb(193, 193, 193);
|
--btn-default-fg-hover: rgb(193, 193, 193);
|
||||||
|
|
||||||
--btn-subtle-bg: transparent;
|
--btn-subtle-bg: transparent;
|
||||||
--btn-subtle-bg-hover: rgba(100, 100, 100, 0.5);
|
--btn-subtle-bg-hover: transparent;
|
||||||
--btn-subtle-fg: rgb(150, 150, 150);
|
--btn-subtle-fg: rgb(150, 150, 150);
|
||||||
--btn-subtle-fg-hover: rgb(200, 200, 200);
|
--btn-subtle-fg-hover: rgb(240, 240, 240);
|
||||||
|
|
||||||
--input-bg: rgb(56, 56, 56);
|
--input-bg: rgb(56, 56, 56);
|
||||||
--input-fg: rgb(193, 193, 193);
|
--input-fg: rgb(193, 193, 193);
|
||||||
@@ -74,7 +75,7 @@
|
|||||||
--input-active-bg: rgba(255, 255, 255, 0.1);
|
--input-active-bg: rgba(255, 255, 255, 0.1);
|
||||||
|
|
||||||
--dropdown-menu-bg: rgb(24, 24, 24);
|
--dropdown-menu-bg: rgb(24, 24, 24);
|
||||||
--dropdown-menu-fg: rgb(193, 194, 197);
|
--dropdown-menu-fg: rgb(220, 220, 220);
|
||||||
--dropdown-menu-bg-hover: rgb(37, 38, 43);
|
--dropdown-menu-bg-hover: rgb(37, 38, 43);
|
||||||
--dropdown-menu-border: 1px rgba(50, 50, 50, 0.7) solid;
|
--dropdown-menu-border: 1px rgba(50, 50, 50, 0.7) solid;
|
||||||
--dropdown-menu-border-radius: 4px;
|
--dropdown-menu-border-radius: 4px;
|
||||||
@@ -133,5 +134,14 @@
|
|||||||
|
|
||||||
.mantine-Modal-modal {
|
.mantine-Modal-modal {
|
||||||
background: var(--modal-bg);
|
background: var(--modal-bg);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mantine-Modal-header {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: medium;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
border-bottom: 1px solid var(--generic-border-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
body[data-theme='defaultLight'] {
|
body[data-theme='defaultLight'] {
|
||||||
--primary-color: rgb(117, 172, 255);
|
--primary-color: rgb(79, 149, 255);
|
||||||
--icon-color: #ffffff;
|
--icon-color: #ffffff;
|
||||||
|
|
||||||
--main-bg: rgb(255, 255, 255);
|
--main-bg: rgb(255, 255, 255);
|
||||||
|
|||||||
Reference in New Issue
Block a user