From a9d778d7281a78d627231b631854ece1c6ed375a Mon Sep 17 00:00:00 2001 From: haozhe Date: Mon, 27 Apr 2020 10:47:50 +0800 Subject: [PATCH 1/6] fixed message img display --- dev/App.tsx | 2 ++ package-lock.json | 5 +++-- .../components/Messages/components/Message/styles.scss | 8 ++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dev/App.tsx b/dev/App.tsx index 22c2989aa..0117f3918 100644 --- a/dev/App.tsx +++ b/dev/App.tsx @@ -6,6 +6,8 @@ export default class App extends Component { componentDidMount() { addResponseMessage('Welcome to this awesome chat!'); addLinkSnippet({ link: 'https://google.com', title: 'Google' }); + addResponseMessage('![](https://raw.githubusercontent.com/Wolox/press-kit/master/logos/logo_banner.png)'); + addResponseMessage('![vertical](https://d2sofvawe08yqg.cloudfront.net/reintroducing-react/hero2x?1556470143)'); } handleNewUserMessage = (newMessage: any) => { diff --git a/package-lock.json b/package-lock.json index 22615a370..2b7332b92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-chat-widget", - "version": "3.0.0-beta", + "version": "3.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -10976,7 +10976,8 @@ }, "js-yaml": { "version": "3.7.0", - "resolved": "", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", "dev": true, "requires": { "argparse": "^1.0.7", diff --git a/src/components/Widget/components/Conversation/components/Messages/components/Message/styles.scss b/src/components/Widget/components/Conversation/components/Messages/components/Message/styles.scss index 533296076..c286b6289 100644 --- a/src/components/Widget/components/Conversation/components/Messages/components/Message/styles.scss +++ b/src/components/Widget/components/Conversation/components/Messages/components/Message/styles.scss @@ -16,7 +16,7 @@ display: flex; flex-direction: column; margin-left: auto; - + .rcw-message-text { @include message-bubble($turqois-2); } @@ -38,10 +38,14 @@ /* For markdown elements created with default styles */ .rcw-message-text { - p { margin: 0; } + + img { + width: 100%; + object-fit: contain; + } } .rcw-avatar { From ff39016f0c9a5abf1527f29d45cc9e32abab6361 Mon Sep 17 00:00:00 2001 From: haozhe Date: Tue, 28 Apr 2020 21:27:37 +0800 Subject: [PATCH 2/6] image preview --- assets/close.svg | 1 + assets/minus.svg | 1 + assets/plus.svg | 1 + assets/zoom-in.svg | 1 + assets/zoom-out.svg | 1 + dev/index.html | 13 +- package-lock.json | 6 + package.json | 1 + .../Messages/components/Message/index.tsx | 7 +- .../components/Messages/index.tsx | 34 ++++- .../components/FullScreenPreview/index.tsx | 86 +++++++++++ .../components/FullScreenPreview/styles.scss | 56 ++++++++ .../components/FullScreenPreview/usePortal.ts | 52 +++++++ .../FullScreenPreview/usePreview.ts | 135 ++++++++++++++++++ src/components/Widget/layout.tsx | 2 + src/store/actions/index.ts | 15 +- src/store/actions/types.ts | 15 +- src/store/dispatcher.ts | 11 +- src/store/index.ts | 3 +- .../reducers/fullscreenPreviewReducer.ts | 26 ++++ src/store/types.ts | 11 ++ 21 files changed, 468 insertions(+), 10 deletions(-) create mode 100644 assets/close.svg create mode 100644 assets/minus.svg create mode 100644 assets/plus.svg create mode 100644 assets/zoom-in.svg create mode 100644 assets/zoom-out.svg create mode 100644 src/components/Widget/components/FullScreenPreview/index.tsx create mode 100644 src/components/Widget/components/FullScreenPreview/styles.scss create mode 100644 src/components/Widget/components/FullScreenPreview/usePortal.ts create mode 100644 src/components/Widget/components/FullScreenPreview/usePreview.ts create mode 100644 src/store/reducers/fullscreenPreviewReducer.ts diff --git a/assets/close.svg b/assets/close.svg new file mode 100644 index 000000000..fcb517711 --- /dev/null +++ b/assets/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/minus.svg b/assets/minus.svg new file mode 100644 index 000000000..6d2858a45 --- /dev/null +++ b/assets/minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/plus.svg b/assets/plus.svg new file mode 100644 index 000000000..c13a81c3f --- /dev/null +++ b/assets/plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/zoom-in.svg b/assets/zoom-in.svg new file mode 100644 index 000000000..2e18b4ced --- /dev/null +++ b/assets/zoom-in.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/zoom-out.svg b/assets/zoom-out.svg new file mode 100644 index 000000000..b37084ded --- /dev/null +++ b/assets/zoom-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dev/index.html b/dev/index.html index 8ec2a8359..580ad4157 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,9 +1,18 @@ - - + + Dev Widget +
diff --git a/package-lock.json b/package-lock.json index 2b7332b92..a851cb231 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1893,6 +1893,12 @@ "type-detect": "4.0.8" } }, + "@toycode/markdown-it-class": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@toycode/markdown-it-class/-/markdown-it-class-1.2.3.tgz", + "integrity": "sha512-9N7iI5iGzjmYpeEFE93/76SkiSZkywkIiKUxahoU4h5WDUJyruXO+Ce4o/nFkFdKQnmsTmyxhdCtXVikl67XGw==", + "dev": true + }, "@types/babel__core": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.7.tgz", diff --git a/package.json b/package.json index 6d523ebe0..56b536049 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@babel/preset-env": "^7.8.7", "@babel/preset-react": "^7.8.3", "@babel/preset-typescript": "^7.8.3", + "@toycode/markdown-it-class": "^1.2.3", "@types/classnames": "^2.2.10", "@types/enzyme": "^3.10.5", "@types/jest": "^25.1.4", diff --git a/src/components/Widget/components/Conversation/components/Messages/components/Message/index.tsx b/src/components/Widget/components/Conversation/components/Messages/components/Message/index.tsx index d6c0e24e1..42a8ac356 100644 --- a/src/components/Widget/components/Conversation/components/Messages/components/Message/index.tsx +++ b/src/components/Widget/components/Conversation/components/Messages/components/Message/index.tsx @@ -3,6 +3,7 @@ import format from 'date-fns/format'; import markdownIt from 'markdown-it'; import markdownItSup from 'markdown-it-sup'; import markdownItSanitizer from 'markdown-it-sanitizer'; +import markdownItClass from '@toycode/markdown-it-class'; import markdownItLinkAttributes from 'markdown-it-link-attributes'; import { Message } from 'src/store/types'; @@ -15,7 +16,11 @@ type Props = { } function Message({ message, showTimeStamp }: Props) { - const sanitizedHTML = markdownIt().use(markdownItSup) + const sanitizedHTML = markdownIt() + .use(markdownItClass, { + img: ['message-img'] + }) + .use(markdownItSup) .use(markdownItSanitizer) .use(markdownItLinkAttributes, { attrs: { target: '_blank', rel: 'noopener' } }) .render(message.text); diff --git a/src/components/Widget/components/Conversation/components/Messages/index.tsx b/src/components/Widget/components/Conversation/components/Messages/index.tsx index ac15f6dfa..e43ded8ce 100644 --- a/src/components/Widget/components/Conversation/components/Messages/index.tsx +++ b/src/components/Widget/components/Conversation/components/Messages/index.tsx @@ -1,10 +1,10 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useRef, useState, ElementRef, ImgHTMLAttributes, MouseEvent } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import format from 'date-fns/format'; import { scrollToBottom } from '../../../../../../utils/messages'; import { Message, Link, CustomCompMessage, GlobalState } from '../../../../../../store/types'; -import { setBadgeCount, markAllMessagesRead } from '@actions'; +import { setBadgeCount, markAllMessagesRead, openFullscreenPreview } from '@actions'; import Loader from './components/Loader'; import './styles.scss'; @@ -23,7 +23,7 @@ function Messages({ profileAvatar, showTimeStamp }: Props) { showChat: state.behavior.showChat })); - const messageRef = useRef(null); + const messageRef = useRef(null); useEffect(() => { // @ts-ignore scrollToBottom(messageRef.current); @@ -47,6 +47,33 @@ function Messages({ profileAvatar, showTimeStamp }: Props) { // } // } + useEffect(() => { + const target = messageRef && messageRef.current; + const eventHandle = (evt) => { + if(evt.target && evt.target.className === 'message-img') { + const { src, naturalWidth, naturalHeight } = (evt.target as HTMLImageElement); + const obj = { + src: src, + width: naturalWidth, + height: naturalHeight, + }; + dispatch(openFullscreenPreview(obj)) + } + } + + if(target) { + target.addEventListener('click', eventHandle, false) + } + + return () => { + if (target) { + target.removeEventListener('click', eventHandle) + } + } + }, [messageRef]) + + + return (
{messages?.map((message, index) => @@ -58,6 +85,7 @@ function Messages({ profileAvatar, showTimeStamp }: Props) { {getComponentToRender(message)}
)} + ); diff --git a/src/components/Widget/components/FullScreenPreview/index.tsx b/src/components/Widget/components/FullScreenPreview/index.tsx new file mode 100644 index 000000000..34bd3c838 --- /dev/null +++ b/src/components/Widget/components/FullScreenPreview/index.tsx @@ -0,0 +1,86 @@ +import React, { useEffect, useRef } from 'react'; +import ReactDOM from 'react-dom'; +import { useSelector, useDispatch } from 'react-redux'; +import usePreview from './usePreview'; +import usePortal from './usePortal'; +import './styles.scss'; +import { GlobalState } from '../../../../store/types'; +import { closeFullscreenPreview } from '../../../../store/actions'; + +const close = require('../../../../../assets/close.svg') as string; +const plus = require('../../../../../assets/plus.svg') as string; +const minus = require('../../../../../assets/minus.svg') as string; +const zoomIn = require('../../../../../assets/zoom-in.svg') as string; +const zoomOut = require('../../../../../assets/zoom-out.svg') as string; + +export default function PdfFullScreen() { + const { + state, + initFileSize, + onZoomIn, + onZoomOut, + onResizePageZoom + } = usePreview(); + + const dispatch = useDispatch(); + const { src, width, height, visible } = useSelector((state: GlobalState) => ({ + src: state.preview.src, + width: state.preview.width, + height: state.preview.height, + visible: state.preview.visible + })); + + useEffect(() => { + if(src) { + initFileSize(width, height); + } + }, [src]) + + const pDom = usePortal() + + const onClosePreview = () => { + dispatch(closeFullscreenPreview()) + } + + const childNode = ( +
+
+ +
+ +
+ + + + +
+
+ ) + + if(visible) { + return ( + ReactDOM.createPortal(childNode, pDom) + ); + } + return null +} diff --git a/src/components/Widget/components/FullScreenPreview/styles.scss b/src/components/Widget/components/FullScreenPreview/styles.scss new file mode 100644 index 000000000..5910b7847 --- /dev/null +++ b/src/components/Widget/components/FullScreenPreview/styles.scss @@ -0,0 +1,56 @@ +.fullscreen-container { + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.75); + overflow: hidden; + position: fixed; + z-index: 9999; + left: 0; + top: 0; + + &__image { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; + transition: all 0.3s ease; + } + + &__tool-container { + position: fixed; + right: 16px; + bottom: 16px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + + &__button { + padding: 0; + margin: 16px; + box-shadow: 0 3px 8px 0px rgba(0, 0, 0, 0.3); + border-radius: 50%; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + outline: none; + } + + &__button--close { + position: absolute; + right: 0; + top: 0; + } + + &__shadow { + width: 100%; + height: 100%; + overflow: scroll; + position: relative; + } +} diff --git a/src/components/Widget/components/FullScreenPreview/usePortal.ts b/src/components/Widget/components/FullScreenPreview/usePortal.ts new file mode 100644 index 000000000..57f3e836a --- /dev/null +++ b/src/components/Widget/components/FullScreenPreview/usePortal.ts @@ -0,0 +1,52 @@ +import { useRef, useEffect } from 'react'; + +function createRootElement(id: string):HTMLDivElement { + const rootContainer = document.createElement('div'); + rootContainer.setAttribute('id', id); + return rootContainer; +} + +function addRootElement(rootElem: HTMLDivElement):void { + document.body.appendChild(rootElem); +} + +function usePortal():HTMLDivElement { + const rootElemRef = useRef(null); + + useEffect(() => { + // Look for existing target dom element to append to + const existingParent: HTMLDivElement | null = document.querySelector('#rcw-image-preview'); + // Parent is either a new root or the existing dom element + const parentElem: HTMLDivElement = existingParent || createRootElement('#rcw-image-preview'); + + // If there is no existing DOM element, add a new one. + if (!existingParent) { + addRootElement(parentElem); + } + + // Add the detached element to the parent + if(rootElemRef.current) { + parentElem.appendChild(rootElemRef.current); + } + + return function removeElement() { + if(rootElemRef.current) { + rootElemRef.current.remove(); + } + if (parentElem.childNodes.length === -1) { + parentElem.remove(); + } + }; + }, []); + + function getRootElem():HTMLDivElement { + if (!rootElemRef.current) { + rootElemRef.current = document.createElement('div'); + } + return rootElemRef.current as HTMLDivElement; + } + + return getRootElem(); +} + +export default usePortal; diff --git a/src/components/Widget/components/FullScreenPreview/usePreview.ts b/src/components/Widget/components/FullScreenPreview/usePreview.ts new file mode 100644 index 000000000..6e6d280e4 --- /dev/null +++ b/src/components/Widget/components/FullScreenPreview/usePreview.ts @@ -0,0 +1,135 @@ +import { useState, useEffect, useReducer } from 'react'; + +type Layout = { + width?: number; + height?: number; +} + +interface STATE { + layout: Layout; + zoom: boolean + direction: 'vertical' | 'horizontal' +} + +const STEP: number = 80; + +const initState: STATE = { + layout: { width: 800 }, + zoom: false, + direction: 'vertical' +}; + +const usePreview = () => { + const [windowSize, setWindowSize] = useState({ width: 0, height: 0 }); + const [fileSize, setFileSize] = useState({ width: 0, height: 0 }); + + const reducer = (state, action) => { + switch (action.type) { + case 'initLayout': + return { ...state, layout: action.layout, direction: action.direction, zoom: false }; + case 'zoomIn': + return { + ...state, + layout: action.layout, + zoom: true + }; + case 'zoomOut': + return { + ...state, + layout: action.layout, + zoom: true + }; + case 'resetZoom': + return { ...state, layout: action.layout, direction: action.direction }; + default: + throw new Error('Unexpected action'); + } + }; + + const [state, dispatch] = useReducer(reducer, { ...initState }); + + useEffect(() => { + const { innerWidth, innerHeight } = window; + setWindowSize({ width: innerWidth, height: innerHeight }); + }, []); + + const initFileSize = (width: number, height: number) => { + // default size + setFileSize({ width, height }); + // window size and img size rate + if(width < height) { + // vertical + dispatch({ + type: 'initLayout', + layout: { + height: windowSize.height * 0.8 + }, + direction: 'vertical', + }); + } else { + // horizontal + dispatch({ + type: 'initLayout', + layout: { + width: windowSize.width * 0.8, + }, + direction: 'horizontal', + }); + } + }; + + const getLayout = (step: number): Layout => { + let layout; + if(state.direction === 'vertical') { + layout = { + height: state.layout.height + step + } + } else { + layout = { + width: state.layout.width + step + } + } + return layout + } + + const isMinSize = (): Boolean => { + if(state.direction === 'vertical') { + return state.layout.height > (windowSize.height / 3) + } + return state.layout.width > windowSize.width / 3 + } + + const onZoomIn = () => { + dispatch({ + type: 'zoomIn', + layout: getLayout(STEP) + }); + }; + + + const onZoomOut = () => { + if (isMinSize()) { + dispatch({ + type: 'zoomOut', + layout: getLayout(-STEP) + }); + } + }; + + const onResizePageZoom = () => { + if (state.zoom) { + // full height + initFileSize(fileSize.width, fileSize.height) + } + }; + + return { + state, + initFileSize, + onZoomIn, + onZoomOut, + onResizePageZoom + }; +}; + +export default usePreview; diff --git a/src/components/Widget/layout.tsx b/src/components/Widget/layout.tsx index 8718387de..9f81e6efe 100644 --- a/src/components/Widget/layout.tsx +++ b/src/components/Widget/layout.tsx @@ -7,6 +7,7 @@ import { AnyFunction } from 'src/utils/types'; import Conversation from './components/Conversation'; import Launcher from './components/Launcher'; +import FullScreenPreview from './components/FullScreenPreview'; import './style.scss'; @@ -85,6 +86,7 @@ function WidgetLayout({ closeLabel={launcherCloseLabel} /> } + ); } diff --git a/src/store/actions/index.ts b/src/store/actions/index.ts index e56d72dfe..8a12a646f 100644 --- a/src/store/actions/index.ts +++ b/src/store/actions/index.ts @@ -1,7 +1,7 @@ import { ElementType } from 'react'; import * as actionsTypes from './types'; -import { LinkParams } from '../types'; +import { LinkParams, ImageState } from '../types'; export function toggleChat(): actionsTypes.ToggleChat { return { @@ -100,3 +100,16 @@ export function markAllMessagesRead(): actionsTypes.MarkAllMessagesRead { type: actionsTypes.MARK_ALL_READ } } + +export function openFullscreenPreview(payload: ImageState): actionsTypes.FullscreenPreviewActions { + return { + type: actionsTypes.OPEN_FULLSCREEN_PREVIEW, + payload + }; +} + +export function closeFullscreenPreview(): actionsTypes.FullscreenPreviewActions { + return { + type: actionsTypes.CLOSE_FULLSCREEN_PREVIEW + }; +} diff --git a/src/store/actions/types.ts b/src/store/actions/types.ts index 3358350f9..a3acc0a32 100644 --- a/src/store/actions/types.ts +++ b/src/store/actions/types.ts @@ -1,6 +1,6 @@ import { ElementType } from 'react'; -import { LinkParams } from '../types'; +import { LinkParams, FullscreenPreviewState } from '../types'; export const TOGGLE_CHAT = 'BEHAVIOR/TOGGLE_CHAT'; export const TOGGLE_INPUT_DISABLED = 'BEHAVIOR/TOGGLE_INPUT_DISABLED'; @@ -15,6 +15,8 @@ export const HIDE_AVATAR = 'MESSAGES/HIDE_AVATAR'; export const DELETE_MESSAGES = 'MESSAGES/DELETE_MESSAGES'; export const MARK_ALL_READ = 'MESSAGES/MARK_ALL_READ'; export const SET_QUICK_BUTTONS = 'SET_QUICK_BUTTONS'; +export const OPEN_FULLSCREEN_PREVIEW = 'FULLSCREEN/OPEN_PREVIEW'; +export const CLOSE_FULLSCREEN_PREVIEW = 'FULLSCREEN/CLOSE_PREVIEW'; export interface ToggleChat { type: typeof TOGGLE_CHAT; @@ -89,3 +91,14 @@ export type MessagesActions = AddUserMessage | AddResponseMessage | AddLinkSnipp | DropMessages | HideAvatar | DeleteMessages | MarkAllMessagesRead | SetBadgeCount; export type QuickButtonsActions = SetQuickButtons; + +export interface openFullscreenPreview { + type: typeof OPEN_FULLSCREEN_PREVIEW; + payload: FullscreenPreviewState +} + +export interface closeFullscreenPreview { + type: typeof CLOSE_FULLSCREEN_PREVIEW; +} + +export type FullscreenPreviewActions = openFullscreenPreview | closeFullscreenPreview; \ No newline at end of file diff --git a/src/store/dispatcher.ts b/src/store/dispatcher.ts index 0d2ee5386..cfad11257 100644 --- a/src/store/dispatcher.ts +++ b/src/store/dispatcher.ts @@ -2,7 +2,7 @@ import { ElementType } from 'react'; import store from '.'; import * as actions from './actions'; -import { LinkParams } from './types'; +import { LinkParams, ImageState } from './types'; export function addUserMessage(text: string, id?: string) { store.dispatch(actions.addUserMessage(text, id)); @@ -55,3 +55,12 @@ export function markAllAsRead() { export function setBadgeCount(count: number) { store.dispatch(actions.setBadgeCount(count)); } + +export function openFullscreenPreview(payload: ImageState) { + console.log('payload', payload) + store.dispatch(actions.openFullscreenPreview(payload)); +} + +export function closeFullscreenPreview() { + store.dispatch(actions.closeFullscreenPreview()); +} diff --git a/src/store/index.ts b/src/store/index.ts index dca1fdd06..a70a40e90 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -3,6 +3,7 @@ import { createStore, combineReducers, compose } from 'redux'; import behavior from './reducers/behaviorReducer'; import messages from './reducers/messagesReducer'; import quickButtons from './reducers/quickButtonsReducer'; +import preview from './reducers/fullscreenPreviewReducer'; declare global { interface Window { @@ -11,6 +12,6 @@ declare global { } const composeEnhancers = (process.env.NODE_ENV !== 'production' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose; -const reducer = combineReducers({ behavior, messages, quickButtons }); +const reducer = combineReducers({ behavior, messages, quickButtons, preview }); export default createStore(reducer, composeEnhancers()); diff --git a/src/store/reducers/fullscreenPreviewReducer.ts b/src/store/reducers/fullscreenPreviewReducer.ts new file mode 100644 index 000000000..a2847b464 --- /dev/null +++ b/src/store/reducers/fullscreenPreviewReducer.ts @@ -0,0 +1,26 @@ +import { createReducer } from '../../utils/createReducer'; +import { FullscreenPreviewState, ImageState } from '../types'; + +import { + OPEN_FULLSCREEN_PREVIEW, + CLOSE_FULLSCREEN_PREVIEW, + FullscreenPreviewActions +} from '../actions/types'; + +const initialState = { + src: '', + width: 0, + height: 0, + visible: false +}; + +const fullscreenPreviewReducer = { + [OPEN_FULLSCREEN_PREVIEW]: (state: FullscreenPreviewState, { payload }) => { + const { src, width, height } = payload + return { ...state, src, width, height, visible: true } + }, + + [CLOSE_FULLSCREEN_PREVIEW]: (state: FullscreenPreviewState) => ({ ...initialState }), +}; + +export default (state: FullscreenPreviewState = initialState, action: FullscreenPreviewActions) => createReducer(fullscreenPreviewReducer, state, action); diff --git a/src/store/types.ts b/src/store/types.ts index 71daf09ff..e91efe2ba 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -52,8 +52,19 @@ export interface QuickButtonsState { quickButtons: QuickButton[]; } +export interface ImageState { + src: string; + width: number; + height: number; +} + +export interface FullscreenPreviewState extends ImageState { + visible?: boolean; +}; + export interface GlobalState { messages: MessagesState; behavior: BehaviorState; quickButtons: QuickButtonsState; + preview: FullscreenPreviewState; } From 807141871faa9fac9826af0507a46a3f37f02072 Mon Sep 17 00:00:00 2001 From: haozhe Date: Wed, 29 Apr 2020 11:03:21 +0800 Subject: [PATCH 3/6] suit mobile --- dev/App.tsx | 1 + .../components/FullScreenPreview/index.tsx | 4 +- .../FullScreenPreview/usePreview.ts | 54 +++++++++---------- src/components/Widget/index.tsx | 5 +- src/components/Widget/layout.tsx | 8 ++- src/index.tsx | 8 ++- 6 files changed, 46 insertions(+), 34 deletions(-) diff --git a/dev/App.tsx b/dev/App.tsx index 0117f3918..adfc0d4b4 100644 --- a/dev/App.tsx +++ b/dev/App.tsx @@ -35,6 +35,7 @@ export default class App extends Component { senderPlaceHolder="Escribe aquĆ­ ..." handleNewUserMessage={this.handleNewUserMessage} handleQuickButtonClicked={this.handleQuickButtonClicked} + imagePreview /> ); } diff --git a/src/components/Widget/components/FullScreenPreview/index.tsx b/src/components/Widget/components/FullScreenPreview/index.tsx index 34bd3c838..6053aaefd 100644 --- a/src/components/Widget/components/FullScreenPreview/index.tsx +++ b/src/components/Widget/components/FullScreenPreview/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useRef, ReactElement, ReactNode } from 'react'; import ReactDOM from 'react-dom'; import { useSelector, useDispatch } from 'react-redux'; import usePreview from './usePreview'; @@ -42,7 +42,7 @@ export default function PdfFullScreen() { dispatch(closeFullscreenPreview()) } - const childNode = ( + const childNode:ReactNode = (
diff --git a/src/components/Widget/components/FullScreenPreview/usePreview.ts b/src/components/Widget/components/FullScreenPreview/usePreview.ts index 6e6d280e4..00220c3ce 100644 --- a/src/components/Widget/components/FullScreenPreview/usePreview.ts +++ b/src/components/Widget/components/FullScreenPreview/usePreview.ts @@ -7,7 +7,7 @@ type Layout = { interface STATE { layout: Layout; - zoom: boolean + zoom?: boolean direction: 'vertical' | 'horizontal' } @@ -26,7 +26,12 @@ const usePreview = () => { const reducer = (state, action) => { switch (action.type) { case 'initLayout': - return { ...state, layout: action.layout, direction: action.direction, zoom: false }; + return { + ...state, + layout: action.payload.layout, + direction: action.payload.direction, + zoom: false + }; case 'zoomIn': return { ...state, @@ -48,34 +53,29 @@ const usePreview = () => { const [state, dispatch] = useReducer(reducer, { ...initState }); - useEffect(() => { + const initFileSize = (width: number, height: number):void => { const { innerWidth, innerHeight } = window; setWindowSize({ width: innerWidth, height: innerHeight }); - }, []); - - const initFileSize = (width: number, height: number) => { // default size setFileSize({ width, height }); - // window size and img size rate - if(width < height) { - // vertical - dispatch({ - type: 'initLayout', - layout: { - height: windowSize.height * 0.8 - }, - direction: 'vertical', - }); + + const payload: STATE = { layout: {}, direction: 'horizontal' }; + + /** + * Calculate the display ratio of screen to picture + */ + if(innerWidth / innerHeight <= width / height) { + payload.layout.width = innerWidth * 0.8 + payload.direction = 'horizontal' } else { - // horizontal - dispatch({ - type: 'initLayout', - layout: { - width: windowSize.width * 0.8, - }, - direction: 'horizontal', - }); + payload.layout.height = innerHeight * 0.8 + payload.direction = 'vertical' } + + dispatch({ + type: 'initLayout', + payload + }); }; const getLayout = (step: number): Layout => { @@ -99,7 +99,7 @@ const usePreview = () => { return state.layout.width > windowSize.width / 3 } - const onZoomIn = () => { + const onZoomIn = ():void => { dispatch({ type: 'zoomIn', layout: getLayout(STEP) @@ -107,7 +107,7 @@ const usePreview = () => { }; - const onZoomOut = () => { + const onZoomOut = ():void => { if (isMinSize()) { dispatch({ type: 'zoomOut', @@ -116,7 +116,7 @@ const usePreview = () => { } }; - const onResizePageZoom = () => { + const onResizePageZoom = ():void => { if (state.zoom) { // full height initFileSize(fileSize.width, fileSize.height) diff --git a/src/components/Widget/index.tsx b/src/components/Widget/index.tsx index 6aba111de..ad32d9775 100644 --- a/src/components/Widget/index.tsx +++ b/src/components/Widget/index.tsx @@ -24,6 +24,7 @@ type Props = { launcherCloseLabel: string; sendButtonAlt: string; showTimeStamp: boolean; + imagePreview: boolean; } function Widget({ @@ -43,7 +44,8 @@ function Widget({ launcherOpenLabel, launcherCloseLabel, sendButtonAlt, - showTimeStamp + showTimeStamp, + imagePreview, }: Props) { const dispatch = useDispatch(); @@ -86,6 +88,7 @@ function Widget({ launcherCloseLabel={launcherCloseLabel} sendButtonAlt={sendButtonAlt} showTimeStamp={showTimeStamp} + imagePreview={imagePreview} /> ); } diff --git a/src/components/Widget/layout.tsx b/src/components/Widget/layout.tsx index 9f81e6efe..be116402e 100644 --- a/src/components/Widget/layout.tsx +++ b/src/components/Widget/layout.tsx @@ -30,6 +30,7 @@ type Props = { launcherCloseLabel: string; sendButtonAlt: string; showTimeStamp: boolean; + imagePreview: boolean; } function WidgetLayout({ @@ -50,7 +51,8 @@ function WidgetLayout({ launcherOpenLabel, launcherCloseLabel, sendButtonAlt, - showTimeStamp + showTimeStamp, + imagePreview }: Props) { const { dissableInput, showChat } = useSelector((state: GlobalState) => ({ showChat: state.behavior.showChat, @@ -86,7 +88,9 @@ function WidgetLayout({ closeLabel={launcherCloseLabel} /> } - + { + imagePreview && + }
); } diff --git a/src/index.tsx b/src/index.tsx index e2989e2d6..aac7cbdc2 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -25,6 +25,7 @@ type Props = { launcherCloseLabel?: string, sendButtonAlt?: string; showTimeStamp?: boolean; + imagePreview?: boolean; } & typeof defaultProps; function ConnectedWidget({ @@ -44,7 +45,8 @@ function ConnectedWidget({ launcherOpenLabel, launcherCloseLabel, sendButtonAlt, - showTimeStamp + showTimeStamp, + imagePreview }: Props) { return ( @@ -66,6 +68,7 @@ function ConnectedWidget({ launcherCloseLabel={launcherCloseLabel} sendButtonAlt={sendButtonAlt} showTimeStamp={showTimeStamp} + imagePreview={imagePreview} /> ); @@ -82,7 +85,8 @@ const defaultProps = { launcherOpenLabel: 'Open chat', launcherCloseLabel: 'Close chat', sendButtonAlt: 'Send', - showTimeStamp: true + showTimeStamp: true, + imagePreview: false, }; ConnectedWidget.defaultProps = defaultProps; From eeb90309b558b9b383787f2b9de313ef1c31ddd3 Mon Sep 17 00:00:00 2001 From: haozhe Date: Wed, 29 Apr 2020 11:50:46 +0800 Subject: [PATCH 4/6] clear code --- src/components/Widget/components/FullScreenPreview/index.tsx | 4 ++-- .../Widget/components/FullScreenPreview/usePreview.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/Widget/components/FullScreenPreview/index.tsx b/src/components/Widget/components/FullScreenPreview/index.tsx index 6053aaefd..098da7837 100644 --- a/src/components/Widget/components/FullScreenPreview/index.tsx +++ b/src/components/Widget/components/FullScreenPreview/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, ReactElement, ReactNode } from 'react'; +import React, { useEffect, ReactNode } from 'react'; import ReactDOM from 'react-dom'; import { useSelector, useDispatch } from 'react-redux'; import usePreview from './usePreview'; @@ -42,7 +42,7 @@ export default function PdfFullScreen() { dispatch(closeFullscreenPreview()) } - const childNode:ReactNode = ( + const childNode: ReactNode = (
diff --git a/src/components/Widget/components/FullScreenPreview/usePreview.ts b/src/components/Widget/components/FullScreenPreview/usePreview.ts index 00220c3ce..dd4758604 100644 --- a/src/components/Widget/components/FullScreenPreview/usePreview.ts +++ b/src/components/Widget/components/FullScreenPreview/usePreview.ts @@ -1,4 +1,4 @@ -import { useState, useEffect, useReducer } from 'react'; +import { useState, useReducer } from 'react'; type Layout = { width?: number; @@ -118,7 +118,6 @@ const usePreview = () => { const onResizePageZoom = ():void => { if (state.zoom) { - // full height initFileSize(fileSize.width, fileSize.height) } }; From 1d14550007a334c3444df4521d96ef98e7f96da6 Mon Sep 17 00:00:00 2001 From: haozhe Date: Mon, 4 May 2020 21:40:49 +0800 Subject: [PATCH 5/6] fixed fullscreen preview --- dev/App.tsx | 5 +- .../Messages/components/Message/index.tsx | 2 +- .../components/Messages/index.tsx | 32 +----- .../Widget/components/Conversation/style.scss | 6 +- .../components/FullScreenPreview/index.tsx | 62 +++++++---- .../components/FullScreenPreview/styles.scss | 14 ++- .../FullScreenPreview/usePreview.ts | 8 +- src/components/Widget/index.tsx | 5 +- src/components/Widget/layout.tsx | 104 ++++++++++++++---- src/components/Widget/style.scss | 4 + src/index.tsx | 6 +- src/store/dispatcher.ts | 1 - .../reducers/fullscreenPreviewReducer.ts | 1 + src/store/types.ts | 1 + src/utils/messages.ts | 2 +- 15 files changed, 159 insertions(+), 94 deletions(-) diff --git a/dev/App.tsx b/dev/App.tsx index adfc0d4b4..dde0c5e8e 100644 --- a/dev/App.tsx +++ b/dev/App.tsx @@ -29,6 +29,8 @@ export default class App extends Component { render() { return ( +
+ + /> +
); } } diff --git a/src/components/Widget/components/Conversation/components/Messages/components/Message/index.tsx b/src/components/Widget/components/Conversation/components/Messages/components/Message/index.tsx index 42a8ac356..b7ccdc08f 100644 --- a/src/components/Widget/components/Conversation/components/Messages/components/Message/index.tsx +++ b/src/components/Widget/components/Conversation/components/Messages/components/Message/index.tsx @@ -18,7 +18,7 @@ type Props = { function Message({ message, showTimeStamp }: Props) { const sanitizedHTML = markdownIt() .use(markdownItClass, { - img: ['message-img'] + img: ['rcw-message-img'] }) .use(markdownItSup) .use(markdownItSanitizer) diff --git a/src/components/Widget/components/Conversation/components/Messages/index.tsx b/src/components/Widget/components/Conversation/components/Messages/index.tsx index e43ded8ce..62db5cfd2 100644 --- a/src/components/Widget/components/Conversation/components/Messages/index.tsx +++ b/src/components/Widget/components/Conversation/components/Messages/index.tsx @@ -4,7 +4,7 @@ import format from 'date-fns/format'; import { scrollToBottom } from '../../../../../../utils/messages'; import { Message, Link, CustomCompMessage, GlobalState } from '../../../../../../store/types'; -import { setBadgeCount, markAllMessagesRead, openFullscreenPreview } from '@actions'; +import { setBadgeCount, markAllMessagesRead } from '@actions'; import Loader from './components/Loader'; import './styles.scss'; @@ -23,7 +23,7 @@ function Messages({ profileAvatar, showTimeStamp }: Props) { showChat: state.behavior.showChat })); - const messageRef = useRef(null); + const messageRef = useRef(null); useEffect(() => { // @ts-ignore scrollToBottom(messageRef.current); @@ -47,33 +47,6 @@ function Messages({ profileAvatar, showTimeStamp }: Props) { // } // } - useEffect(() => { - const target = messageRef && messageRef.current; - const eventHandle = (evt) => { - if(evt.target && evt.target.className === 'message-img') { - const { src, naturalWidth, naturalHeight } = (evt.target as HTMLImageElement); - const obj = { - src: src, - width: naturalWidth, - height: naturalHeight, - }; - dispatch(openFullscreenPreview(obj)) - } - } - - if(target) { - target.addEventListener('click', eventHandle, false) - } - - return () => { - if (target) { - target.removeEventListener('click', eventHandle) - } - } - }, [messageRef]) - - - return (
{messages?.map((message, index) => @@ -85,7 +58,6 @@ function Messages({ profileAvatar, showTimeStamp }: Props) { {getComponentToRender(message)}
)} -
); diff --git a/src/components/Widget/components/Conversation/style.scss b/src/components/Widget/components/Conversation/style.scss index 2d65a85b8..a6b6fa82b 100644 --- a/src/components/Widget/components/Conversation/style.scss +++ b/src/components/Widget/components/Conversation/style.scss @@ -5,19 +5,19 @@ .rcw-conversation-container { border-radius: 10px; box-shadow: 0px 2px 10px 1px $grey-3; - &.active { opacity: 1; transform: translateY(0px); - transition: opacity 0.3s ease, transform 0.3s ease; + transition: opacity 0.3s ease, transform 0.3s ease; } &.hidden { + z-index: -1; pointer-events: none; opacity: 0; transform: translateY(10px); - transition: opacity 0.3s ease, transform 0.3s ease; + transition: opacity 0.3s ease, transform 0.3s ease; } } diff --git a/src/components/Widget/components/FullScreenPreview/index.tsx b/src/components/Widget/components/FullScreenPreview/index.tsx index 098da7837..b40108658 100644 --- a/src/components/Widget/components/FullScreenPreview/index.tsx +++ b/src/components/Widget/components/FullScreenPreview/index.tsx @@ -13,18 +13,24 @@ const minus = require('../../../../../assets/minus.svg') as string; const zoomIn = require('../../../../../assets/zoom-in.svg') as string; const zoomOut = require('../../../../../assets/zoom-out.svg') as string; -export default function PdfFullScreen() { +type Props = { + fullScreenMode?: boolean; + zoomStep?: number +} + +export default function FullScreenPreview({ fullScreenMode, zoomStep }:Props) { const { state, initFileSize, onZoomIn, onZoomOut, onResizePageZoom - } = usePreview(); + } = usePreview(zoomStep); const dispatch = useDispatch(); - const { src, width, height, visible } = useSelector((state: GlobalState) => ({ + const { src, alt, width, height, visible } = useSelector((state: GlobalState) => ({ src: state.preview.src, + alt: state.preview.alt, width: state.preview.width, height: state.preview.height, visible: state.preview.visible @@ -36,6 +42,21 @@ export default function PdfFullScreen() { } }, [src]) + /** + * Previewer needs to prevent body scroll behavior, + * Except fullScreenMode is true + */ + useEffect(() => { + if(fullScreenMode) { + return; + } + if(visible) { + document.body.setAttribute('style', "overflow: hidden") + } else { + document.body.setAttribute('style', "overflow: auto") + } + }, [visible]) + const pDom = usePortal() const onClosePreview = () => { @@ -43,44 +64,43 @@ export default function PdfFullScreen() { } const childNode: ReactNode = ( -
-
- +
+
+ {alt}
-
+
) - if(visible) { - return ( - ReactDOM.createPortal(childNode, pDom) - ); - } - return null + return visible ? ReactDOM.createPortal(childNode, pDom) : null; } diff --git a/src/components/Widget/components/FullScreenPreview/styles.scss b/src/components/Widget/components/FullScreenPreview/styles.scss index 5910b7847..9f6a04096 100644 --- a/src/components/Widget/components/FullScreenPreview/styles.scss +++ b/src/components/Widget/components/FullScreenPreview/styles.scss @@ -1,4 +1,4 @@ -.fullscreen-container { +.rcw-previewer-container { width: 100vw; height: 100vh; background: rgba(0, 0, 0, 0.75); @@ -8,7 +8,7 @@ left: 0; top: 0; - &__image { + .rcw-previewer-image { position: absolute; top: 0; left: 0; @@ -18,7 +18,7 @@ transition: all 0.3s ease; } - &__tool-container { + .rcw-previewer-tools { position: fixed; right: 16px; bottom: 16px; @@ -28,7 +28,7 @@ align-items: center; } - &__button { + .rcw-previewer-button { padding: 0; margin: 16px; box-shadow: 0 3px 8px 0px rgba(0, 0, 0, 0.3); @@ -39,15 +39,17 @@ align-items: center; justify-content: center; outline: none; + background-color: #ffffff; + border: none; } - &__button--close { + .rcw-previewer-close-button { position: absolute; right: 0; top: 0; } - &__shadow { + .rcw-previewer-veil { width: 100%; height: 100%; overflow: scroll; diff --git a/src/components/Widget/components/FullScreenPreview/usePreview.ts b/src/components/Widget/components/FullScreenPreview/usePreview.ts index dd4758604..11ad6daf7 100644 --- a/src/components/Widget/components/FullScreenPreview/usePreview.ts +++ b/src/components/Widget/components/FullScreenPreview/usePreview.ts @@ -11,15 +11,13 @@ interface STATE { direction: 'vertical' | 'horizontal' } -const STEP: number = 80; - const initState: STATE = { layout: { width: 800 }, zoom: false, direction: 'vertical' }; -const usePreview = () => { +const usePreview = (zoomStep) => { const [windowSize, setWindowSize] = useState({ width: 0, height: 0 }); const [fileSize, setFileSize] = useState({ width: 0, height: 0 }); @@ -102,7 +100,7 @@ const usePreview = () => { const onZoomIn = ():void => { dispatch({ type: 'zoomIn', - layout: getLayout(STEP) + layout: getLayout(zoomStep) }); }; @@ -111,7 +109,7 @@ const usePreview = () => { if (isMinSize()) { dispatch({ type: 'zoomOut', - layout: getLayout(-STEP) + layout: getLayout(-zoomStep) }); } }; diff --git a/src/components/Widget/index.tsx b/src/components/Widget/index.tsx index ad32d9775..2ec189ce2 100644 --- a/src/components/Widget/index.tsx +++ b/src/components/Widget/index.tsx @@ -24,7 +24,8 @@ type Props = { launcherCloseLabel: string; sendButtonAlt: string; showTimeStamp: boolean; - imagePreview: boolean; + imagePreview?: boolean; + zoomStep?: number; } function Widget({ @@ -46,6 +47,7 @@ function Widget({ sendButtonAlt, showTimeStamp, imagePreview, + zoomStep, }: Props) { const dispatch = useDispatch(); @@ -89,6 +91,7 @@ function Widget({ sendButtonAlt={sendButtonAlt} showTimeStamp={showTimeStamp} imagePreview={imagePreview} + zoomStep={zoomStep} /> ); } diff --git a/src/components/Widget/layout.tsx b/src/components/Widget/layout.tsx index be116402e..67cf1d84c 100644 --- a/src/components/Widget/layout.tsx +++ b/src/components/Widget/layout.tsx @@ -1,9 +1,10 @@ -import React from 'react'; -import { useSelector } from 'react-redux'; +import React,{ useEffect, useRef } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; import cn from 'classnames'; import { GlobalState } from 'src/store/types'; import { AnyFunction } from 'src/utils/types'; +import { openFullscreenPreview } from '@actions'; import Conversation from './components/Conversation'; import Launcher from './components/Launcher'; @@ -30,7 +31,8 @@ type Props = { launcherCloseLabel: string; sendButtonAlt: string; showTimeStamp: boolean; - imagePreview: boolean; + imagePreview?: boolean; + zoomStep?: number; } function WidgetLayout({ @@ -52,32 +54,88 @@ function WidgetLayout({ launcherCloseLabel, sendButtonAlt, showTimeStamp, - imagePreview + imagePreview, + zoomStep, }: Props) { + const dispatch = useDispatch(); const { dissableInput, showChat } = useSelector((state: GlobalState) => ({ showChat: state.behavior.showChat, dissableInput: state.behavior.disabledInput })); + const messageRef = useRef(null); + + useEffect(() => { + if(showChat) { + messageRef.current = document.getElementById('messages') as HTMLDivElement; + } + return () => { + messageRef.current = null; + } + }, [showChat]) + + const eventHandle = evt => { + if(evt.target && evt.target.className === 'rcw-message-img') { + const { src, alt, naturalWidth, naturalHeight } = (evt.target as HTMLImageElement); + const obj = { + src: src, + alt: alt, + width: naturalWidth, + height: naturalHeight, + }; + dispatch(openFullscreenPreview(obj)) + } + } + + /** + * Previewer needs to prevent body scroll behavior when fullScreenMode is true + */ + useEffect(() => { + const target = messageRef?.current; + if(imagePreview && showChat) { + target?.addEventListener('click', eventHandle, false); + } + + return () => { + target?.removeEventListener('click', eventHandle); + } + }, [imagePreview, showChat]); + + useEffect(() => { + if(fullScreenMode) { + document.body.setAttribute('style', "overflow: hidden") + } else { + document.body.setAttribute('style', "overflow: auto") + } + }, [fullScreenMode]) + return ( -
- +
+ {showChat && + + } {customLauncher ? customLauncher(onToggleConversation) : !fullScreenMode && @@ -89,7 +147,7 @@ function WidgetLayout({ /> } { - imagePreview && + imagePreview && }
); diff --git a/src/components/Widget/style.scss b/src/components/Widget/style.scss index e36ec2c96..565fea397 100644 --- a/src/components/Widget/style.scss +++ b/src/components/Widget/style.scss @@ -23,3 +23,7 @@ @include widget-container-fs; } } + +.rcw-previewer .rcw-message-img { + cursor: pointer; +} diff --git a/src/index.tsx b/src/index.tsx index aac7cbdc2..573af1734 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -26,6 +26,7 @@ type Props = { sendButtonAlt?: string; showTimeStamp?: boolean; imagePreview?: boolean; + zoomStep?: number; } & typeof defaultProps; function ConnectedWidget({ @@ -46,7 +47,8 @@ function ConnectedWidget({ launcherCloseLabel, sendButtonAlt, showTimeStamp, - imagePreview + imagePreview, + zoomStep, }: Props) { return ( @@ -69,6 +71,7 @@ function ConnectedWidget({ sendButtonAlt={sendButtonAlt} showTimeStamp={showTimeStamp} imagePreview={imagePreview} + zoomStep={zoomStep} /> ); @@ -87,6 +90,7 @@ const defaultProps = { sendButtonAlt: 'Send', showTimeStamp: true, imagePreview: false, + zoomStep: 80, }; ConnectedWidget.defaultProps = defaultProps; diff --git a/src/store/dispatcher.ts b/src/store/dispatcher.ts index cfad11257..ca362adad 100644 --- a/src/store/dispatcher.ts +++ b/src/store/dispatcher.ts @@ -57,7 +57,6 @@ export function setBadgeCount(count: number) { } export function openFullscreenPreview(payload: ImageState) { - console.log('payload', payload) store.dispatch(actions.openFullscreenPreview(payload)); } diff --git a/src/store/reducers/fullscreenPreviewReducer.ts b/src/store/reducers/fullscreenPreviewReducer.ts index a2847b464..df8a50548 100644 --- a/src/store/reducers/fullscreenPreviewReducer.ts +++ b/src/store/reducers/fullscreenPreviewReducer.ts @@ -9,6 +9,7 @@ import { const initialState = { src: '', + alt: '', width: 0, height: 0, visible: false diff --git a/src/store/types.ts b/src/store/types.ts index e91efe2ba..89ca058af 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -54,6 +54,7 @@ export interface QuickButtonsState { export interface ImageState { src: string; + alt?: string; width: number; height: number; } diff --git a/src/utils/messages.ts b/src/utils/messages.ts index f4f896bb3..65997180d 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -86,7 +86,7 @@ function scrollWithSlowMotion(target: any, scrollStart: any, scroll: number) { raf(step); } -export function scrollToBottom(messagesDiv: HTMLDivElement) { +export function scrollToBottom(messagesDiv: HTMLDivElement | null) { if (!messagesDiv) return; const screenHeight = messagesDiv.clientHeight; const scrollTop = messagesDiv.scrollTop; From 712dc5745a32118f093eabb177ef58fa587100cd Mon Sep 17 00:00:00 2001 From: haozhe Date: Sun, 17 May 2020 23:07:07 +0800 Subject: [PATCH 6/6] styles && body overflow --- .../Widget/components/FullScreenPreview/index.tsx | 15 --------------- .../components/FullScreenPreview/styles.scss | 4 +++- src/components/Widget/layout.tsx | 13 +++++-------- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/components/Widget/components/FullScreenPreview/index.tsx b/src/components/Widget/components/FullScreenPreview/index.tsx index b40108658..7ce438b31 100644 --- a/src/components/Widget/components/FullScreenPreview/index.tsx +++ b/src/components/Widget/components/FullScreenPreview/index.tsx @@ -42,21 +42,6 @@ export default function FullScreenPreview({ fullScreenMode, zoomStep }:Props) { } }, [src]) - /** - * Previewer needs to prevent body scroll behavior, - * Except fullScreenMode is true - */ - useEffect(() => { - if(fullScreenMode) { - return; - } - if(visible) { - document.body.setAttribute('style', "overflow: hidden") - } else { - document.body.setAttribute('style', "overflow: auto") - } - }, [visible]) - const pDom = usePortal() const onClosePreview = () => { diff --git a/src/components/Widget/components/FullScreenPreview/styles.scss b/src/components/Widget/components/FullScreenPreview/styles.scss index 9f6a04096..6e61c135f 100644 --- a/src/components/Widget/components/FullScreenPreview/styles.scss +++ b/src/components/Widget/components/FullScreenPreview/styles.scss @@ -1,3 +1,5 @@ +@import 'variables/colors'; + .rcw-previewer-container { width: 100vw; height: 100vh; @@ -39,7 +41,7 @@ align-items: center; justify-content: center; outline: none; - background-color: #ffffff; + background-color: $white; border: none; } diff --git a/src/components/Widget/layout.tsx b/src/components/Widget/layout.tsx index 67cf1d84c..804e8e835 100644 --- a/src/components/Widget/layout.tsx +++ b/src/components/Widget/layout.tsx @@ -58,9 +58,10 @@ function WidgetLayout({ zoomStep, }: Props) { const dispatch = useDispatch(); - const { dissableInput, showChat } = useSelector((state: GlobalState) => ({ + const { dissableInput, showChat, visible } = useSelector((state: GlobalState) => ({ showChat: state.behavior.showChat, - dissableInput: state.behavior.disabledInput + dissableInput: state.behavior.disabledInput, + visible: state.preview.visible, })); const messageRef = useRef(null); @@ -102,12 +103,8 @@ function WidgetLayout({ }, [imagePreview, showChat]); useEffect(() => { - if(fullScreenMode) { - document.body.setAttribute('style', "overflow: hidden") - } else { - document.body.setAttribute('style', "overflow: auto") - } - }, [fullScreenMode]) + document.body.setAttribute('style', `overflow: ${visible || fullScreenMode ? 'hidden' : 'auto'}`) + }, [fullScreenMode, visible]) return (