Files
Homarr/src/components/Dashboard/Tiles/Apps/AppTile.tsx

136 lines
3.7 KiB
TypeScript
Raw Normal View History

import { Affix, Box, Text, Tooltip, UnstyledButton } from '@mantine/core';
import { createStyles, useMantineTheme } from '@mantine/styles';
2023-01-02 02:52:12 +09:00
import { motion } from 'framer-motion';
2023-01-23 01:34:36 +09:00
import Link from 'next/link';
2023-07-21 18:08:40 +09:00
import { AppType } from '../../../../types/app';
2022-12-04 19:10:07 +01:00
import { useEditModeStore } from '../../Views/useEditModeStore';
2022-12-11 15:04:05 +01:00
import { HomarrCardWrapper } from '../HomarrCardWrapper';
2022-12-04 17:36:30 +01:00
import { BaseTileProps } from '../type';
import { AppMenu } from './AppMenu';
import { AppPing } from './AppPing';
2022-12-04 17:36:30 +01:00
interface AppTileProps extends BaseTileProps {
app: AppType;
2022-12-04 17:36:30 +01:00
}
export const AppTile = ({ className, app }: AppTileProps) => {
2022-12-04 17:36:30 +01:00
const isEditMode = useEditModeStore((x) => x.enabled);
const { cx, classes } = useStyles();
const { colorScheme } = useMantineTheme();
const tooltipContent = [
app.appearance.appNameStatus === 'hover' ? app.name : undefined,
app.behaviour.tooltipDescription,
]
.filter((e) => e)
.join(': ');
const isRow = app.appearance.positionAppName.includes('row');
2022-12-04 17:36:30 +01:00
2023-01-03 22:32:00 +09:00
function Inner() {
return (
<Tooltip.Floating
label={tooltipContent}
position="right-start"
c={colorScheme === 'light' ? 'black' : 'dark.0'}
color={colorScheme === 'light' ? 'gray.2' : 'dark.4'}
multiline
disabled={!tooltipContent}
styles={{ tooltip: { maxWidth: 300 } }}
>
<Box
className={`${classes.base} ${cx(classes.appContent, 'dashboard-tile-app')}`}
h="100%"
sx={{
flexFlow: app.appearance.positionAppName ?? 'column',
}}
>
{app.appearance.appNameStatus === 'normal' && (
<Text
className={cx(classes.appName, 'dashboard-tile-app-title')}
fw={700}
size="md"
ta="center"
sx={{
flex: isRow ? '1' : undefined,
}}
lineClamp={app.appearance.lineClampAppName}
>
{app.name}
</Text>
)}
<motion.img
className={cx(classes.appImage, 'dashboard-tile-app-image')}
src={app.appearance.iconUrl}
alt={app.name}
whileHover={{ scale: 1 }}
initial={{ scale: 0.9 }}
style={{
width: isRow ? 0 : undefined,
}}
/>
</Box>
</Tooltip.Floating>
2023-01-03 22:32:00 +09:00
);
}
2022-12-04 17:36:30 +01:00
return (
<HomarrCardWrapper className={className} p={10}>
<AppMenu app={app} />
{!app.url || isEditMode ? (
2022-12-04 17:36:30 +01:00
<UnstyledButton
className={`${classes.button} ${classes.base}`}
2022-12-04 17:36:30 +01:00
style={{ pointerEvents: isEditMode ? 'none' : 'auto' }}
>
2023-01-03 22:32:00 +09:00
<Inner />
2022-12-04 17:36:30 +01:00
</UnstyledButton>
) : (
<UnstyledButton
style={{ pointerEvents: isEditMode ? 'none' : 'auto' }}
2023-01-23 01:34:36 +09:00
component={Link}
2022-12-30 16:58:05 +01:00
href={app.behaviour.externalUrl.length > 0 ? app.behaviour.externalUrl : app.url}
target={app.behaviour.isOpeningNewTab ? '_blank' : '_self'}
className={`${classes.button} ${classes.base}`}
2022-12-04 17:36:30 +01:00
>
2023-01-03 22:32:00 +09:00
<Inner />
2022-12-04 17:36:30 +01:00
</UnstyledButton>
)}
<AppPing app={app} />
2022-12-11 15:04:05 +01:00
</HomarrCardWrapper>
2022-12-04 17:36:30 +01:00
);
};
2022-12-11 00:00:11 +01:00
const useStyles = createStyles((theme, _params, getRef) => ({
base: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
appContent: {
gap: 0,
overflow: 'visible',
flexGrow: 5,
2022-12-11 00:00:11 +01:00
},
appName: {
2023-01-20 12:57:45 +09:00
wordBreak: 'break-word',
2022-12-11 00:00:11 +01:00
},
appImage: {
flex: '1',
objectFit: 'contain',
overflowY: 'auto',
},
2022-12-11 00:00:11 +01:00
button: {
height: '100%',
width: '100%',
gap: 4,
},
}));
export const appTileDefinition = {
component: AppTile,
2023-01-03 22:32:00 +09:00
minWidth: 1,
minHeight: 1,
maxWidth: 12,
maxHeight: 12,
};