1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-24 20:36:40 +07:00

refactored media components

This commit is contained in:
Fedor Katurov 2023-11-21 19:34:22 +06:00
parent b551fc44ea
commit d757b74fd0
9 changed files with 6 additions and 210 deletions

View file

@ -1,135 +0,0 @@
import { FC, MouseEventHandler, useCallback, useMemo, useState } from 'react';
import classNames from 'classnames';
import { Icon } from '~/components/common/Icon';
import { ImageWithSSRLoad } from '~/components/common/ImageWithSSRLoad';
import { LoaderCircle } from '~/components/common/LoaderCircle';
import { DEFAULT_DOMINANT_COLOR } from '~/constants/node';
import { imagePresets } from '~/constants/urls';
import { useResizeHandler } from '~/hooks/dom/useResizeHandler';
import { IFile } from '~/types';
import { getURL } from '~/utils/dom';
import styles from './styles.module.scss';
interface IProps {
file: IFile;
color?: string;
onLoad?: () => void;
onClick?: MouseEventHandler;
className?: string;
}
const DEFAULT_WIDTH = 1920;
const DEFAULT_HEIGHT = 1020;
const ImagePreloader: FC<IProps> = ({
file,
color,
onLoad,
onClick,
className,
}) => {
const [maxHeight, setMaxHeight] = useState(0);
const [loaded, setLoaded] = useState(false);
const [hasError, setHasError] = useState(false);
const onImageLoad = useCallback(() => {
setLoaded(true);
setHasError(false);
if (onLoad) {
onLoad();
}
}, [setLoaded, onLoad]);
const onResize = useCallback(() => {
setMaxHeight(window.innerHeight - 140);
}, [setMaxHeight]);
const onError = useCallback(() => {
setHasError(true);
}, [setHasError]);
const [width, height] = useMemo(
() => [
file?.metadata?.width || DEFAULT_WIDTH,
file?.metadata?.height || DEFAULT_HEIGHT,
],
[file],
);
useResizeHandler(onResize);
const estimatedWidth = (width * maxHeight) / height;
const fill = color && color !== DEFAULT_DOMINANT_COLOR ? color : '#222222';
return (
<>
<svg
viewBox={`0 0 ${width} ${height}`}
className={classNames(styles.preview, { [styles.is_loaded]: loaded })}
style={{
maxHeight: maxHeight,
width: estimatedWidth,
}}
onClick={onClick}
>
<defs>
<filter id="f1" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation="30" />
</filter>
</defs>
<g filter="url(#f1)">
<rect
fill={fill}
width="100%"
height="100%"
stroke="none"
rx="8"
ry="8"
/>
{!hasError && (
<image
xlinkHref={getURL(file, imagePresets['300'])}
width="100%"
height="100%"
onLoad={onLoad}
/>
)}
</g>
</svg>
<ImageWithSSRLoad
className={classNames(
styles.image,
{ [styles.is_loaded]: loaded },
className,
)}
src={getURL(file, imagePresets['1600'])}
alt=""
key={file.id}
onLoad={onImageLoad}
style={{ maxHeight }}
onClick={onClick}
onError={onError}
/>
{!loaded && !hasError && (
<LoaderCircle className={styles.icon} size={64} />
)}
{hasError && (
<div className={styles.error}>
<div className={styles.error__text}>Не удалось получить картинку</div>
<Icon icon="warn" size={64} />
</div>
)}
</>
);
};
export { ImagePreloader };

View file

@ -1,67 +0,0 @@
@import 'src/styles/variables.scss';
img.image {
position: absolute;
opacity: 0;
width: 0;
height: 0;
&.is_loaded {
width: auto;
height: auto;
opacity: 1;
position: static;
}
}
.preview {
border-radius: $radius;
&.is_loaded {
display: none;
}
}
.icon {
position: absolute;
right: 30px;
bottom: 40px;
opacity: 0.4;
@include tablet {
right: 5px;
bottom: 5px;
}
svg {
fill: currentColor;
@include tablet {
transform: scale(0.6);
}
}
}
.error {
position: absolute;
right: 30px;
bottom: 40px;
opacity: 0.4;
color: $color_offline;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
svg {
fill: currentColor;
}
&__text {
max-width: 200px;
text-align: right;
margin-right: $gap;
font: $font_16_semibold;
line-height: 24px;
}
}

View file

@ -1,6 +1,6 @@
import { FC } from 'react';
import { AudioPlayer } from '~/components/media/AudioPlayer';
import { AudioPlayer } from '~/components/common/AudioPlayer';
import { NodeComponentProps } from '~/constants/node';
import { useNodeAudios } from '~/hooks/node/useNodeAudios';

View file

@ -20,17 +20,15 @@ const SettingsMenu: VFC<SettingsMenuProps> = () => (
<Group>
<VerticalMenu className={styles.menu}>
<Link href={URLS.SETTINGS.BASE} passHref>
<VerticalMenu.Item onClick={console.log}>Настройки</VerticalMenu.Item>
<VerticalMenu.Item>Настройки</VerticalMenu.Item>
</Link>
<Link href={URLS.SETTINGS.NOTES} passHref>
<VerticalMenu.Item onClick={console.log}>Заметки</VerticalMenu.Item>
<VerticalMenu.Item>Заметки</VerticalMenu.Item>
</Link>
<Link href={URLS.SETTINGS.TRASH} passHref>
<VerticalMenu.Item onClick={console.log}>
Удалённые посты
</VerticalMenu.Item>
<VerticalMenu.Item>Удалённые посты</VerticalMenu.Item>
</Link>
</VerticalMenu>

View file

@ -1,6 +1,6 @@
import { FC, useMemo } from 'react';
import { AudioPlayer } from '~/components/media/AudioPlayer';
import { AudioPlayer } from '~/components/common/AudioPlayer';
import { AudioUpload } from '~/components/upload/AudioUpload';
import { UploadStatus } from '~/store/uploader/UploaderStore';
import { IFile } from '~/types';

View file

@ -10,8 +10,8 @@ import {
import classnames from 'classnames';
import { AudioPlayer } from '~/components/common/AudioPlayer';
import { Group } from '~/components/common/Group';
import { AudioPlayer } from '~/components/media/AudioPlayer';
import { UploadType } from '~/constants/uploads';
import { IComment, IFile } from '~/types';
import { formatCommentText, getPrettyDate } from '~/utils/dom';