diff --git a/src/components/node/NodeImageSlideBlock/index.tsx b/src/components/node/NodeImageSlideBlock/index.tsx index 14ef1fae..45b3f6aa 100644 --- a/src/components/node/NodeImageSlideBlock/index.tsx +++ b/src/components/node/NodeImageSlideBlock/index.tsx @@ -1,21 +1,14 @@ -import React, { - FC, - useMemo, - useState, - useEffect, - useRef, - useCallback -} from "react"; -import { ImageSwitcher } from "../ImageSwitcher"; -import * as styles from "./styles.scss"; -import { INode } from "~/redux/types"; -import classNames from "classnames"; -import { UPLOAD_TYPES } from "~/redux/uploads/constants"; -import { NODE_SETTINGS } from "~/redux/node/constants"; -import { getURL } from "~/utils/dom"; -import { PRESETS } from "~/constants/urls"; -import { LoaderCircle } from "~/components/input/LoaderCircle"; -import { throttle } from "throttle-debounce"; +import React, { FC, useMemo, useState, useEffect, useRef, useCallback } from 'react'; +import { ImageSwitcher } from '../ImageSwitcher'; +import * as styles from './styles.scss'; +import { INode } from '~/redux/types'; +import classNames from 'classnames'; +import { UPLOAD_TYPES } from '~/redux/uploads/constants'; +import { NODE_SETTINGS } from '~/redux/node/constants'; +import { getURL } from '~/utils/dom'; +import { PRESETS } from '~/constants/urls'; +import { LoaderCircle } from '~/components/input/LoaderCircle'; +import { throttle } from 'throttle-debounce'; interface IProps { is_loading: boolean; @@ -24,14 +17,9 @@ interface IProps { updateLayout: () => void; } -const getX = event => - event.touches ? event.touches[0].clientX : event.clientX; +const getX = event => (event.touches ? event.touches[0].clientX : event.clientX); -const NodeImageSlideBlock: FC = ({ - node, - is_loading, - updateLayout -}) => { +const NodeImageSlideBlock: FC = ({ node, is_loading, updateLayout }) => { const [current, setCurrent] = useState(0); const [height, setHeight] = useState(320); const [max_height, setMaxHeight] = useState(960); @@ -50,10 +38,7 @@ const NodeImageSlideBlock: FC = ({ const images = useMemo( () => - (node && - node.files && - node.files.filter(({ type }) => type === UPLOAD_TYPES.IMAGE)) || - [], + (node && node.files && node.files.filter(({ type }) => type === UPLOAD_TYPES.IMAGE)) || [], [node] ); @@ -81,26 +66,34 @@ const NodeImageSlideBlock: FC = ({ [refs, heights, setHeights, images] ); - const onImageLoad = useCallback( - index => () => setLoaded({ ...loaded, [index]: true }), - [setLoaded, loaded] - ); + 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(() => { - if (!wrap || !wrap.current) return; + const timeout = setTimeout(updateLayout, 300); + + if (!wrap || !wrap.current) return () => clearTimeout(timeout); const { width } = wrap.current.getBoundingClientRect(); const fallback = (width * 9) / 16; - if (is_loading) return setHeight(fallback); + if (is_loading) { + setHeight(fallback); + return () => clearTimeout(timeout); + } const selected = Math.abs(-offset / width); - if (!heights[Math.round(selected)]) return setHeight(fallback); + if (!heights[Math.round(selected)]) { + setHeight(fallback); + return () => clearTimeout(timeout); + } const prev = Math.max(heights[Math.floor(selected)] || fallback, fallback); const next = Math.max(heights[Math.ceil(selected)] || fallback, fallback); @@ -115,9 +108,8 @@ const NodeImageSlideBlock: FC = ({ } // update layout after all manipulations - const timeout = setTimeout(() => updateLayout(), 500); return () => clearTimeout(timeout); - }, [is_dragging, wrap, offset, heights, max_height, images, is_loading]); + }, [is_dragging, wrap, offset, heights, max_height, images, is_loading, updateLayout]); const onDrag = useCallback( event => { @@ -133,13 +125,7 @@ const NodeImageSlideBlock: FC = ({ const { width: wrap_width } = wrap.current.getBoundingClientRect(); setOffset( - Math.min( - Math.max( - initial_offset + getX(event) - initial_x, - wrap_width - slide_width - ), - 0 - ) + Math.min(Math.max(initial_offset + getX(event) - initial_x, wrap_width - slide_width), 0) ); }, [is_dragging, initial_x, setOffset, initial_offset] @@ -152,9 +138,7 @@ const NodeImageSlideBlock: FC = ({ 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 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 @@ -189,24 +173,24 @@ const NodeImageSlideBlock: FC = ({ useEffect(() => updateMaxHeight(), [images]); useEffect(() => { - window.addEventListener("resize", updateSizes); - window.addEventListener("resize", updateMaxHeight); + window.addEventListener('resize', updateSizes); + window.addEventListener('resize', updateMaxHeight); - window.addEventListener("mousemove", onDrag); - window.addEventListener("touchmove", onDrag); + window.addEventListener('mousemove', onDrag); + window.addEventListener('touchmove', onDrag); - window.addEventListener("mouseup", stopDragging); - window.addEventListener("touchend", stopDragging); + window.addEventListener('mouseup', stopDragging); + window.addEventListener('touchend', stopDragging); return () => { - window.removeEventListener("resize", updateSizes); - window.removeEventListener("resize", updateMaxHeight); + window.removeEventListener('resize', updateSizes); + window.removeEventListener('resize', updateMaxHeight); - window.removeEventListener("mousemove", onDrag); - window.removeEventListener("touchmove", onDrag); + window.removeEventListener('mousemove', onDrag); + window.removeEventListener('touchmove', onDrag); - window.removeEventListener("mouseup", stopDragging); - window.removeEventListener("touchend", stopDragging); + window.removeEventListener('mouseup', stopDragging); + window.removeEventListener('touchend', stopDragging); }; }, [onDrag, stopDragging, updateMaxHeight, updateSizes]); @@ -219,13 +203,10 @@ const NodeImageSlideBlock: FC = ({ ); return ( -
+
@@ -247,7 +228,7 @@ const NodeImageSlideBlock: FC = ({ style={{ height, transform: `translate(${offset}px, 0)`, - width: `${images.length * 100}%` + width: `${images.length * 100}%`, }} onMouseDown={startDragging} onTouchStart={startDragging} @@ -257,14 +238,14 @@ const NodeImageSlideBlock: FC = ({ images.map((file, index) => (
; @@ -28,40 +21,29 @@ interface IProps { } const NodePanel: FC = memo( - ({ - node, - layout, - can_edit, - can_like, - can_star, - is_loading, - onEdit, - onLike, - onStar - }) => { + ({ node, layout, can_edit, can_like, can_star, is_loading, onEdit, onLike, onStar }) => { const [stack, setStack] = useState(false); const ref = useRef(null); const getPlace = useCallback(() => { if (!ref.current) return; - const { offsetTop } = ref.current; - const { height } = ref.current.getBoundingClientRect(); - const { scrollY, innerHeight } = window; + const { bottom } = ref.current.getBoundingClientRect(); - setStack(offsetTop > scrollY + innerHeight - height); + setStack(bottom > window.innerHeight); }, [ref]); + useEffect(() => getPlace(), [layout]); + useEffect(() => { - getPlace(); - window.addEventListener("scroll", getPlace); - window.addEventListener("resize", getPlace); + window.addEventListener('scroll', getPlace); + window.addEventListener('resize', getPlace); return () => { - window.removeEventListener("scroll", getPlace); - window.removeEventListener("resize", getPlace); + window.removeEventListener('scroll', getPlace); + window.removeEventListener('resize', getPlace); }; - }, [layout]); + }, [layout, getPlace]); return (
diff --git a/src/components/node/NodePanelInner/styles.scss b/src/components/node/NodePanelInner/styles.scss index 3e1790b3..f78b67a4 100644 --- a/src/components/node/NodePanelInner/styles.scss +++ b/src/components/node/NodePanelInner/styles.scss @@ -14,6 +14,10 @@ padding: 0 $gap; bottom: 0; position: fixed; + + @include tablet { + padding: 0; + } } } @@ -27,7 +31,17 @@ padding: $gap; background: $node_bg; height: 72px; + @include outer_shadow(); + + @include tablet { + border-radius: 0; + } + + @include can_backdrop { + backdrop-filter: blur(15px); + background: transparentize($node_bg, 0.2); + } } .title {