mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 11:39:17 +00:00
fixed video playback in mobile browser
This commit is contained in:
parent
779db5635b
commit
7f5b80a70b
@ -105,7 +105,7 @@ export const CarouselWrapper = styled.div`
|
|||||||
|
|
||||||
.space {
|
.space {
|
||||||
height: 128px;
|
height: 128px;
|
||||||
padding-left: 32px;
|
padding-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.object {
|
.object {
|
||||||
|
@ -20,7 +20,9 @@ export function ChannelItem({ item, openChannel }) {
|
|||||||
)}
|
)}
|
||||||
{ item.contacts.length === 1 && (
|
{ item.contacts.length === 1 && (
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<Logo url={item.logo} width={32} height={32} radius={8} />
|
<div class="avatar">
|
||||||
|
<Logo url={item.logo} width={32} height={32} radius={8} />
|
||||||
|
</div>
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div class="subject">{ item.subject }</div>
|
<div class="subject">{ item.subject }</div>
|
||||||
<div class="message">{ item.message }</div>
|
<div class="message">{ item.message }</div>
|
||||||
|
@ -22,6 +22,16 @@ export const ChannelItemWrapper = styled.div`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
min-width: 0;
|
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 {
|
.logo {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -103,15 +103,15 @@ export function TopicItem({ host, topic }) {
|
|||||||
<div class={nameClass}>{ name }</div>
|
<div class={nameClass}>{ name }</div>
|
||||||
<div>{ state.created }</div>
|
<div>{ state.created }</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="topic-options">
|
||||||
|
<Options />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{ !state.confirmed && (
|
{ !state.confirmed && (
|
||||||
<div>
|
<div>
|
||||||
<div class="message">
|
<div class="message">
|
||||||
<Skeleton size={'small'} active={true} />
|
<Skeleton size={'small'} active={true} />
|
||||||
</div>
|
</div>
|
||||||
<div class="options">
|
|
||||||
<Options />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{ state.confirmed && (
|
{ state.confirmed && (
|
||||||
@ -134,9 +134,6 @@ export function TopicItem({ host, topic }) {
|
|||||||
<div class="message">
|
<div class="message">
|
||||||
<Message />
|
<Message />
|
||||||
</div>
|
</div>
|
||||||
<div class="options">
|
|
||||||
<Options />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</TopicItemWrapper>
|
</TopicItemWrapper>
|
||||||
|
@ -5,10 +5,6 @@ export const TopicItemWrapper = styled.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
&:hover .options {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.topic-header {
|
.topic-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -18,6 +14,33 @@ export const TopicItemWrapper = styled.div`
|
|||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
border-top: 1px solid #dddddd;
|
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 {
|
.avatar {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
width: 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 {
|
.asset-placeholder {
|
||||||
width: 128px;
|
width: 128px;
|
||||||
height: 128px;
|
height: 128px;
|
||||||
|
@ -11,17 +11,15 @@ export function ImageAsset({ thumbUrl, fullUrl }) {
|
|||||||
const [dimension, setDimension] = useState({ width: 0, height: 0 });
|
const [dimension, setDimension] = useState({ width: 0, height: 0 });
|
||||||
|
|
||||||
const popout = () => {
|
const popout = () => {
|
||||||
if (dimension.width == 0 || dimension.height == 0) {
|
if (dimension.width / dimension.height > window.innerWidth / window.innerHeight) {
|
||||||
actions.setPopout('50%', '50%');
|
let width = Math.floor(window.innerWidth * 8 / 10);
|
||||||
|
let height = Math.floor(width * dimension.height / dimension.width);
|
||||||
|
actions.setPopout(width, height);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (dimension.width / dimension.height > window.innerWidth / window.innerHeight) {
|
let height = Math.floor(window.innerHeight * 8 / 10);
|
||||||
actions.setPopout('80%', 'auto');
|
let width = Math.floor(height * dimension.width / dimension.height);
|
||||||
}
|
actions.setPopout(width, height);
|
||||||
else {
|
|
||||||
let width = Math.floor(80 * (dimension.width / dimension.height) * (window.innerHeight / window.innerWidth));
|
|
||||||
actions.setPopout(width + '%', 'auto');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,13 +35,10 @@ export function ImageAsset({ thumbUrl, fullUrl }) {
|
|||||||
</ReactResizeDetector>
|
</ReactResizeDetector>
|
||||||
{ state.display !== 'small' && (
|
{ state.display !== 'small' && (
|
||||||
<div class="viewer">
|
<div class="viewer">
|
||||||
<div class="overlay" style={{ width: dimension.width, height: dimension.height }}>
|
<div class="overlay" style={{ width: dimension.width, height: dimension.height }}
|
||||||
<div class="expand" onClick={popout}>
|
onClick={popout} />
|
||||||
<ExpandOutlined style={{ fontSize: 24, color: '#eeeeee', cursor: 'pointer' }} />
|
<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}>
|
||||||
</div>
|
<img style={{ width: '100%', objectFit: 'contain' }} src={fullUrl} alt="topic image" />
|
||||||
</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="" />
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -9,15 +9,10 @@ export const ImageAssetWrapper = styled.div`
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewer:hover .overlay {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay {
|
.overlay {
|
||||||
visibility: hidden;
|
cursor: pointer;
|
||||||
position: relative;
|
top: 0;
|
||||||
background-color: black;
|
position: absolute;
|
||||||
opacity: 0.5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.expand {
|
.expand {
|
||||||
|
@ -25,7 +25,6 @@ export function useImageAsset() {
|
|||||||
updateState({ popout: true, width, height });
|
updateState({ popout: true, width, height });
|
||||||
},
|
},
|
||||||
clearPopout: () => {
|
clearPopout: () => {
|
||||||
console.log("CLEAR POPOUT");
|
|
||||||
updateState({ popout: false });
|
updateState({ popout: false });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,92 +1,54 @@
|
|||||||
import React, { useRef, useEffect, useState } from 'react';
|
import React, { useRef, useEffect, useState } from 'react';
|
||||||
import { Button, Modal } from 'antd';
|
import { Button, Modal } from 'antd';
|
||||||
import ReactPlayer from 'react-player'
|
|
||||||
import ReactResizeDetector from 'react-resize-detector';
|
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 { VideoAssetWrapper } from './VideoAsset.styled';
|
||||||
|
import { useVideoAsset } from './useVideoAsset.hook';
|
||||||
|
|
||||||
export function VideoAsset({ thumbUrl, lqUrl, hdUrl }) {
|
export function VideoAsset({ thumbUrl, lqUrl, hdUrl }) {
|
||||||
|
|
||||||
const [state, setState] = useState({});
|
const { state, actions } = useVideoAsset();
|
||||||
const player = useRef(null);
|
const [dimension, setDimension] = useState({ width: 0, height: 0 });
|
||||||
|
const video = useRef(null);
|
||||||
|
|
||||||
const updateState = (value) => {
|
const activate = () => {
|
||||||
setState((s) => ({ ...s, ...value }));
|
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);
|
||||||
useEffect(() => {
|
actions.setActive(width, height);
|
||||||
}, [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 });
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (state.width / state.height > window.innerWidth / window.innerHeight) {
|
let height = Math.floor(window.innerHeight * 8 / 10);
|
||||||
updateState({ popout: true, popWidth: '70%', inline: false, popoutUrl: hdUrl, playing: false, inlineUrl: null });
|
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 (
|
return (
|
||||||
<VideoAssetWrapper>
|
<VideoAssetWrapper>
|
||||||
<ReactResizeDetector handleWidth={true} handleHeight={true}>
|
<ReactResizeDetector handleWidth={true} handleHeight={true}>
|
||||||
{({ width, height }) => {
|
{({ width, height }) => {
|
||||||
if (width != state.width || height != state.height) {
|
if (width != dimension.width || height != dimension.height) {
|
||||||
updateState({ width, height });
|
setDimension({ width, height });
|
||||||
}
|
}
|
||||||
return <img style={{ height: '100%', objectFit: 'contain' }} src={thumbUrl} alt="" />
|
return <img style={{ height: '100%', objectFit: 'contain' }} src={thumbUrl} alt="" />
|
||||||
}}
|
}}
|
||||||
</ReactResizeDetector>
|
</ReactResizeDetector>
|
||||||
<div class="player" style={{ width: state.width, height: state.height }}>
|
<div class="overlay" style={{ width: dimension.width, height: dimension.height }}>
|
||||||
<ReactPlayer ref={player} controls={false} playing={state.playing}
|
{ !state.active && (
|
||||||
height="100%" width="100%" url={state.inlineUrl} />
|
<div onClick={activate}>
|
||||||
<Controls />
|
<VideoCameraOutlined style={{ fontSize: 32, color: '#eeeeee', cursor: 'pointer' }} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{ 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>
|
</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} />
|
|
||||||
</Modal>
|
|
||||||
</VideoAssetWrapper>
|
</VideoAssetWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,46 +4,13 @@ export const VideoAssetWrapper = styled.div`
|
|||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.playback {
|
.overlay {
|
||||||
top: 0;
|
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player:hover .control {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player:hover .expand {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
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;
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -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 };
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user