From b88889665fb1055bfb5f55550efb7a3afd9f8980 Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Sun, 17 Nov 2019 23:51:54 -0300 Subject: [PATCH] Refactor Toolbar, move video & notifications --- src/client/actions/MediaActions.ts | 5 +- src/client/components/App.tsx | 14 +-- src/client/components/Media.tsx | 1 - src/client/components/Side.tsx | 7 +- src/client/components/Toolbar.tsx | 158 ++++++++++++++++------------- src/client/components/Video.tsx | 5 +- src/scss/_media.scss | 9 ++ src/scss/_toolbar.scss | 31 +++--- src/scss/_video.scss | 9 +- src/scss/style.scss | 5 +- 10 files changed, 134 insertions(+), 110 deletions(-) diff --git a/src/client/actions/MediaActions.ts b/src/client/actions/MediaActions.ts index cbf598e..db59a78 100644 --- a/src/client/actions/MediaActions.ts +++ b/src/client/actions/MediaActions.ts @@ -107,10 +107,7 @@ export function setMediaVisible(visible: boolean): MediaVisibleAction { export const play = makeAction('MEDIA_PLAY', async () => { const promises = Array .from(document.querySelectorAll('video')) - .filter(video => { - console.log('video', video.paused, video) - return video.paused - }) + .filter(video => video.paused) .map(video => video.play()) await Promise.all(promises) }) diff --git a/src/client/components/App.tsx b/src/client/components/App.tsx index 0ed5177..21df3dc 100644 --- a/src/client/components/App.tsx +++ b/src/client/components/App.tsx @@ -75,9 +75,13 @@ export default class App extends React.PureComponent { const { videos } = this.state + const chatVisibleClassName = classnames({ + 'chat-visible': this.state.chatVisible, + }) + return (
- + { stream={streams[constants.ME]} /> - + { sendMessage={sendMessage} visible={this.state.chatVisible} /> -
+
{streams[constants.ME] && (
) diff --git a/src/client/components/Side.tsx b/src/client/components/Side.tsx index 67d67d6..1e269e0 100644 --- a/src/client/components/Side.tsx +++ b/src/client/components/Side.tsx @@ -7,6 +7,7 @@ export type Top = { top: true } export type Bottom = { bottom: true } export type SideProps = (Left | Right | Top | Bottom) & { + className?: string zIndex: number children: React.ReactNode align?: 'baseline' | 'center' | 'end' @@ -14,11 +15,11 @@ export type SideProps = (Left | Right | Top | Bottom) & { export const Side = React.memo( function Side(props: SideProps) { - const className = classnames('side', { ...props }) + const { className, zIndex, ...otherProps } = props return (
{props.children}
diff --git a/src/client/components/Toolbar.tsx b/src/client/components/Toolbar.tsx index 43ff840..8a9c501 100644 --- a/src/client/components/Toolbar.tsx +++ b/src/client/components/Toolbar.tsx @@ -22,6 +22,43 @@ export interface ToolbarState { fullScreenEnabled: boolean } +export interface ToolbarButtonProps { + className?: string + badge?: string | number + blink?: boolean + onClick: () => void + icon: string + offIcon?: string + on?: boolean + title: string +} + + +function ToolbarButton(props: ToolbarButtonProps) { + const { blink, on } = props + const icon = !on && props.offIcon ? props.offIcon : props.icon + + function onClick(event: React.MouseEvent) { + props.onClick() + document.activeElement && + document.activeElement instanceof HTMLElement && + document.activeElement.blur() + } + + return ( + + + {!!props.badge && {props.badge}} + + {props.title} + + ) +} + export default class Toolbar extends React.PureComponent { file = React.createRef() @@ -61,7 +98,7 @@ extends React.PureComponent { screenfull.toggle() this.setState({ ...this.state, - fullScreenEnabled: !this.state.fullScreenEnabled, + fullScreenEnabled: !screenfull.isFullscreen, }) } } @@ -84,88 +121,73 @@ extends React.PureComponent { } render () { const { messagesCount, stream } = this.props + const unreadCount = messagesCount - this.state.readMessages + const hasUnread = unreadCount > 0 return (
- this.state.readMessages} - title="Chat" - > - - Toggle Chat - - + + + + - - - Send File - + title='Send File' + /> {stream && ( - - - - Toggle Microphone - - - - - Toggle Camera - + className='mute-audio' + on={this.state.micMuted} + icon='icon-mic_off' + offIcon='icon-mic' + title='Toggle Microphone' + /> + )} - - - - Fullscreen - + className='fullscreen' + icon='icon-fullscreen_exit' + offIcon='icon-fullscreen' + on={this.state.fullScreenEnabled} + title='Toggle Fullscreen' + /> - - - Hang Up - + /> +
) } diff --git a/src/client/components/Video.tsx b/src/client/components/Video.tsx index f21f451..8c3c0a8 100644 --- a/src/client/components/Video.tsx +++ b/src/client/components/Video.tsx @@ -52,10 +52,7 @@ export default class Video extends React.PureComponent { id={`video-${socket.id}`} autoPlay onClick={this.handleClick} - onLoadedMetadata={() => { - console.log('onLoadedMetadata') - this.props.play() - }} + onLoadedMetadata={() => this.props.play()} playsInline ref={this.videoRef} muted={muted} diff --git a/src/scss/_media.scss b/src/scss/_media.scss index 756df65..195da61 100644 --- a/src/scss/_media.scss +++ b/src/scss/_media.scss @@ -28,6 +28,15 @@ border-radius: 4px; border-bottom: 2px solid darken(#fff, 10%); text-align: center; + color: black; + background-color: white; + cursor: pointer; + &:hover { + background-color: darken(white, 5%); + } + &:active { + background-color: darken(white, 10%); + } } select, button { diff --git a/src/scss/_toolbar.scss b/src/scss/_toolbar.scss index bd585fe..22d460a 100644 --- a/src/scss/_toolbar.scss +++ b/src/scss/_toolbar.scss @@ -9,6 +9,7 @@ width: 48px; height: 48px; border-radius: 48px; + background-color: rgba(0, 0, 0, 0.2); box-shadow: 2px 2px 24px #444; transition: all .1s; transition-timing-function: ease-in-out; @@ -21,8 +22,13 @@ top: 12px; } - &.on { - display: none; + .badge { + font-family: sans-serif; + font-weight: bold; + color: white; + position: relative; + font-size: 12px; + top: 23px; } } @@ -35,17 +41,18 @@ text-shadow: 0 0 5px black; transition: opacity 200ms ease-in 25ms, transform 100ms ease-in; transform: translateX(-100%); - z-index: 0; + pointer-events: none; } .button { + outline: none; text-decoration: none; display: flex; flex-direction: row; align-items: center; cursor: pointer; - &:hover { + &:hover, &:focus { .icon { box-shadow: 4px 4px 48px #666; cursor: pointer; @@ -62,12 +69,6 @@ } &.on .icon { background: lighten(#407cf7, 10%); - &.on { - display: inherit; - } - &.off { - display: none; - } } } @@ -75,12 +76,10 @@ margin-top: 1rem; } - .chat { - &[data-blink="true"] .icon { - -webkit-animation: bg-blink 1s infinite; - -moz-animation: bg-blink 1s infinite; - animation: bg-blink 1s infinite; - } + .chat.blink .icon { + -webkit-animation: bg-blink 1s infinite; + -moz-animation: bg-blink 1s infinite; + animation: bg-blink 1s infinite; } } diff --git a/src/scss/_video.scss b/src/scss/_video.scss index 87414c0..d921779 100644 --- a/src/scss/_video.scss +++ b/src/scss/_video.scss @@ -2,8 +2,9 @@ position: fixed; height: 100px; bottom: 1rem; - right: 1rem; + right: 0; text-align: right; + transition: right cubic-bezier(0.55, 0, 0, 1) 500ms; $video-size: 100px; @@ -15,6 +16,7 @@ width: $video-size; height: 100%; z-index: 3; + margin-right: 1rem; video { border-radius: 10px; @@ -25,10 +27,6 @@ } } - .video-container + .video-container { - margin-left: 1rem; - } - .video-container.active { background-color: transparent; box-shadow: none; @@ -40,6 +38,7 @@ top: 0; bottom: 0; z-index: -1; + transform: none; video { border-radius: 0; diff --git a/src/scss/style.scss b/src/scss/style.scss index 73a51b2..577358f 100644 --- a/src/scss/style.scss +++ b/src/scss/style.scss @@ -165,6 +165,7 @@ body.call { .side { position: absolute; display: flex; + transition: right cubic-bezier(0.55, 0, 0, 1) 500ms; &.left { flex-direction: row; @@ -195,6 +196,6 @@ body.call { } } -.chat-visible { - transform: translateX(-330px); +.app .chat-visible { + right: 320px; }