Files
Homarr/components/AppShelf/AppShelf.tsx

141 lines
3.7 KiB
TypeScript
Raw Normal View History

2022-04-25 23:33:32 +02:00
import React, { useEffect, useState } from 'react';
import { motion } from 'framer-motion';
2022-04-27 23:18:50 +02:00
import {
Text,
AspectRatio,
createStyles,
SimpleGrid,
2022-05-04 07:12:22 +02:00
Card,
useMantineTheme,
Image,
2022-05-04 07:49:29 +02:00
Group,
Space,
2022-04-27 23:18:50 +02:00
} from '@mantine/core';
2022-04-25 23:33:32 +02:00
import AppShelfMenu from './AppShelfMenu';
import AddItemShelfItem from './AddAppShelfItem';
import { useConfig } from '../../tools/state';
import { pingQbittorrent } from '../../tools/api';
import { serviceItem } from '../../tools/types';
2022-04-25 23:33:32 +02:00
2022-05-10 18:58:13 +02:00
export function AppShelfItemWrapper(props: any) {
const { children, hovering } = props;
const theme = useMantineTheme();
return (
<Card
style={{
boxShadow: hovering ? '0px 0px 3px rgba(0, 0, 0, 0.5)' : '0px 0px 1px rgba(0, 0, 0, 0.5)',
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[1],
//TODO: #3 Fix this temporary fix and make the width and height dynamic / responsive
width: 200,
height: 180,
}}
radius="md"
>
{children}
</Card>
);
}
2022-04-25 00:11:32 +02:00
2022-04-27 03:11:35 +02:00
const AppShelf = (props: any) => {
const { config, addService, removeService, setConfig } = useConfig();
2022-04-25 23:33:32 +02:00
/* A hook that is used to load the config from local storage. */
2022-04-25 23:33:32 +02:00
useEffect(() => {
const localConfig = localStorage.getItem('config');
if (localConfig) {
setConfig(JSON.parse(localConfig));
2022-04-25 23:33:32 +02:00
}
}, []);
if (config.services && config.services.length === 0) {
config.services.forEach((service) => {
if (service.type === 'qBittorrent') {
pingQbittorrent(service);
}
});
}
2022-04-25 23:33:32 +02:00
2022-04-25 00:11:32 +02:00
return (
<SimpleGrid m="xl" cols={5} spacing="xl">
{config.services.map((service, i) => (
2022-05-04 10:33:08 +02:00
<AppShelfItem key={service.name} service={service} />
2022-05-04 07:12:22 +02:00
))}
<AddItemShelfItem />
</SimpleGrid>
);
};
export function AppShelfItem(props: any) {
const { service }: { service: serviceItem } = props;
const theme = useMantineTheme();
const { removeService } = useConfig();
const [hovering, setHovering] = useState(false);
return (
<motion.div
2022-05-04 07:49:29 +02:00
key={service.name}
2022-05-04 07:12:22 +02:00
onHoverStart={(e) => {
setHovering(true);
}}
onHoverEnd={(e) => {
setHovering(false);
}}
>
2022-05-10 18:58:13 +02:00
<AppShelfItemWrapper hovering={hovering}>
2022-05-04 07:12:22 +02:00
<Card.Section>
2022-05-04 07:49:29 +02:00
<Group position="apart" mx="lg">
<Space />
<Text
// TODO: #1 Remove this hack to get the text to be centered.
ml={15}
style={{
alignSelf: 'center',
alignContent: 'center',
alignItems: 'center',
justifyContent: 'center',
justifyItems: 'center',
}}
mt="sm"
weight={500}
>
2022-05-04 07:12:22 +02:00
{service.name}
</Text>
2022-05-04 07:49:29 +02:00
<motion.div
style={{
alignSelf: 'flex-end',
}}
animate={{
opacity: hovering ? 1 : 0,
}}
>
<AppShelfMenu service={service} removeitem={removeService} />
2022-05-04 07:49:29 +02:00
</motion.div>
</Group>
2022-05-04 07:12:22 +02:00
</Card.Section>
<Card.Section>
<AspectRatio ratio={5 / 3} m="xl">
<motion.i
whileHover={{
cursor: 'pointer',
scale: 1.1,
}}
>
<Image
onClick={() => {
window.open(service.url);
}}
style={{
maxWidth: '50%',
marginBottom: 10,
}}
src={service.icon}
/>
</motion.i>
</AspectRatio>
</Card.Section>
2022-05-10 18:58:13 +02:00
</AppShelfItemWrapper>
2022-05-04 07:12:22 +02:00
</motion.div>
2022-04-25 00:11:32 +02:00
);
2022-05-04 07:12:22 +02:00
}
2022-04-25 00:11:32 +02:00
2022-04-27 03:11:35 +02:00
export default AppShelf;