diff --git a/src/components/node/_obsolete/ImageSwitcher/index.tsx b/src/components/node/_obsolete/ImageSwitcher/index.tsx deleted file mode 100644 index 32c03ea3..00000000 --- a/src/components/node/_obsolete/ImageSwitcher/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { FC } from 'react'; -import range from 'ramda/es/range'; -import classNames from 'classnames'; - -import styles from './styles.module.scss'; - -interface IProps { - total: number; - current: number; - loaded?: Record; - onChange: (current: number) => void; -} - -const ImageSwitcher: FC = ({ total, current, onChange, loaded }) => { - if (total <= 1) return null; - - return ( -
-
- {range(0, total).map(item => ( -
onChange(item)} - /> - ))} -
-
- ); -}; - -export { ImageSwitcher }; diff --git a/src/components/node/_obsolete/ImageSwitcher/styles.module.scss b/src/components/node/_obsolete/ImageSwitcher/styles.module.scss deleted file mode 100644 index b1e64a6e..00000000 --- a/src/components/node/_obsolete/ImageSwitcher/styles.module.scss +++ /dev/null @@ -1,56 +0,0 @@ -@import "src/styles/variables"; - -.wrap { - width: 100%; - height: 0; - position: relative; - z-index: 4; -} - -.switcher { - position: absolute; - // background: darken($content_bg, 2%); - background: url('../../../../src/sprites/noise.png') $main_bg_color; - display: flex; - left: 50%; - transform: translate(-50%, 0); - top: -60px; - border-radius: 24px; - padding: 0 3px; - // flex-wrap: wrap; - transition: background-color 0.5s; - transform: translate(-50%, 0); - - & > div { - width: 30px; - height: 30px; - box-sizing: border-box; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - transition: opacity 0.25s; - opacity: 0.5; - - &::after { - content: ' '; - display: block; - width: 14px; - height: 14px; - border-radius: 8px; - box-shadow: inset white 0 0 0 2px; - transform: scale(0.5); - transition: transform 0.5s; - } - - &:global(.is_active) { - &::after { - background: white; - } - } - - &:global(.is_loaded)::after { - transform: scale(1); - } - } -} diff --git a/src/components/node/_obsolete/NodeImageBlock/index.tsx b/src/components/node/_obsolete/NodeImageBlock/index.tsx deleted file mode 100644 index d3875ffc..00000000 --- a/src/components/node/_obsolete/NodeImageBlock/index.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import React, { FC, useMemo, useState, useEffect, useRef, useCallback } from 'react'; -import { ImageSwitcher } from '../ImageSwitcher'; -import styles from './styles.module.scss'; -import { INode } from '~/redux/types'; -import classNames from 'classnames'; -import { getURL } from '~/utils/dom'; -import { UPLOAD_TYPES } from '~/redux/uploads/constants'; -import { PRESETS } from '~/constants/urls'; -import * as MODAL_ACTIONS from '~/redux/modal/actions'; -import { LoaderCircle } from '~/components/input/LoaderCircle'; - -interface IProps { - is_loading: boolean; - node: INode; - layout: {}; - updateLayout: () => void; - modalShowPhotoswipe: typeof MODAL_ACTIONS.modalShowPhotoswipe; -} - -const NodeImageBlock: FC = ({ node, is_loading, updateLayout, modalShowPhotoswipe }) => { - const [is_animated, setIsAnimated] = useState(false); - const [current, setCurrent] = useState(0); - const [height, setHeight] = useState(window.innerHeight - 150); - const [loaded, setLoaded] = useState>({}); - const refs = useRef>({}); - - const images = useMemo( - () => - (node && node.files && node.files.filter(({ type }) => type === UPLOAD_TYPES.IMAGE)) || [], - [node] - ); - - const setRef = useCallback(index => el => (refs.current[index] = el), [refs]); - - const onImageLoad = useCallback(index => () => setLoaded({ ...loaded, [index]: true }), [ - setLoaded, - loaded, - ]); - - useEffect(() => updateLayout(), [loaded]); - - useEffect(() => { - if (!refs || !refs.current[current] || !loaded[current]) - return setHeight(window.innerHeight - 150); - - const el = refs.current[current]; - const element_height = el.getBoundingClientRect && el.getBoundingClientRect().height; - - setHeight(element_height); - }, [refs, current, loaded]); - - useEffect(() => { - const timer = setTimeout(() => setIsAnimated(true), 250); - return () => clearTimeout(timer); - }, []); - - const onOpenPhotoSwipe = useCallback(() => modalShowPhotoswipe(images, current), [ - modalShowPhotoswipe, - images, - current, - ]); - - return ( -
-
- {(is_loading || !loaded[0] || !images.length) && ( -
- -
- )} - - {images.map((file, index) => ( -
- -
- ))} -
- - -
- ); -}; - -export { NodeImageBlock }; diff --git a/src/components/node/_obsolete/NodeImageBlock/styles.module.scss b/src/components/node/_obsolete/NodeImageBlock/styles.module.scss deleted file mode 100644 index 7cd09f4a..00000000 --- a/src/components/node/_obsolete/NodeImageBlock/styles.module.scss +++ /dev/null @@ -1,62 +0,0 @@ -@import "src/styles/variables"; - -.wrap { - padding-bottom: $gap * 2; - - &:global(.is_animated) { - .image_container { - transition: height 0.5s; - } - - .image_wrap { - transition: opacity 0.5s; - } - } -} - -.image_container { - width: 100%; - border-radius: $panel_radius 0 0 $panel_radius; - display: flex; - align-items: center; - justify-content: center; - position: relative; - overflow: hidden; - user-select: none; - - .image { - max-height: calc(100vh - 150px); - max-width: 100%; - opacity: 1; - border-radius: $radius; - - @include outer_shadow(); - } -} - -.image_wrap { - width: 100%; - position: absolute; - top: 0; - left: 0; - opacity: 0; - pointer-events: none; - touch-action: none; - z-index: 1; - display: flex; - align-items: center; - justify-content: center; - - &:global(.is_active) { - opacity: 1; - } -} - -.placeholder { - width: 100%; - height: calc(100vh - 130px); - border-radius: $radius; - display: flex; - align-items: center; - justify-content: center; -} diff --git a/src/components/node/_obsolete/NodeImageSlideBlock/index.tsx b/src/components/node/_obsolete/NodeImageSlideBlock/index.tsx deleted file mode 100644 index 746dde08..00000000 --- a/src/components/node/_obsolete/NodeImageSlideBlock/index.tsx +++ /dev/null @@ -1,345 +0,0 @@ -import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import styles from './styles.module.scss'; -import classNames from 'classnames'; -import { UPLOAD_TYPES } from '~/redux/uploads/constants'; -import { INodeComponentProps } from '~/redux/node/constants'; -import { getURL } from '~/utils/dom'; -import { PRESETS } from '~/constants/urls'; -import { throttle } from 'throttle-debounce'; -import { Icon } from '~/components/input/Icon'; -import { useArrows } from '~/utils/hooks/keys'; -import { useDispatch } from 'react-redux'; -import { modalShowPhotoswipe } from '~/redux/modal/actions'; -import { useShallowSelect } from '~/utils/hooks/useShallowSelect'; -import { selectModal } from '~/redux/modal/selectors'; - -interface IProps extends INodeComponentProps { - updateLayout?: () => void; -} - -const getX = event => - (event.touches && event.touches.length) || (event.changedTouches && event.changedTouches.length) - ? (event.touches.length && event.touches[0].clientX) || event.changedTouches[0].clientX - : event.clientX; - -const NodeImageSlideBlock: FC = ({ node, isLoading, updateLayout = () => {} }) => { - const dispatch = useDispatch(); - const { is_shown } = useShallowSelect(selectModal); - - const [current, setCurrent] = useState(0); - const [height, setHeight] = useState(window.innerHeight - 143); - const [max_height, setMaxHeight] = useState(960); - const [loaded, setLoaded] = useState>({}); - const refs = useRef>({}); - const [heights, setHeights] = useState({}); - - const [initial_offset, setInitialOffset] = useState(0); - const [initial_x, setInitialX] = useState(0); - const [offset, setOffset] = useState(0); - const [is_dragging, setIsDragging] = useState(false); - const [drag_start, setDragStart] = useState(0); - - const slide = useRef(null); - const wrap = useRef(null); - - const setHeightThrottled = useCallback(throttle(100, setHeight), [setHeight]); - - const images = useMemo( - () => - (node && node.files && node.files.filter(({ type }) => type === UPLOAD_TYPES.IMAGE)) || [], - [node.files] - ); - - useEffect(() => { - setLoaded({}); - refs.current = {}; - }, [images]); - - const updateSizes = useCallback(() => { - const values = Object.keys(refs.current).reduce((obj, key) => { - const ref = refs.current[key]; - - if (!ref || !ref.getBoundingClientRect) return 0; - - return { ...obj, [key]: ref.getBoundingClientRect().height }; - }, {}); - - setHeights(values); - }, [refs]); - - const setRef = useCallback( - index => el => { - refs.current[index] = el; - }, - [refs, heights, setHeights, images] - ); - - const onImageLoad = useCallback(index => () => setLoaded({ ...loaded, [index]: true }), [ - setLoaded, - loaded, - ]); - - // update outside hooks - useEffect(updateLayout, [loaded, height, images]); - useEffect(updateSizes, [refs, current, loaded, images]); - - useEffect(() => { - const timeout = setTimeout(updateLayout, 300); - - if (!wrap || !wrap.current) return () => clearTimeout(timeout); - - const { width } = wrap.current.getBoundingClientRect(); - const fallback = window.innerHeight - 143; - - if (isLoading) { - setHeight(fallback); - return () => clearTimeout(timeout); - } - - const selected = Math.abs(-offset / width); - - if (!heights[Math.round(selected)]) { - setHeight(fallback); - return () => clearTimeout(timeout); - } - - const minimal = Math.min(fallback, 120); - - const prev = Math.max(heights[Math.floor(selected)] || fallback, minimal); - const next = Math.max(heights[Math.ceil(selected)] || fallback, minimal); - const now = prev - (prev - next) * (selected % 1); - - if (current !== Math.round(selected)) setCurrent(Math.round(selected)); - - if (!is_dragging) { - setHeight(now); - } else { - setHeightThrottled(now); - } - - // update layout after all manipulations - return () => { - if (timeout) clearTimeout(timeout); - }; - }, [is_dragging, wrap, offset, heights, max_height, images, isLoading, updateLayout]); - - const onDrag = useCallback( - event => { - if ( - !is_dragging || - !slide.current || - !wrap.current || - (event.touches && event.clientY > event.clientX) - ) - return; - - const { width: slide_width } = slide.current.getBoundingClientRect(); - const { width: wrap_width } = wrap.current.getBoundingClientRect(); - - setOffset( - Math.min(Math.max(initial_offset + getX(event) - initial_x, wrap_width - slide_width), 0) - ); - }, - [is_dragging, initial_x, setOffset, initial_offset] - ); - - const normalizeOffset = useCallback(() => { - if (!slide.current || !wrap.current) return; - - const { width: wrap_width } = wrap.current.getBoundingClientRect(); - const { width: slide_width } = slide.current.getBoundingClientRect(); - - const shift = (initial_offset - offset) / wrap_width; // percent / 100 - const diff = initial_offset - (shift > 0 ? Math.ceil(shift) : Math.floor(shift)) * wrap_width; - const new_offset = - Math.abs(shift) > 0.25 - ? Math.min(Math.max(diff, wrap_width - slide_width), 0) // next or prev slide - : Math.round(offset / wrap_width) * wrap_width; // back to this one - - setOffset(new_offset); - }, [wrap, offset, initial_offset]); - - const updateMaxHeight = useCallback(() => { - if (!wrap.current) return; - setMaxHeight(window.innerHeight - 143); - normalizeOffset(); - }, [wrap, setMaxHeight, normalizeOffset]); - - const onOpenPhotoSwipe = useCallback(() => dispatch(modalShowPhotoswipe(images, current)), [ - dispatch, - images, - current, - ]); - - const stopDragging = useCallback( - event => { - if (!is_dragging) return; - - setIsDragging(false); - normalizeOffset(); - - if ( - Math.abs(new Date().getTime() - drag_start) < 200 && - Math.abs(initial_x - getX(event)) < 5 - ) { - onOpenPhotoSwipe(); - } - }, - [setIsDragging, is_dragging, normalizeOffset, onOpenPhotoSwipe, drag_start] - ); - - const startDragging = useCallback( - event => { - setIsDragging(true); - setInitialX(getX(event)); - setInitialOffset(offset); - setDragStart(new Date().getTime()); - }, - [setIsDragging, setInitialX, offset, setInitialOffset, setDragStart] - ); - - useEffect(() => updateMaxHeight(), [images]); - - useEffect(() => { - window.addEventListener('resize', updateSizes); - window.addEventListener('resize', updateMaxHeight); - - window.addEventListener('mousemove', onDrag); - window.addEventListener('touchmove', onDrag); - - window.addEventListener('mouseup', stopDragging); - window.addEventListener('touchend', stopDragging); - - return () => { - window.removeEventListener('resize', updateSizes); - window.removeEventListener('resize', updateMaxHeight); - - window.removeEventListener('mousemove', onDrag); - window.removeEventListener('touchmove', onDrag); - - window.removeEventListener('mouseup', stopDragging); - window.removeEventListener('touchend', stopDragging); - }; - }, [onDrag, stopDragging, updateMaxHeight, updateSizes]); - - const changeCurrent = useCallback( - (item: number) => { - if (!wrap.current) return; - - const { width } = wrap.current.getBoundingClientRect(); - setOffset(-1 * item * width); - }, - [wrap] - ); - - const onPrev = useCallback(() => changeCurrent(current > 0 ? current - 1 : images.length - 1), [ - changeCurrent, - current, - images, - ]); - - const onNext = useCallback(() => changeCurrent(current < images.length - 1 ? current + 1 : 0), [ - changeCurrent, - current, - images, - ]); - - useArrows(onNext, onPrev, is_shown); - - useEffect(() => { - setOffset(0); - }, [node.id]); - - return ( -
-
-
- {!isLoading && - images.map((file, index) => ( -
- - - - - - - - - - - - - -
- ))} -
- - {images.length > 1 && ( -
- {current + 1} - / - {images.length} -
- )} -
- - {images.length > 1 && ( -
- -
- )} - - {images.length > 1 && ( -
- -
- )} -
- ); -}; - -export { NodeImageSlideBlock }; diff --git a/src/components/node/_obsolete/NodeImageSlideBlock/styles.module.scss b/src/components/node/_obsolete/NodeImageSlideBlock/styles.module.scss deleted file mode 100644 index c779655a..00000000 --- a/src/components/node/_obsolete/NodeImageSlideBlock/styles.module.scss +++ /dev/null @@ -1,187 +0,0 @@ -@import "src/styles/variables"; - -.wrap { - position: relative; -} - -.cutter { - overflow: hidden; - position: relative; - min-width: 0; - transition: height 0.25s; - border-radius: $radius; - margin-right: -$gap / 2; - margin-left: -$gap / 2; - - .is_loading { - .placeholder { - opacity: 1; - } - } - - @include tablet { - margin-left: 0; - margin-right: 0; - border-radius: 0; - } -} - -.image_container { - display: flex; - align-items: flex-start; - justify-content: flex-start; - position: relative; - overflow: hidden; - user-select: none; - will-change: transform, height; - transition: height 500ms, transform 500ms; - padding: 0 0 20px 0; - - &:active { - transition: none; - } - - &.is_dragging { - transition: none; - } -} - -.image_wrap { - width: 100%; - pointer-events: none; - touch-action: none; - z-index: 1; - display: flex; - align-items: center; - justify-content: center; - padding: 0 $gap / 2; - position: relative; - - &.is_active { - opacity: 1; - } - - @include tablet { - padding: 0; - } -} - -.image_count { - position: absolute; - color: transparentize(white, 0.5); - bottom: $gap * 3; - right: 50%; - padding: $gap / 3 $gap; - border-radius: 20px; - background: $content_bg; - font: $font_12_semibold; - transform: translate(50%, 0); - display: flex; - align-items: center; - justify-content: center; - user-select: none; - - small { - font-size: 0.8em; - padding: 0 3px; - } -} - -.image_arrow { - position: absolute; - left: -$gap; - top: 50%; - width: 40px; - height: 64px; - border-radius: $radius; - display: flex; - align-items: center; - justify-content: center; - transform: translate(-100%, -50%); - cursor: pointer; - opacity: 0.7; - transition: opacity 0.5s; - - &:hover { - opacity: 1; - } - - &_right { - right: -$gap; - left: auto; - transform: translate(100%, -50%); - } - - @media (max-width: $content_width + 80px + 40px) { - background: $content_bg; - left: 0; - transform: translate(0, -50%); - border-radius: 0 $radius $radius 0; - - &_right { - right: 0; - left: auto; - border-radius: $radius 0 0 $radius; - } - } - - @include tablet { - display: none; - } - - svg { - position: relative; - left: -2px; - } -} - -.placeholder { - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; - background: $content_bg; - pointer-events: none; - touch-action: none; - transition: opacity 2s; - z-index: 2; - opacity: 0; - - &.is_loading { - opacity: 1; - } - - svg { - opacity: 0.025; - fill: white; - } -} - -.image, .preview { - max-width: 100%; - border-radius: $radius; - - @include tablet { - border-radius: 0; - } -} - -.image { - position: absolute; - opacity: 0; - - &.is_loaded { - opacity: 1; - position: static; - } -} - -.preview { - &.is_loaded { - display: none; - } -}