From e6273f374d8c920b9f210fa6c6319d2cfd7c0c5f Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 22:59:16 +0500 Subject: [PATCH 01/16] Web:Common:Components:MediaViewer:StyledComponents: Added component ControlBtn --- .../StyledComponents/ControlBtn.tsx | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 packages/common/components/MediaViewer/StyledComponents/ControlBtn.tsx diff --git a/packages/common/components/MediaViewer/StyledComponents/ControlBtn.tsx b/packages/common/components/MediaViewer/StyledComponents/ControlBtn.tsx new file mode 100644 index 0000000000..6371b50ad0 --- /dev/null +++ b/packages/common/components/MediaViewer/StyledComponents/ControlBtn.tsx @@ -0,0 +1,22 @@ +import styled from "styled-components"; +import { Base } from "@docspace/components/themes"; + +const ControlBtn = styled.div` + display: inline-block; + height: 30px; + line-height: 25px; + margin: 5px; + width: 40px; + border-radius: 2px; + cursor: pointer; + text-align: center; + + &:hover { + background-color: ${(props) => + props.theme.mediaViewer.controlBtn.backgroundColor}; + } +`; + +ControlBtn.defaultProps = { theme: Base }; + +export default ControlBtn; From 3b17f4b55f54e0b91187392cb4333a6b2787f7d5 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:00:47 +0500 Subject: [PATCH 02/16] Web:Common:Components:MediaViewer:StyledComponents: Added component StyledButtonScroll --- .../StyledComponents/StyledButtonScroll.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 packages/common/components/MediaViewer/StyledComponents/StyledButtonScroll.tsx diff --git a/packages/common/components/MediaViewer/StyledComponents/StyledButtonScroll.tsx b/packages/common/components/MediaViewer/StyledComponents/StyledButtonScroll.tsx new file mode 100644 index 0000000000..eb69648058 --- /dev/null +++ b/packages/common/components/MediaViewer/StyledComponents/StyledButtonScroll.tsx @@ -0,0 +1,15 @@ +import styled from "styled-components"; + +type StyledButtonScrollProps = { + orientation: "left" | "right"; +}; + +const StyledButtonScroll = styled.div` + z-index: 307; + position: fixed; + top: calc(50% - 20px); + + ${(props) => (props.orientation === "left" ? "left: 20px;" : "right: 20px;")} +`; + +export default StyledButtonScroll; From f34f49d5700d60e8b2846e8f3c1b051f77f7e420 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:01:59 +0500 Subject: [PATCH 03/16] Web:Common:Components:MediaViewer:StyledComponents: Added component StyledMobileDetails --- .../StyledComponents/StyledMobileDetails.tsx | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 packages/common/components/MediaViewer/StyledComponents/StyledMobileDetails.tsx diff --git a/packages/common/components/MediaViewer/StyledComponents/StyledMobileDetails.tsx b/packages/common/components/MediaViewer/StyledComponents/StyledMobileDetails.tsx new file mode 100644 index 0000000000..0636947d7d --- /dev/null +++ b/packages/common/components/MediaViewer/StyledComponents/StyledMobileDetails.tsx @@ -0,0 +1,47 @@ +import styled from "styled-components"; + +const StyledMobileDetails = styled.div` + z-index: 307; + position: fixed; + top: 0; + left: 0; + right: 0; + height: 53px; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient( + 0deg, + rgba(0, 0, 0, 0) 0%, + rgba(0, 0, 0, 0.8) 100% + ); + + svg { + path { + fill: #fff; + } + } + + .mobile-close { + position: fixed; + left: 21px; + top: 22px; + } + + .mobile-context { + position: fixed; + right: 22px; + top: 22px; + } + + .title { + font-weight: 600; + margin-top: 6px; + width: calc(100% - 100px); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +`; + +export default StyledMobileDetails; From 78c159387ce01fe63ae0ad77ced3e4cd4904d59e Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:02:41 +0500 Subject: [PATCH 04/16] Web:Common:Components:MediaViewer:StyledComponents: Added component StyledSwitchToolbar --- .../StyledComponents/StyledSwitchToolbar.tsx | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 packages/common/components/MediaViewer/StyledComponents/StyledSwitchToolbar.tsx diff --git a/packages/common/components/MediaViewer/StyledComponents/StyledSwitchToolbar.tsx b/packages/common/components/MediaViewer/StyledComponents/StyledSwitchToolbar.tsx new file mode 100644 index 0000000000..68ec441308 --- /dev/null +++ b/packages/common/components/MediaViewer/StyledComponents/StyledSwitchToolbar.tsx @@ -0,0 +1,23 @@ +import styled from "styled-components"; + +type StyledSwitchToolbarProps = { + left?: boolean; +}; + +const StyledSwitchToolbar = styled.div` + height: 100%; + z-index: 306; + position: fixed; + width: 73px; + background: inherit; + display: block; + opacity: 0; + transition: all 0.3s; + ${(props) => (props.left ? "left: 0" : "right: 0")}; + &:hover { + cursor: pointer; + opacity: 1; + } +`; + +export default StyledSwitchToolbar; From d9da80902f74d028fbe9575c6317eaecad53cd3f Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:03:19 +0500 Subject: [PATCH 05/16] Web:Common:Components:MediaViewer:StyledComponents: Added component StyledViewerContainer --- .../StyledViewerContainer.tsx | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 packages/common/components/MediaViewer/StyledComponents/StyledViewerContainer.tsx diff --git a/packages/common/components/MediaViewer/StyledComponents/StyledViewerContainer.tsx b/packages/common/components/MediaViewer/StyledComponents/StyledViewerContainer.tsx new file mode 100644 index 0000000000..307d9a4065 --- /dev/null +++ b/packages/common/components/MediaViewer/StyledComponents/StyledViewerContainer.tsx @@ -0,0 +1,84 @@ +import styled from "styled-components"; +import { Base } from "@docspace/components/themes"; + +type StyledViewerContainerProps = { + visible: boolean; +}; + +const StyledViewerContainer = styled.div` + color: ${(props) => props.theme.mediaViewer.color}; + display: ${(props) => (props.visible ? "block" : "none")}; + overflow: hidden; + span { + position: fixed; + right: 0; + bottom: 5px; + margin-right: 10px; + z-index: 305; + } + .deleteBtnContainer, + .downloadBtnContainer { + display: block; + width: 16px; + height: 16px; + margin: 4px 12px; + line-height: 19px; + svg { + path { + fill: ${(props) => props.theme.mediaViewer.fill}; + } + } + } + .details { + z-index: 307; + padding-top: 21px; + height: 64px; + width: 100%; + background: linear-gradient( + 0deg, + rgba(0, 0, 0, 0) 0%, + rgba(0, 0, 0, 0.8) 100% + ); + position: fixed; + top: 0; + left: 0; + .title { + text-align: center; + white-space: nowrap; + overflow: hidden; + font-size: 20px; + font-weight: 600; + text-overflow: ellipsis; + width: calc(100% - 50px); + padding-left: 16px; + box-sizing: border-box; + color: ${(props) => props.theme.mediaViewer.titleColor}; + } + } + .mediaPlayerClose { + position: fixed; + top: 13px; + right: 12px; + height: 17px; + &:hover { + background-color: transparent; + } + svg { + path { + fill: ${(props) => props.theme.mediaViewer.iconColor}; + } + } + } + + .containerVideo { + position: fixed; + top: 0; + bottom: 0; + right: 0; + left: 0; + } +`; + +StyledViewerContainer.defaultProps = { theme: Base }; + +export default StyledViewerContainer; From 0792f45aef0012888dc4207ea46c7bc1206d2510 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:05:31 +0500 Subject: [PATCH 06/16] Web:Common:Components:MediaViewer:StyledComponents: Added entry point index.ts --- .../common/components/MediaViewer/StyledComponents/index.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/common/components/MediaViewer/StyledComponents/index.ts diff --git a/packages/common/components/MediaViewer/StyledComponents/index.ts b/packages/common/components/MediaViewer/StyledComponents/index.ts new file mode 100644 index 0000000000..5af2e602f7 --- /dev/null +++ b/packages/common/components/MediaViewer/StyledComponents/index.ts @@ -0,0 +1,5 @@ +export { default as ControlBtn } from "./ControlBtn"; +export { default as StyledButtonScroll } from "./StyledButtonScroll"; +export { default as StyledSwitchToolbar } from "./StyledSwitchToolbar"; +export { default as StyledViewerContainer } from "./StyledViewerContainer"; +export { default as StyledMobileDetails } from "./StyledMobileDetails"; From 8f38037b01d244a88e9e14797d38e6793f4b3f12 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:08:01 +0500 Subject: [PATCH 07/16] Web:Common:Components:MediaViewer:Sub-Components: Added MobileDetails component --- .../MobileDetails/MobileDetails.props.ts | 15 ++++ .../sub-components/MobileDetails/index.tsx | 70 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 packages/common/components/MediaViewer/sub-components/MobileDetails/MobileDetails.props.ts create mode 100644 packages/common/components/MediaViewer/sub-components/MobileDetails/index.tsx diff --git a/packages/common/components/MediaViewer/sub-components/MobileDetails/MobileDetails.props.ts b/packages/common/components/MediaViewer/sub-components/MobileDetails/MobileDetails.props.ts new file mode 100644 index 0000000000..f9023a4dd3 --- /dev/null +++ b/packages/common/components/MediaViewer/sub-components/MobileDetails/MobileDetails.props.ts @@ -0,0 +1,15 @@ +import { ContextMenuModel } from "../../types"; + +interface MobileDetailsProps { + icon: string; + title: string; + isError: boolean; + isPreviewFile: boolean; + contextModel: () => ContextMenuModel[]; + + onHide: VoidFunction; + onMaskClick: VoidFunction; + onContextMenu: (e: TouchEvent) => void; +} + +export default MobileDetailsProps; diff --git a/packages/common/components/MediaViewer/sub-components/MobileDetails/index.tsx b/packages/common/components/MediaViewer/sub-components/MobileDetails/index.tsx new file mode 100644 index 0000000000..8ecc16314b --- /dev/null +++ b/packages/common/components/MediaViewer/sub-components/MobileDetails/index.tsx @@ -0,0 +1,70 @@ +import React, { ForwardedRef, useMemo } from "react"; + +import Text from "@docspace/components/text"; +import ContextMenu from "@docspace/components/context-menu"; + +import { StyledMobileDetails } from "../../StyledComponents"; + +import type MobileDetailsProps from "./MobileDetails.props"; + +import BackArrow from "PUBLIC_DIR/images/viewer.media.back.react.svg"; +import MediaContextMenu from "PUBLIC_DIR/images/vertical-dots.react.svg"; + +function MobileDetails( + { + icon, + title, + isError, + isPreviewFile, + onHide, + onMaskClick, + onContextMenu, + contextModel, + }: MobileDetailsProps, + ref: ForwardedRef +) { + const contextMenuHeader = useMemo( + () => ({ + icon: icon, + title: title, + }), + [icon, title] + ); + + return ( + + + + {title} + + {!isPreviewFile && !isError && ( +
+ + +
+ )} +
+ ); +} + +export default React.memo( + React.forwardRef(MobileDetails) +); From 5b9e3e28e47ef5398154c3cc7a3f5ed233390444 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:09:50 +0500 Subject: [PATCH 08/16] Web:Common:Components:MediaViewer:Sub-Components Added NextButton component --- .../sub-components/NextButton/index.tsx | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 packages/common/components/MediaViewer/sub-components/NextButton/index.tsx diff --git a/packages/common/components/MediaViewer/sub-components/NextButton/index.tsx b/packages/common/components/MediaViewer/sub-components/NextButton/index.tsx new file mode 100644 index 0000000000..a0a88a080c --- /dev/null +++ b/packages/common/components/MediaViewer/sub-components/NextButton/index.tsx @@ -0,0 +1,23 @@ +import React from "react"; + +import { + StyledButtonScroll, + StyledSwitchToolbar, +} from "../../StyledComponents"; +import MediaNextIcon from "PUBLIC_DIR/images/viewer.next.react.svg"; + +type NextButtonProps = { + nextClick: VoidFunction; +}; + +function NextButton({ nextClick }: NextButtonProps) { + return ( + + + + + + ); +} + +export default NextButton; From 30a842dec754fea62d6b5777ff187105392a0f23 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:11:15 +0500 Subject: [PATCH 09/16] Web:Common:Components:MediaViewer:Sub-Components Added PrevButton component --- .../sub-components/PrevButton/index.tsx | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 packages/common/components/MediaViewer/sub-components/PrevButton/index.tsx diff --git a/packages/common/components/MediaViewer/sub-components/PrevButton/index.tsx b/packages/common/components/MediaViewer/sub-components/PrevButton/index.tsx new file mode 100644 index 0000000000..dea1d4c116 --- /dev/null +++ b/packages/common/components/MediaViewer/sub-components/PrevButton/index.tsx @@ -0,0 +1,23 @@ +import React from "react"; + +import { + StyledButtonScroll, + StyledSwitchToolbar, +} from "../../StyledComponents"; +import MediaPrevIcon from "PUBLIC_DIR/images/viewer.prew.react.svg"; + +type PrevButtonProps = { + prevClick: VoidFunction; +}; + +function PrevButton({ prevClick }: PrevButtonProps) { + return ( + + + + + + ); +} + +export default PrevButton; From 1f499d679541e4478120e124dfd8db59d0372744 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:26:54 +0500 Subject: [PATCH 10/16] Web:Components:Viewer:Sub-Components Moved the global state to the local state in the viewer-player component --- packages/components/viewer/sub-components/viewer-player.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/components/viewer/sub-components/viewer-player.js b/packages/components/viewer/sub-components/viewer-player.js index dc6c07cb19..40dde73de9 100644 --- a/packages/components/viewer/sub-components/viewer-player.js +++ b/packages/components/viewer/sub-components/viewer-player.js @@ -356,9 +356,6 @@ export default function ViewerPlayer(props) { setPanelVisible, onTouch, isOpenContextMenu, - setGlobalTimer, - globalTimer, - videoControls, setIsOpenContextMenu, contextModel, onDownloadClick, @@ -418,10 +415,12 @@ export default function ViewerPlayer(props) { const inputRef = React.useRef(null); const volumeRef = React.useRef(null); const actionRef = React.useRef(null); + const videoControls = React.useRef(null); const mobileProgressRef = React.useRef(null); const [state, dispatch] = React.useReducer(reducer, initialState); const [currentVolume, setCurrentVolume] = React.useState(stateVolume); + const [globalTimer, setGlobalTimer] = React.useState(null); const speedIcons = [, , , ]; const handlers = useSwipeable({ onSwiping: (e) => { From 8762efde2c18b386f598e5ea03657dde6bdb6281 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:30:20 +0500 Subject: [PATCH 11/16] Web:Common:Components:MediaViewer:Sub-Components: Added Viewer component --- .../sub-components/Viewer/Viewer.props.ts | 36 +++ .../sub-components/Viewer/index.tsx | 215 ++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 packages/common/components/MediaViewer/sub-components/Viewer/Viewer.props.ts create mode 100644 packages/common/components/MediaViewer/sub-components/Viewer/index.tsx diff --git a/packages/common/components/MediaViewer/sub-components/Viewer/Viewer.props.ts b/packages/common/components/MediaViewer/sub-components/Viewer/Viewer.props.ts new file mode 100644 index 0000000000..7f21f0c797 --- /dev/null +++ b/packages/common/components/MediaViewer/sub-components/Viewer/Viewer.props.ts @@ -0,0 +1,36 @@ +import { getCustomToolbar } from "../../helpers/getCustomToolbar"; +import { ContextMenuModel, PlaylistType } from "../../types"; + +interface ViewerProps { + title: string; + images: { src: string; alt: string }[]; + isAudio: boolean; + isVideo: boolean; + visible: boolean; + isImage: boolean; + + playlist: PlaylistType[]; + inactive: boolean; + + audioIcon: string; + zoomSpeed: number; + errorTitle: string; + headerIcon: string; + customToolbar: () => ReturnType; + playlistPos: number; + archiveRoom: boolean; + isPreviewFile: boolean; + onMaskClick: VoidFunction; + onNextClick: VoidFunction; + onPrevClick: VoidFunction; + contextModel: () => ContextMenuModel[]; + onDownloadClick: VoidFunction; + generateContextMenu: ( + isOpen: boolean, + right: string, + bottom: string + ) => JSX.Element; + onSetSelectionFile: VoidFunction; +} + +export default ViewerProps; diff --git a/packages/common/components/MediaViewer/sub-components/Viewer/index.tsx b/packages/common/components/MediaViewer/sub-components/Viewer/index.tsx new file mode 100644 index 0000000000..b7391a01f5 --- /dev/null +++ b/packages/common/components/MediaViewer/sub-components/Viewer/index.tsx @@ -0,0 +1,215 @@ +import ReactDOM from "react-dom"; +import React, { useRef, useState, useEffect, useCallback } from "react"; +import { isMobileOnly } from "react-device-detect"; + +import Text from "@docspace/components/text"; +import IconButton from "@docspace/components/icon-button"; +import ContextMenu from "@docspace/components/context-menu"; + +import { StyledViewer } from "@docspace/components/viewer/styled-viewer"; +import ViewerPlayer from "@docspace/components/viewer/sub-components/viewer-player"; + +import { ControlBtn, StyledViewerContainer } from "../../StyledComponents"; + +import MobileDetails from "../MobileDetails"; +import PrevButton from "../PrevButton"; +import NextButton from "../NextButton"; + +import type ViewerProps from "./Viewer.props"; + +import ViewerMediaCloseSvgUrl from "PUBLIC_DIR/images/viewer.media.close.svg?url"; + +function Viewer(props: ViewerProps) { + const timerIDRef = useRef(); + + const containerRef = React.useRef(document.createElement("div")); + + const [panelVisible, setPanelVisible] = useState(true); + const [isOpenContextMenu, setIsOpenContextMenu] = useState(false); + const [isError, setIsError] = useState(false); + const [isPlay, setIsPlay] = useState(null); + + const [imageTimer, setImageTimer] = useState(); + + const contextMenuRef = useRef(null); + const videoElementRef = useRef(null); + + const [isFullscreen, setIsFullScreen] = useState(false); + useEffect(() => { + document.body.appendChild(containerRef.current); + + return () => { + document.body.removeChild(containerRef.current); + timerIDRef.current && clearTimeout(timerIDRef.current); + }; + }, []); + + useEffect(() => { + if ((!isPlay || isOpenContextMenu) && (!props.isImage || isOpenContextMenu)) + return clearTimeout(timerIDRef.current); + }, [isPlay, isOpenContextMenu, props.isImage]); + + useEffect(() => { + if (!isMobileOnly) { + const resetTimer = () => { + setPanelVisible(true); + clearTimeout(timerIDRef.current); + timerIDRef.current = setTimeout(() => setPanelVisible(false), 2500); + setImageTimer(timerIDRef.current); + }; + + document.addEventListener("mousemove", resetTimer, { passive: true }); + + return () => { + document.removeEventListener("mousemove", resetTimer); + clearTimeout(timerIDRef.current); + setPanelVisible(true); + }; + } + }, [setImageTimer, setPanelVisible]); + + useEffect(() => { + document.addEventListener("touchstart", onTouch); + + return () => document.removeEventListener("touchstart", onTouch); + }, [setPanelVisible]); + + const onTouch = useCallback( + (e: TouchEvent, canTouch?: boolean) => { + if (e.target === videoElementRef.current || canTouch) { + setPanelVisible((visible) => !visible); + } + }, + [setPanelVisible] + ); + + const nextClick = () => { + clearTimeout(imageTimer); + props.onNextClick(); + }; + + const prevClick = () => { + clearTimeout(imageTimer); + props.onPrevClick(); + }; + + const onMobileContextMenu = useCallback( + (e: TouchEvent) => { + setIsOpenContextMenu((open) => !open); + props.onSetSelectionFile(); + contextMenuRef.current?.show(e); + }, + [props.onSetSelectionFile, setIsOpenContextMenu] + ); + + const onHide = useCallback(() => { + setIsOpenContextMenu(false); + }, [setIsOpenContextMenu]); + + const mobileDetails = ( + + ); + + const displayUI = (isMobileOnly && props.isAudio) || panelVisible; + + const isNotFirstElement = props.playlistPos !== 0; + const isNotLastElement = props.playlistPos < props.playlist.length - 1; + + return ( + + {!isFullscreen && !isMobileOnly && displayUI && ( +
+
+ + {props.title} + + + + +
+
+ )} + + {props.playlist.length > 1 && !isFullscreen && displayUI && ( + <> + {isNotFirstElement && } + {isNotLastElement && } + + )} + + {props.isImage + ? ReactDOM.createPortal( + , + containerRef.current + ) + : (props.isVideo || props.isAudio) && + ReactDOM.createPortal( + , + containerRef.current + )} +
+ ); +} + +export default Viewer; From bcfef89ef1db6793d5459788ff10ec0a6fd935a1 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:34:55 +0500 Subject: [PATCH 12/16] Web:Common:Components:MediaViewer:Sub-Components: Changed to a new viewer component --- .../MediaViewer/sub-components/ViewerWrapper/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/components/MediaViewer/sub-components/ViewerWrapper/index.tsx b/packages/common/components/MediaViewer/sub-components/ViewerWrapper/index.tsx index 5cc1914baa..731e768278 100644 --- a/packages/common/components/MediaViewer/sub-components/ViewerWrapper/index.tsx +++ b/packages/common/components/MediaViewer/sub-components/ViewerWrapper/index.tsx @@ -1,7 +1,7 @@ import React, { useMemo, memo, useCallback } from "react"; import equal from "fast-deep-equal/react"; -import { Viewer } from "@docspace/components/viewer"; +import Viewer from "../Viewer"; import { isSeparator } from "../../helpers"; import { getCustomToolbar } from "../../helpers/getCustomToolbar"; import { ContextMenuModel } from "../../types"; From e810217b42c6af048b8e79ef0e1ab724dd3b688c Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Sat, 18 Feb 2023 23:37:37 +0500 Subject: [PATCH 13/16] Web:Common:Components:MediaViewer:Sub-Components: Removed old unnecessary components --- .../MediaViewer/sub-components/duration.js | 24 - .../sub-components/image-viewer.js | 415 ------------- .../MediaViewer/sub-components/progress.js | 138 ----- .../sub-components/video-viewer.js | 579 ------------------ 4 files changed, 1156 deletions(-) delete mode 100644 packages/common/components/MediaViewer/sub-components/duration.js delete mode 100644 packages/common/components/MediaViewer/sub-components/image-viewer.js delete mode 100644 packages/common/components/MediaViewer/sub-components/progress.js delete mode 100644 packages/common/components/MediaViewer/sub-components/video-viewer.js diff --git a/packages/common/components/MediaViewer/sub-components/duration.js b/packages/common/components/MediaViewer/sub-components/duration.js deleted file mode 100644 index 85ae296596..0000000000 --- a/packages/common/components/MediaViewer/sub-components/duration.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from "react"; - -export default function Duration({ className, seconds }) { - return ( - - ); -} - -function format(seconds) { - const date = new Date(seconds * 1000); - const hh = date.getUTCHours(); - const mm = date.getUTCMinutes(); - const ss = pad(date.getUTCSeconds()); - if (hh) { - return `${hh}:${pad(mm)}:${ss}`; - } - return `${mm}:${ss}`; -} - -function pad(string) { - return ("0" + string).slice(-2); -} diff --git a/packages/common/components/MediaViewer/sub-components/image-viewer.js b/packages/common/components/MediaViewer/sub-components/image-viewer.js deleted file mode 100644 index 5de161772f..0000000000 --- a/packages/common/components/MediaViewer/sub-components/image-viewer.js +++ /dev/null @@ -1,415 +0,0 @@ -import React from "react"; -import PropTypes from "prop-types"; -import styled from "styled-components"; - -import MediaZoomInIcon from "PUBLIC_DIR/images/media.zoomin.react.svg"; -import MediaZoomOutIcon from "PUBLIC_DIR/images/media.zoomout.react.svg"; -import MediaRotateLeftIcon from "PUBLIC_DIR/images/media.rotateleft.react.svg"; -import MediaRotateRightIcon from "PUBLIC_DIR/images/media.rotateright.react.svg"; -import MediaDeleteIcon from "PUBLIC_DIR/images/media.delete.react.svg"; -import MediaDownloadIcon from "PUBLIC_DIR/images/download.react.svg"; -import commonIconsStyles from "@docspace/components/utils/common-icons-style"; -import MediaFavoriteIcon from "PUBLIC_DIR/images/favorite.react.svg"; - -import ViewerSeparator from "PUBLIC_DIR/images/viewer.separator.react.svg"; -import MediaShare from "PUBLIC_DIR/images/share.react.svg"; - -import DropDownItem from "@docspace/components/drop-down-item"; -import DropDown from "@docspace/components/drop-down"; -import equal from "fast-deep-equal/react"; -import { Base } from "@docspace/components/themes"; -import { Viewer } from "@docspace/components/viewer"; - -const StyledViewer = styled(Viewer)` - .react-viewer-footer { - bottom: 5px !important; - z-index: 301 !important; - overflow: visible; - } - .react-viewer-canvas { - z-index: 300 !important; - margin-top: 50px; - } - .react-viewer-navbar, - .react-viewer-mask, - .react-viewer-attribute, - .react-viewer-close { - display: none; - } - .react-viewer-toolbar { - position: relative; - overflow: visible; - bottom: 4px; - } - .react-viewer-toolbar li { - width: 40px; - height: 30px; - margin-top: 4px; - border-radius: 2px; - cursor: pointer; - line-height: 24px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - } - .react-viewer-btn { - background-color: transparent; - &:hover { - background-color: ${(props) => - props.theme.mediaViewer.imageViewer.backgroundColor}; - } - } - .react-viewer-image-transition { - transition-duration: 0s; - } - li[data-key="prev"] { - left: 20px; - } - li[data-key="next"] { - right: 20px; - } - li[data-key="prev"], - li[data-key="next"] { - position: fixed; - top: calc(50% - 20px); - - height: auto; - background: none; - - &:hover { - background: none; - } - } - li[data-key="delete"], - li[data-key="customDownload"] { - position: fixed; - @media (max-width: 600px) { - position: initial; - } - bottom: 9px; - .controlBtn { - margin: 0; - } - } - li[data-key="delete"] { - right: 62px; - } - li[data-key="customDownload"] { - right: 12px; - } - .iconContainer { - width: 24px; - height: 24px; - line-height: 20px; - margin: 3px auto; - - &.reset { - width: 18px; - } - - path, - rect { - fill: ${(props) => props.theme.mediaViewer.imageViewer.fill}; - } - } - - .btnContainer { - display: block; - width: 16px; - height: 16px; - margin: 4px 12px; - line-height: 19px; - - path, - rect { - fill: ${(props) => props.theme.mediaViewer.imageViewer.fill}; - } - } - .scrollBtn { - cursor: ${(props) => (props.inactive ? "default" : "pointer")}; - opacity: ${(props) => (props.inactive ? "0.2" : "1")}; - &:hover { - background-color: ${(props) => - !props.inactive - ? props.theme.mediaViewer.imageViewer.backgroundColor - : props.theme.mediaViewer.imageViewer.inactiveBackgroundColor}; - } - } -`; - -const StyledDropDown = styled(DropDown)` - background: #333; -`; - -const StyledDropDownItem = styled(DropDownItem)` - color: #fff; - - .drop-down-item_icon svg { - path { - fill: #fff !important; - } - } - - /* .is-separator { - height: 1px; - background: #474747; - } */ - - &:hover { - background: #444; - } -`; - -StyledViewer.defaultProps = { theme: Base }; - -class ImageViewer extends React.Component { - // componentDidUpdate() { - // document.getElementsByClassName("iconContainer reset").length > 0 && - // document.getElementsByClassName("iconContainer reset")[0].click(); - // } - - shouldComponentUpdate(nextProps) { - return !equal(this.props, nextProps); - } - render() { - const { - className, - visible, - images, - inactive, - onClose, - userAccess, - title, - errorTitle, - onPrevClick, - onNextClick, - playlist, - playlistPos, - isImage, - isAudio, - isVideo, - isPreviewFile, - archiveRoom, - contextModel, - audioIcon, - headerIcon, - onSetSelectionFile, - onDownloadClick, - } = this.props; - - const generateContextMenu = (isOpen, right, bottom) => { - const model = contextModel(); - - const onItemClick = (e, item) => { - const { action, onClick } = item; - - return onClick({ originalEvent: e, action: action, item }); - }; - - return ( - - {model.map((item) => { - if (item.disabled) return; - - const onClick = (e) => { - onClose(); - onItemClick(e, item); - }; - return ( - - ); - })} - - ); - }; - - var customToolbar = [ - { - key: "zoomOut", - percent: true, - actionType: 2, - render: ( -
- -
- ), - }, - { - key: "percent", - actionType: 999, - }, - { - key: "zoomIn", - actionType: 1, - render: ( -
- -
- ), - }, - { - key: "rotateLeft", - actionType: 5, - render: ( -
- -
- ), - }, - { - key: "rotateRight", - actionType: 6, - render: ( -
- -
- ), - }, - { - key: "separator download-separator", - actionType: -1, - noHover: true, - render: ( -
- -
- ), - }, - // { - // key: "share", - // actionType: 101, - // render: ( - //
- // - //
- // ), - // }, - { - key: "download", - actionType: 102, - render: ( -
- -
- ), - }, - { - key: "context-separator", - actionType: -1, - noHover: true, - render: ( -
- -
- ), - }, - { - key: "context-menu", - actionType: -1, - }, - { - key: "delete", - actionType: 103, - render: ( -
- -
- ), - }, - { - key: "favorite", - actionType: 104, - render: ( -
- -
- ), - }, - ]; - - customToolbar.forEach((button) => { - switch (button.key) { - case "prev": - button.onClick = this.props.onPrevClick; - break; - case "next": - button.onClick = this.props.onNextClick; - break; - case "delete": - button.onClick = this.props.onDeleteClick; - break; - case "download": - button.onClick = onDownloadClick; - break; - default: - break; - } - }); - - const canShare = playlist[playlistPos].canShare; - const toolbars = - !canShare && userAccess - ? customToolbar.filter( - (x) => x.key !== "share" && x.key !== "share-separator" - ) - : customToolbar.filter((x) => x.key !== "delete"); - - return ( -
- toolbars} - images={images} - /> -
- ); - } -} - -ImageViewer.propTypes = { - className: PropTypes.string, - visible: PropTypes.bool, - inactive: PropTypes.bool, - images: PropTypes.arrayOf(PropTypes.object), - onNextClick: PropTypes.func, - onPrevClick: PropTypes.func, - onDeleteClick: PropTypes.func, - onDownloadClick: PropTypes.func, - onClose: PropTypes.func, -}; - -export default ImageViewer; diff --git a/packages/common/components/MediaViewer/sub-components/progress.js b/packages/common/components/MediaViewer/sub-components/progress.js deleted file mode 100644 index 3c4ed0cd40..0000000000 --- a/packages/common/components/MediaViewer/sub-components/progress.js +++ /dev/null @@ -1,138 +0,0 @@ -import React from "react"; -import styled from "styled-components"; -import PropTypes from "prop-types"; -import { Base } from "@docspace/components/themes"; - -const StyledProgress = styled.div` - display: inline-block; - - .slider-container { - display: inline-block; - border-radius: 2px; - position: relative; - width: ${(props) => props.width}px; - height: 6px; - background: ${(props) => - props.theme.mediaViewer.progressBar.backgroundColor}; - margin: 15px 0; - vertical-align: middle; - } - .fill { - cursor: pointer; - width: ${(props) => 100 * props.value}%; - position: absolute; - - top: calc(50% - 3px); - height: 6px; - background: ${(props) => props.theme.mediaViewer.progressBar.background}; - border-radius: 2px; - } - input[type="range"] { - display: block; - overflow: visible; - background: transparent; - width: ${(props) => props.width}px; - height: 6px; - outline: none; - margin: 0; - -webkit-appearance: none; - position: relative; - cursor: pointer; - } - - input[type="range"]::-webkit-slider-thumb { - position: relative; - appearance: none; - box-sizing: content-box; - width: 12px; - height: 12px; - margin-top: -3px; - background: white; - border-radius: 50%; - - cursor: pointer; - } - input[type="range"]::-moz-range-thumb { - position: relative; - appearance: none; - box-sizing: content-box; - width: 12px; - height: 12px; - background: white; - border-radius: 50%; - margin-top: -3px; - cursor: pointer; - } - input[type="range"]::-ms-thumb { - position: relative; - appearance: none; - box-sizing: content-box; - width: 12px; - height: 12px; - background: white; - border-radius: 50%; - margin-top: -3px; - cursor: pointer; - } - - input[type="range"]::-webkit-slider-runnable-track { - margin: 12px 0; - height: 6px; - border-radius: 2px; - cursor: pointer; - -webkit-appearance: none; - text-align: right; - pointer-events: none; - } - input[type="range"]::-moz-range-track { - margin: 12px 0; - height: 6px; - border-radius: 2px; - cursor: pointer; - -webkit-appearance: none; - text-align: right; - pointer-events: none; - } - input[type="range"]::-ms-track { - border-color: transparent; - color: transparent; - - margin: 12px 0; - height: 6px; - border-radius: 2px; - cursor: pointer; - -webkit-appearance: none; - text-align: right; - pointer-events: none; - } -`; - -StyledProgress.defaultProps = { theme: Base }; -const Progress = (props) => { - return ( - -
-
- props.handleSeekChange(event)} - onMouseUp={props.handleSeekMouseUp} - /> -
-
- ); -}; - -Progress.propTypes = { - value: PropTypes.number, - handleSeekMouseDown: PropTypes.func, - handleSeekChange: PropTypes.func, - handleSeekMouseUp: PropTypes.func, -}; - -export default Progress; diff --git a/packages/common/components/MediaViewer/sub-components/video-viewer.js b/packages/common/components/MediaViewer/sub-components/video-viewer.js deleted file mode 100644 index 95f18ed8f1..0000000000 --- a/packages/common/components/MediaViewer/sub-components/video-viewer.js +++ /dev/null @@ -1,579 +0,0 @@ -import React, { Component } from "react"; -import PropTypes from "prop-types"; -import styled, { css } from "styled-components"; -import { findDOMNode } from "react-dom"; -import screenfull from "screenfull"; -import ReactPlayer from "react-player"; - -import Duration from "./duration"; -import Progress from "./progress"; -import MediaPauseIcon from "PUBLIC_DIR/images/media.pause.react.svg"; -import MediaPlayIcon from "PUBLIC_DIR/images/media.play.react.svg"; -import MediaFullScreenIcon from "PUBLIC_DIR/images/media.fullscreen.video.react.svg"; -import MediaMuteIcon from "PUBLIC_DIR/images/media.mute.react.svg"; -import MediaMuteOffIcon from "PUBLIC_DIR/images/media.muteoff.react.svg"; -import commonIconsStyles from "@docspace/components/utils/common-icons-style"; -import { Base } from "@docspace/components/themes"; - -const iconsStyles = css` - path, - stroke, - rect { - fill: ${(props) => props.theme.mediaViewer.videoViewer.fill}; - } -`; - -const controlsHeight = 40; -const StyledControls = styled.div` - height: ${(props) => props.height}px; - display: block; - position: fixed; - z-index: 301; - ${(props) => - !props.isVideo && - `background-color: ${props.theme.mediaViewer.videoViewer.backgroundColor};`} - top: calc(50% + ${(props) => props.top}px); - left: ${(props) => props.left}px; -`; - -StyledControls.defaultProps = { theme: Base }; -const StyledVideoControlBtn = styled.div` - display: inline-block; - height: 26px; - line-height: 30px; - margin: 5px 2px; - width: 38px; - border-radius: 2px; - cursor: pointer; - text-align: center; - vertical-align: top; - &:hover { - background-color: ${(props) => - props.theme.mediaViewer.videoViewer.background}; - } - - .playBtnContainer { - width: 16px; - height: 16px; - line-height: 0; - margin: 5px auto; - } - .pauseBtnContainer { - display: block; - width: 16px; - height: 16px; - margin: 3px 10px; - line-height: 19px; - } - .muteBtnContainer { - display: block; - width: 16px; - height: 16px; - margin: 3px 11px; - line-height: 19px; - } - .fullscreenBtnContainer { - display: block; - width: 16px; - height: 16px; - margin: 3px 11px; - line-height: 19px; - } -`; - -StyledVideoControlBtn.defaultProps = { theme: Base }; -const StyledMediaPauseIcon = styled(MediaPauseIcon)` - ${commonIconsStyles} - ${iconsStyles} -`; -StyledMediaPauseIcon.defaultProps = { theme: Base }; -const StyledMediaPlayIcon = styled(MediaPlayIcon)` - ${commonIconsStyles} - ${iconsStyles} -`; -StyledMediaPlayIcon.defaultProps = { theme: Base }; -const StyledMediaFullScreenIcon = styled(MediaFullScreenIcon)` - ${commonIconsStyles} - ${iconsStyles} -`; -StyledMediaFullScreenIcon.defaultProps = { theme: Base }; -const StyledMediaMuteIcon = styled(MediaMuteIcon)` - ${commonIconsStyles} - - path:first-child { - stroke: ${(props) => props.theme.mediaViewer.videoViewer.stroke}; - } - - path:last-child { - fill: ${(props) => props.theme.mediaViewer.videoViewer.fill}; - } -`; -const StyledMediaMuteOffIcon = styled(MediaMuteOffIcon)` - ${commonIconsStyles} - - path, rect { - fill: ${(props) => props.theme.mediaViewer.videoViewer.fill}; - } -`; - -StyledMediaMuteIcon.defaultProps = { theme: Base }; -const VideoControlBtn = (props) => { - return ( - {props.children} - ); -}; -VideoControlBtn.propTypes = { - children: PropTypes.any, -}; -const Controls = (props) => { - return {props.children}; -}; -Controls.propTypes = { - children: PropTypes.any, -}; -const PlayBtn = (props) => { - return ( - - {props.playing ? ( -
- -
- ) : ( -
- -
- )} -
- ); -}; -PlayBtn.propTypes = { - playing: PropTypes.bool, - onClick: PropTypes.func, -}; -const FullScreenBtn = (props) => { - return ( - -
- -
-
- ); -}; -FullScreenBtn.propTypes = { - onClick: PropTypes.func, -}; - -const StyledValumeContainer = styled.div` - display: inline-block; - vertical-align: top; - line-height: 39px; - position: relative; - - .muteConteiner { - display: none; - position: absolute; - width: 40px; - height: 80px; - border-radius: 5px; - top: -76px; - left: 5px; - background: black; - } - &:hover { - .muteConteiner { - display: inline-block; - } - } - .mute { - display: inline-block; - transform: rotate(-90deg); - margin: 22px -14px; - } -`; -const StyledDuration = styled.div` - display: inline-block; - height: 26px; - line-height: 26px; - margin: 5px; - width: 60px; - text-align: center; - vertical-align: top; - border-radius: 2px; - cursor: pointer; - - &:hover { - background-color: ${(props) => - props.theme.mediaViewer.videoViewer.background}; - } -`; - -StyledValumeContainer.defaultProps = { theme: Base }; -const StyledVideoViewer = styled.div` - color: ${(props) => props.theme.mediaViewer.videoViewer.color}; - - .playerWrapper { - display: ${(props) => (props.isVideo ? "block" : "none")}; - width: ${(props) => props.width}px; - height: ${(props) => props.height}px; - left: ${(props) => props.left}px; - top: calc(50% - ${(props) => props.top / 2}px); - z-index: 301; - position: fixed; - padding-bottom: 40px; - background-color: ${(props) => - props.theme.mediaViewer.videoViewer.backgroundColor}; - - video { - z-index: 300; - } - } -`; - -StyledVideoViewer.defaultProps = { theme: Base }; - -const ErrorContainer = styled.div` - z-index: 301; - display: block; - position: fixed; - left: calc(50% - 110px); - top: calc(50% - 40px); - background-color: ${(props) => - props.theme.mediaViewer.videoViewer.backgroundColorError}; - color: ${(props) => props.theme.mediaViewer.videoViewer.colorError}; - border-radius: 10px; - padding: 20px; - text-align: center; -`; - -ErrorContainer.defaultProps = { theme: Base }; - -class ValumeBtn extends Component { - constructor(props) { - super(props); - } - - render() { - return ( - -
- -
- - -
- {this.props.muted ? ( - - ) : ( - - )} -
-
-
- ); - } -} -ValumeBtn.propTypes = { - width: PropTypes.number, - volume: PropTypes.number, - muted: PropTypes.bool, - onMouseDown: PropTypes.func, - onChange: PropTypes.func, - handleSeekMouseUp: PropTypes.func, - onChangeMute: PropTypes.func, -}; - -class VideoViewer extends Component { - state = { - url: this.props.url, - pip: false, - playing: false, - controls: false, - light: false, - volume: 0.3, - muted: false, - played: 0, - loaded: 0, - duration: 0, - playbackRate: 1.0, - loop: false, - isNew: false, - error: false, - isLoaded: false, - }; - - componentDidMount() { - document.addEventListener("keydown", this.onKeydown, false); - } - - componentWillUnmount() { - document.removeEventListener("keydown", this.onKeydown, false); - } - - componentDidUpdate(prevProps) { - if (this.props.url !== prevProps.url) { - this.setState({ - url: this.props.url, - isNew: true, - error: false, - }); - } - } - - onKeydown = (e) => { - if (e.keyCode === 32) this.handlePlayPause(); - }; - - handlePlayPause = () => { - this.setState({ playing: !this.state.playing, isNew: false }); - }; - - handleStop = () => { - this.setState({ url: null, playing: false }); - }; - - handleVolumeChange = (e) => { - this.setState({ - volume: parseFloat(e.target.value), - muted: false, - }); - }; - - handleToggleMuted = () => { - this.setState({ muted: !this.state.muted }); - }; - - handlePlay = () => { - this.setState({ playing: true }); - }; - - handleEnablePIP = () => { - this.setState({ pip: true }); - }; - - handleDisablePIP = () => { - this.setState({ pip: false }); - }; - - handlePause = () => { - this.setState({ playing: false }); - }; - - handleSeekMouseDown = (e) => { - this.setState({ seeking: true }); - }; - - handleSeekChange = (e) => { - this.setState({ played: parseFloat(e.target.value) }); - }; - - handleSeekMouseUp = (e) => { - console.log(!isNaN(parseFloat(e.target.value)), parseFloat(e.target.value)); - if (!isNaN(parseFloat(e.target.value))) { - this.setState({ seeking: false }); - this.player.seekTo(parseFloat(e.target.value)); - } - }; - - handleProgress = (state) => { - if (!this.state.seeking) { - this.setState(state); - } - }; - - handleEnded = () => { - this.setState({ playing: this.state.loop }); - }; - - handleDuration = (duration) => { - this.setState({ duration }); - }; - - handleClickFullscreen = () => { - screenfull.request(findDOMNode(this.player)); - }; - - ref = (player) => { - this.player = player; - }; - - resizePlayer = (videoSize, screenSize) => { - var ratio = videoSize.h / videoSize.w; - - if (videoSize.h > screenSize.h) { - videoSize.h = screenSize.h; - videoSize.w = videoSize.h / ratio; - } - if (videoSize.w > screenSize.w) { - videoSize.w = screenSize.w; - videoSize.h = videoSize.w * ratio; - } - - return { - width: videoSize.w, - height: videoSize.h, - }; - }; - - onError = (e) => { - console.log("onError", e); - this.setState({ error: true }); - }; - - onPlay = () => { - this.setState({ playing: !this.state.isNew, isNew: false, isLoaded: true }); - }; - - render() { - const { - url, - playing, - controls, - light, - volume, - muted, - loop, - played, - loaded, - duration, - playbackRate, - pip, - error, - isLoaded, - } = this.state; - const { errorLabel } = this.props; - - const parentOffset = this.props.getOffset() || 0; - var screenSize = { - w: window.innerWidth, - h: window.innerHeight, - }; - screenSize.h -= parentOffset + controlsHeight; - - let width = screenSize.w; - let height = screenSize.h; - - let centerAreaOx = screenSize.w / 2 + document.documentElement.scrollLeft; - let centerAreaOy = screenSize.h / 2 + document.documentElement.scrollTop; - - let videoElement = document.getElementsByTagName("video")[0]; - if (videoElement) { - width = this.props.isVideo - ? videoElement.videoWidth || 480 - : screenSize.w - 150; - height = this.props.isVideo ? videoElement.videoHeight || 270 : 0; - - let resize = this.resizePlayer( - { - w: width, - h: height, - }, - screenSize - ); - width = resize.width; - height = resize.height; - } - - let left = this.props.isVideo - ? centerAreaOx - width / 2 - : centerAreaOx - width / 2; - - const videoControlBtnWidth = 220; - const audioControlBtnWidth = 170; - let progressWidth = this.props.isVideo - ? width - videoControlBtnWidth - : width - audioControlBtnWidth; - - if (error) { - return ( - -

{errorLabel}

-
- ); - } - - return ( - -
-
- -
- - - - - - - - - {this.props.isVideo && ( - - )} - -
-
- ); - } -} - -VideoViewer.propTypes = { - isVideo: PropTypes.bool, - url: PropTypes.string, - getOffset: PropTypes.func, - errorLabel: PropTypes.string, -}; - -export default VideoViewer; From e674e4414dfe1f359705750d7e702c274e2179a2 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Mon, 20 Feb 2023 11:50:18 +0500 Subject: [PATCH 14/16] Web:Common:Components:MediaViewer:Sub-Components:Viewer Refactoring --- .../sub-components/Viewer/index.tsx | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/common/components/MediaViewer/sub-components/Viewer/index.tsx b/packages/common/components/MediaViewer/sub-components/Viewer/index.tsx index b7391a01f5..96f94c1448 100644 --- a/packages/common/components/MediaViewer/sub-components/Viewer/index.tsx +++ b/packages/common/components/MediaViewer/sub-components/Viewer/index.tsx @@ -50,22 +50,22 @@ function Viewer(props: ViewerProps) { }, [isPlay, isOpenContextMenu, props.isImage]); useEffect(() => { - if (!isMobileOnly) { - const resetTimer = () => { - setPanelVisible(true); - clearTimeout(timerIDRef.current); - timerIDRef.current = setTimeout(() => setPanelVisible(false), 2500); - setImageTimer(timerIDRef.current); - }; + if (isMobileOnly) return; - document.addEventListener("mousemove", resetTimer, { passive: true }); + const resetTimer = () => { + setPanelVisible(true); + clearTimeout(timerIDRef.current); + timerIDRef.current = setTimeout(() => setPanelVisible(false), 2500); + setImageTimer(timerIDRef.current); + }; - return () => { - document.removeEventListener("mousemove", resetTimer); - clearTimeout(timerIDRef.current); - setPanelVisible(true); - }; - } + document.addEventListener("mousemove", resetTimer, { passive: true }); + + return () => { + document.removeEventListener("mousemove", resetTimer); + clearTimeout(timerIDRef.current); + setPanelVisible(true); + }; }, [setImageTimer, setPanelVisible]); useEffect(() => { From c525cb3d5e2123066bcc4bfc95b0609575b801e6 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Mon, 20 Feb 2023 12:39:01 +0500 Subject: [PATCH 15/16] Web:Common:Components:MediaViewer:Helpers Fixed isSeparator type guard --- packages/common/components/MediaViewer/helpers/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/components/MediaViewer/helpers/index.ts b/packages/common/components/MediaViewer/helpers/index.ts index 8b3d6286e9..4fea4f34db 100644 --- a/packages/common/components/MediaViewer/helpers/index.ts +++ b/packages/common/components/MediaViewer/helpers/index.ts @@ -64,5 +64,5 @@ export const findNearestIndex = ( }; export const isSeparator = (arg: ContextMenuModel): arg is SeparatorType => { - return arg?.isSeparator; + return arg?.isSeparator !== undefined && arg.isSeparator; }; From b41c926279ad8249606d7bdcb7126d0215b1d65b Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Mon, 20 Feb 2023 12:49:30 +0300 Subject: [PATCH 16/16] Web: Files: fixed duplicate files when uploading and resizing at the same time --- packages/client/src/store/FilesStore.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/client/src/store/FilesStore.js b/packages/client/src/store/FilesStore.js index 64d7381592..b6762d586e 100644 --- a/packages/client/src/store/FilesStore.js +++ b/packages/client/src/store/FilesStore.js @@ -181,6 +181,8 @@ class FilesStore { const newFiles = [fileInfo, ...this.files]; + if (this.files.findIndex((x) => x.id === opt?.id) > -1) return; + if (newFiles.length > this.filter.pageCount && withPaging) { newFiles.pop(); // Remove last }