mirror of https://github.com/jitsi/jitsi-meet
* Add buttons to send messages/set nickname. * Redesign message/nickname inputs. * Pin messages to the input. * Add keyboard avoider for Safari. * Make chat content scrollable on mobile.pull/8120/head jitsi-meet_5535
parent
4c39d83ff1
commit
43761fc398
After Width: | Height: | Size: 369 B |
@ -0,0 +1,60 @@ |
||||
// @flow
|
||||
|
||||
import React, { useEffect, useState } from 'react'; |
||||
import styled from 'styled-components'; |
||||
|
||||
import { isIosMobileBrowser } from '../../../base/environment/utils'; |
||||
|
||||
const Avoider = styled.div` |
||||
height: ${props => props.elementHeight}px; |
||||
`;
|
||||
|
||||
/** |
||||
* Component that renders an element to lift the chat input above the Safari keyboard, |
||||
* computing the appropriate height comparisons based on the {@code visualViewport}. |
||||
* |
||||
* @returns {ReactElement} |
||||
*/ |
||||
function KeyboardAvoider() { |
||||
if (!isIosMobileBrowser()) { |
||||
return null; |
||||
} |
||||
|
||||
const [ elementHeight, setElementHeight ] = useState(0); |
||||
const [ storedHeight, setStoredHeight ] = useState(window.innerHeight); |
||||
|
||||
/** |
||||
* Handles the resizing of the visual viewport in order to compute |
||||
* the {@code KeyboardAvoider}'s height. |
||||
* |
||||
* @returns {void} |
||||
*/ |
||||
function handleViewportResize() { |
||||
const { innerWidth, visualViewport: { width, height } } = window; |
||||
|
||||
// Compare the widths to make sure the {@code visualViewport} didn't resize due to zooming.
|
||||
if (width === innerWidth) { |
||||
if (height < storedHeight) { |
||||
setElementHeight(storedHeight - height); |
||||
} else { |
||||
setElementHeight(0); |
||||
} |
||||
setStoredHeight(height); |
||||
} |
||||
} |
||||
|
||||
useEffect(() => { |
||||
// Call the handler in case the keyboard is open when the {@code KeyboardAvoider} is mounted.
|
||||
handleViewportResize(); |
||||
|
||||
window.visualViewport.addEventListener('resize', handleViewportResize); |
||||
|
||||
return () => { |
||||
window.visualViewport.removeEventListener('resize', handleViewportResize); |
||||
}; |
||||
}, []); |
||||
|
||||
return <Avoider elementHeight = { elementHeight } />; |
||||
} |
||||
|
||||
export default KeyboardAvoider; |
@ -0,0 +1,67 @@ |
||||
// @flow
|
||||
|
||||
import React, { useEffect, useRef } from 'react'; |
||||
|
||||
import { isMobileBrowser } from '../../../base/environment/utils'; |
||||
|
||||
type Props = { |
||||
|
||||
/** |
||||
* The component(s) that need to be scrollable on mobile. |
||||
*/ |
||||
children: React$Node, |
||||
|
||||
/** |
||||
* Whether the component is rendered within a modal. |
||||
*/ |
||||
isModal: boolean |
||||
}; |
||||
|
||||
|
||||
/** |
||||
* Component that disables {@code touchmove} propagation below it. |
||||
* |
||||
* @returns {ReactElement} |
||||
*/ |
||||
function TouchmoveHack({ children, isModal }: Props) { |
||||
if (!isModal || !isMobileBrowser()) { |
||||
return children; |
||||
} |
||||
|
||||
const touchMoveElementRef = useRef(null); |
||||
|
||||
/** |
||||
* Atlaskit's {@code Modal} uses a third party library to disable touchmove events |
||||
* which makes scrolling inside dialogs impossible. We therefore employ this hack |
||||
* to intercept and stop the propagation of touchmove events from this wrapper that |
||||
* is placed around the chat conversation from the {@code ChatDialog}. |
||||
* |
||||
* @param {Event} event - The touchmove event fired within the component. |
||||
* @returns {void} |
||||
*/ |
||||
function handleTouchMove(event: TouchEvent) { |
||||
event.stopImmediatePropagation(); |
||||
} |
||||
|
||||
useEffect(() => { |
||||
if (touchMoveElementRef && touchMoveElementRef.current) { |
||||
touchMoveElementRef.current.addEventListener('touchmove', handleTouchMove, true); |
||||
} |
||||
|
||||
return () => { |
||||
if (touchMoveElementRef && touchMoveElementRef.current) { |
||||
touchMoveElementRef.current.removeEventListener('touchmove', handleTouchMove, true); |
||||
} |
||||
}; |
||||
}, []); |
||||
|
||||
return ( |
||||
<div |
||||
className = 'touchmove-hack' |
||||
ref = { touchMoveElementRef }> |
||||
{children} |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default TouchmoveHack; |
Loading…
Reference in new issue