Add ability to toggle object-fit: cover on videos by long-pressing

This commit is contained in:
Jerko Steiner 2020-03-11 15:04:44 +01:00
parent 4a53a2fb55
commit a025fcad43
4 changed files with 65 additions and 7 deletions

View File

@ -16,6 +16,7 @@ export interface VideoProps {
export default class Video extends React.PureComponent<VideoProps> {
videoRef = React.createRef<HTMLVideoElement>()
timeout?: number
static defaultProps = {
muted: false,
@ -23,8 +24,25 @@ export default class Video extends React.PureComponent<VideoProps> {
}
handleClick: ReactEventHandler<HTMLVideoElement> = e => {
const { onClick, userId } = this.props
this.props.play()
onClick(userId)
if (this.timeout) {
// if the timeout was cancelled, execute click
this.props.play()
onClick(userId)
}
this.timeout = undefined
}
handleMouseDown: ReactEventHandler<HTMLVideoElement> = e => {
this.timeout = window.setTimeout(this.toggleCover, 300)
}
handleMouseUp: ReactEventHandler<HTMLVideoElement> = e => {
clearTimeout(this.timeout)
}
toggleCover = () => {
this.timeout = undefined
const v = this.videoRef.current
if (v) {
v.style.objectFit = v.style.objectFit ? '' : 'cover'
}
}
componentDidMount () {
this.componentDidUpdate()
@ -52,6 +70,8 @@ export default class Video extends React.PureComponent<VideoProps> {
id={`video-${socket.id}`}
autoPlay
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}
onLoadedMetadata={() => this.props.play()}
playsInline
ref={this.videoRef}

View File

@ -1,6 +1,7 @@
jest.mock('../actions/CallActions')
jest.mock('../socket')
jest.mock('../window')
jest.useFakeTimers()
import React from 'react'
import ReactDOM from 'react-dom'
@ -108,9 +109,14 @@ describe('App', () => {
})
describe('video', () => {
it('can be activated', () => {
beforeEach(() => {
dispatchSpy.mockReset()
})
it('can be activated', () => {
const video = node.querySelector('video')!
TestUtils.Simulate.mouseDown(video)
TestUtils.Simulate.mouseUp(video)
TestUtils.Simulate.click(video)
expect(dispatchSpy.mock.calls[0][0].type).toBe(constants.MEDIA_PLAY)
expect(dispatchSpy.mock.calls.slice(1)).toEqual([[{
@ -118,6 +124,18 @@ describe('App', () => {
payload: { userId: constants.ME + '_0' },
}]])
})
it('can toggle object-fit to/from cover by long-pressing', () => {
['cover', ''].forEach(objectFit => {
const video = node.querySelector('video')!
TestUtils.Simulate.mouseDown(video)
jest.runAllTimers()
TestUtils.Simulate.mouseUp(video)
TestUtils.Simulate.click(video)
expect(video.style.objectFit).toBe(objectFit)
expect(dispatchSpy.mock.calls.slice(1)).toEqual([])
})
})
})
})

View File

@ -25,6 +25,10 @@
width: 100%;
height: 100%;
}
.video-actions {
display: none;
}
}
.video-container.active {
@ -43,6 +47,22 @@
video {
border-radius: 0;
cursor: inherit;
object-fit: contain;
}
.video-actions {
display: inherit;
position: absolute;
right: 0;
bottom: 0;
padding: 1rem;
font-family: monospace;
user-select: none;
.action:hover {
cursor: pointer;
color: white;
}
}
}

View File

@ -101,8 +101,8 @@ body.call {
}
input[type="text"] {
font-size: 1rem;
padding: 1rem 1rem 0.75rem;
font-size: 1.2rem;
padding: 1rem 0rem 0.75rem;
width: 100%;
margin-bottom: 1rem;
background: none;
@ -120,9 +120,9 @@ body.call {
}
input[type="submit"] {
// font-family: $font-monospace;
font-family: $font-monospace;
@include button($color-primary, $color-warning);
font-size: 1rem;
font-size: 1.2rem;
padding: 1rem 1rem;
}