fixed video playback in mobile browser

This commit is contained in:
Roland Osborne 2022-08-27 00:55:59 -07:00
parent 779db5635b
commit 7f5b80a70b
11 changed files with 126 additions and 164 deletions

View File

@ -105,7 +105,7 @@ export const CarouselWrapper = styled.div`
.space {
height: 128px;
padding-left: 32px;
padding-left: 4px;
}
.object {

View File

@ -20,7 +20,9 @@ export function ChannelItem({ item, openChannel }) {
)}
{ item.contacts.length === 1 && (
<div class="item">
<div class="avatar">
<Logo url={item.logo} width={32} height={32} radius={8} />
</div>
<div class="details">
<div class="subject">{ item.subject }</div>
<div class="message">{ item.message }</div>

View File

@ -22,6 +22,16 @@ export const ChannelItemWrapper = styled.div`
align-items: center;
min-width: 0;
.avatar{
display: flex;
align-items: center;
justify-content: center;
border: 1px solid ${Colors.grey};
border-radius: 8px;
font-size: 18px;
flex-shrink: 0;
}
.logo {
display: flex;
align-items: center;

View File

@ -103,15 +103,15 @@ export function TopicItem({ host, topic }) {
<div class={nameClass}>{ name }</div>
<div>{ state.created }</div>
</div>
<div class="topic-options">
<Options />
</div>
</div>
{ !state.confirmed && (
<div>
<div class="message">
<Skeleton size={'small'} active={true} />
</div>
<div class="options">
<Options />
</div>
</div>
)}
{ state.confirmed && (
@ -134,9 +134,6 @@ export function TopicItem({ host, topic }) {
<div class="message">
<Message />
</div>
<div class="options">
<Options />
</div>
</div>
)}
</TopicItemWrapper>

View File

@ -5,10 +5,6 @@ export const TopicItemWrapper = styled.div`
flex-direction: column;
width: 100%;
&:hover .options {
visibility: visible;
}
.topic-header {
display: flex;
flex-direction: row;
@ -18,6 +14,33 @@ export const TopicItemWrapper = styled.div`
padding-top: 8px;
border-top: 1px solid #dddddd;
&:hover .topic-options {
visibility: visible;
}
.topic-options {
position: absolute;
top: 0;
right: 0;
visibility: hidden;
.buttons {
display: flex;
flex-direction: row;
border-radius: 4px;
background-color: #eeeeee;
border: 1px solid #555555;
margin-top: 2px;
.button {
font-size: 14px;
margin-left: 8px;
margin-right: 8px;
cursor: pointer;
}
}
}
.avatar {
height: 32px;
width: 32px;
@ -54,29 +77,6 @@ export const TopicItemWrapper = styled.div`
}
}
.options {
position: absolute;
top: 0;
right: 0;
visibility: hidden;
.buttons {
display: flex;
flex-direction: row;
border-radius: 4px;
background-color: #eeeeee;
border: 1px solid #555555;
margin-top: 2px;
.button {
font-size: 14px;
margin-left: 8px;
margin-right: 8px;
cursor: pointer;
}
}
}
.asset-placeholder {
width: 128px;
height: 128px;

View File

@ -11,17 +11,15 @@ export function ImageAsset({ thumbUrl, fullUrl }) {
const [dimension, setDimension] = useState({ width: 0, height: 0 });
const popout = () => {
if (dimension.width == 0 || dimension.height == 0) {
actions.setPopout('50%', '50%');
}
else {
if (dimension.width / dimension.height > window.innerWidth / window.innerHeight) {
actions.setPopout('80%', 'auto');
let width = Math.floor(window.innerWidth * 8 / 10);
let height = Math.floor(width * dimension.height / dimension.width);
actions.setPopout(width, height);
}
else {
let width = Math.floor(80 * (dimension.width / dimension.height) * (window.innerHeight / window.innerWidth));
actions.setPopout(width + '%', 'auto');
}
let height = Math.floor(window.innerHeight * 8 / 10);
let width = Math.floor(height * dimension.width / dimension.height);
actions.setPopout(width, height);
}
}
@ -37,13 +35,10 @@ export function ImageAsset({ thumbUrl, fullUrl }) {
</ReactResizeDetector>
{ state.display !== 'small' && (
<div class="viewer">
<div class="overlay" style={{ width: dimension.width, height: dimension.height }}>
<div class="expand" onClick={popout}>
<ExpandOutlined style={{ fontSize: 24, color: '#eeeeee', cursor: 'pointer' }} />
</div>
</div>
<Modal visible={state.popout} width={state.width} height={state.height} bodyStyle={{ width: '100%', height: 'auto', paddingBottom: 6, paddingTop: 6, paddingLeft: 6, paddingRight: 6, backgroundColor: '#dddddd' }} footer={null} destroyOnClose={true} closable={false} onCancel={actions.clearPopout}>
<img style={{ width: '100%', objectFit: 'contain' }} src={fullUrl} alt="" />
<div class="overlay" style={{ width: dimension.width, height: dimension.height }}
onClick={popout} />
<Modal centered={true} visible={state.popout} width={state.width + 12} bodyStyle={{ width: '100%', height: 'auto', paddingBottom: 6, paddingTop: 6, paddingLeft: 6, paddingRight: 6, backgroundColor: '#dddddd' }} footer={null} destroyOnClose={true} closable={false} onCancel={actions.clearPopout}>
<img style={{ width: '100%', objectFit: 'contain' }} src={fullUrl} alt="topic image" />
</Modal>
</div>
)}

View File

@ -9,15 +9,10 @@ export const ImageAssetWrapper = styled.div`
position: absolute;
}
.viewer:hover .overlay {
visibility: visible;
}
.overlay {
visibility: hidden;
position: relative;
background-color: black;
opacity: 0.5;
cursor: pointer;
top: 0;
position: absolute;
}
.expand {

View File

@ -25,7 +25,6 @@ export function useImageAsset() {
updateState({ popout: true, width, height });
},
clearPopout: () => {
console.log("CLEAR POPOUT");
updateState({ popout: false });
},
};

View File

@ -1,92 +1,54 @@
import React, { useRef, useEffect, useState } from 'react';
import { Button, Modal } from 'antd';
import ReactPlayer from 'react-player'
import ReactResizeDetector from 'react-resize-detector';
import { SelectOutlined, ExpandOutlined, MinusCircleOutlined, PlayCircleOutlined } from '@ant-design/icons';
import { SelectOutlined, ExpandOutlined, VideoCameraOutlined, MinusCircleOutlined, PlayCircleOutlined } from '@ant-design/icons';
import { VideoAssetWrapper } from './VideoAsset.styled';
import { useVideoAsset } from './useVideoAsset.hook';
export function VideoAsset({ thumbUrl, lqUrl, hdUrl }) {
const [state, setState] = useState({});
const player = useRef(null);
const { state, actions } = useVideoAsset();
const [dimension, setDimension] = useState({ width: 0, height: 0 });
const video = useRef(null);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
}, [thumbUrl, hdUrl, lqUrl]);
const onPopOut = () => {
if (state.width == 0 || state.height == 0) {
updateState({ popout: true, popWidth: '50%', inline: false, popoutUrl: hdUrl, playing: false, inlineUrl: null });
const activate = () => {
if (dimension.width / dimension.height > window.innerWidth / window.innerHeight) {
let width = Math.floor(window.innerWidth * 8 / 10);
let height = Math.floor(width * dimension.height / dimension.width);
actions.setActive(width, height);
}
else {
if (state.width / state.height > window.innerWidth / window.innerHeight) {
updateState({ popout: true, popWidth: '70%', inline: false, popoutUrl: hdUrl, playing: false, inlineUrl: null });
let height = Math.floor(window.innerHeight * 8 / 10);
let width = Math.floor(height * dimension.width / dimension.height);
actions.setActive(width, height);
}
else {
let width = Math.floor(70 * (state.width / state.height) * (window.innerHeight / window.innerWidth));
updateState({ popout: true, popWidth: width + '%', inline: false, popoutUrl: hdUrl, playing: false, inlineUrl: null });
}
}
}
const CenterButton = () => {
if (!state.inline) {
return (
<div onClick={() => updateState({ inline: true, inlineUrl: lqUrl, playing: false })}>
<SelectOutlined style={{ fontSize: 48, color: '#eeeeee', cursor: 'pointer' }} />
</div>
)
}
if (state.playing) {
return (
<div onClick={() => updateState({ playing: false })}>
<MinusCircleOutlined style={{ fontSize: 48, color: '#eeeeee', cursor: 'pointer' }} />
</div>
)
}
else {
return (
<div onClick={() => updateState({ playing: true })}>
<PlayCircleOutlined style={{ fontSize: 48, color: '#eeeeee', cursor: 'pointer' }} />
</div>
)
}
}
const Controls = () => {
return (
<div>
<div class="control">
<CenterButton />
</div>
<div class="expand" onClick={() => onPopOut()}>
<ExpandOutlined style={{ fontSize: 24, color: '#eeeeee', cursor: 'pointer' }} />
</div>
</div>
)
}
return (
<VideoAssetWrapper>
<ReactResizeDetector handleWidth={true} handleHeight={true}>
{({ width, height }) => {
if (width != state.width || height != state.height) {
updateState({ width, height });
if (width != dimension.width || height != dimension.height) {
setDimension({ width, height });
}
return <img style={{ height: '100%', objectFit: 'contain' }} src={thumbUrl} alt="" />
}}
</ReactResizeDetector>
<div class="player" style={{ width: state.width, height: state.height }}>
<ReactPlayer ref={player} controls={false} playing={state.playing}
height="100%" width="100%" url={state.inlineUrl} />
<Controls />
<div class="overlay" style={{ width: dimension.width, height: dimension.height }}>
{ !state.active && (
<div onClick={activate}>
<VideoCameraOutlined style={{ fontSize: 32, color: '#eeeeee', cursor: 'pointer' }} />
</div>
<Modal visible={state.popout} width={state.popWidth} bodyStyle={{ paddingBottom: 0, paddingTop: 6, paddingLeft: 6, paddingRight: 6, backgroundColor: '#dddddd' }} footer={null} destroyOnClose={true} closable={false} onCancel={() => { updateState({ popout: false })}}>
<ReactPlayer controls={true} height="100%" width="100%" url={state.popoutUrl} />
)}
{ state.active && state.display === 'small' && (
<video autoplay controls src={hdUrl} width={dimension.width} height={dimension.height} />
)}
{ state.display !== 'small' && (
<Modal centered={true} visible={state.active} width={state.width + 12} bodyStyle={{ paddingBottom: 0, paddingTop: 6, paddingLeft: 6, paddingRight: 6, backgroundColor: '#dddddd' }} footer={null} destroyOnClose={true} closable={false} onCancel={actions.clearActive}>
<video autoplay={true} controls src={hdUrl} width={state.width} height={state.height} />
</Modal>
)}
</div>
</VideoAssetWrapper>
)
}

View File

@ -4,46 +4,13 @@ export const VideoAssetWrapper = styled.div`
position: relative;
height: 100%;
.playback {
top: 0;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
}
.player:hover .control {
visibility: visible;
}
.player:hover .expand {
visibility: visible;
}
.player {
.overlay {
position: absolute;
top: 0;
}
.control {
top: 0;
visibility: hidden;
position: absolute;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: black;
opacity: 0.5;
}
.expand {
padding-left: 4px;
visibility: hidden;
position: absolute;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
}
`;

View File

@ -0,0 +1,35 @@
import { useContext, useState, useEffect, useRef } from 'react';
import { ViewportContext } from 'context/ViewportContext';
export function useVideoAsset() {
const [state, setState] = useState({
display: null,
width: 0,
height: 0,
active: false,
});
const viewport = useContext(ViewportContext);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
useEffect(() => {
updateState({ display: viewport.state.display });
}, []);
const actions = {
setActive: (width, height, url) => {
console.log(width, height);
updateState({ active: true, width, height });
},
clearActive: () => {
updateState({ active: false });
},
};
return { state, actions };
}