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:
parent
b551fc44ea
commit
d757b74fd0
9 changed files with 6 additions and 210 deletions
|
@ -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 };
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue