From 87b9b5f51433c5a86fa2a273630e788334dcea74 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Tue, 15 Oct 2019 16:29:49 +0700 Subject: [PATCH] player bar appearance --- src/components/bars/PlayerBar/index.tsx | 64 +++++++++++++++++-- src/components/bars/PlayerBar/styles.scss | 60 +++++++++++++++-- src/components/media/AudioPlayer/index.tsx | 3 +- .../main/BottomContainer/styles.scss | 4 +- src/containers/main/MainLayout/styles.scss | 2 +- src/containers/node/NodeLayout/index.tsx | 1 + 6 files changed, 118 insertions(+), 16 deletions(-) diff --git a/src/components/bars/PlayerBar/index.tsx b/src/components/bars/PlayerBar/index.tsx index 1a6656eb..166a4724 100644 --- a/src/components/bars/PlayerBar/index.tsx +++ b/src/components/bars/PlayerBar/index.tsx @@ -1,4 +1,4 @@ -import React, { FC } from 'react'; +import React, { FC, useCallback, useState, useEffect } from 'react'; import * as styles from './styles.scss'; import { Icon } from '~/components/input/Icon'; import { Filler } from '~/components/containers/Filler'; @@ -7,27 +7,79 @@ import { connect } from 'react-redux'; import pick from 'ramda/es/pick'; import { selectPlayer } from '~/redux/player/selectors'; import * as PLAYER_ACTIONS from '~/redux/player/actions'; +import { IPlayerProgress, Player } from '~/utils/player'; -const mapStateToProps = state => pick(['status'], selectPlayer(state)); +const mapStateToProps = state => pick(['status', 'file'], selectPlayer(state)); const mapDispatchToProps = { playerPlay: PLAYER_ACTIONS.playerPlay, playerPause: PLAYER_ACTIONS.playerPause, + playerSeek: PLAYER_ACTIONS.playerSeek, }; type IProps = ReturnType & typeof mapDispatchToProps & {}; -const PlayerBarUnconnected: FC = ({ status }) => { +const PlayerBarUnconnected: FC = ({ + status, + playerPlay, + playerPause, + playerSeek, + file, +}) => { + const [progress, setProgress] = useState({ progress: 0, current: 0, total: 0 }); + + const onClick = useCallback(() => { + if (status === PLAYER_STATES.PLAYING) return playerPause(); + return playerPlay(); + }, [playerPlay, playerPause, status]); + + const onProgress = useCallback( + ({ detail }: { detail: IPlayerProgress }) => { + if (!detail || !detail.total) return; + setProgress(detail); + }, + [setProgress] + ); + + const onSeek = useCallback( + event => { + event.stopPropagation(); + const { clientX, target } = event; + const { left, width } = target.getBoundingClientRect(); + playerSeek((clientX - left) / width); + }, + [playerSeek] + ); + + useEffect(() => { + Player.on('playprogress', onProgress); + + return () => { + Player.off('playprogress', onProgress); + }; + }, [onProgress]); + if (status === PLAYER_STATES.UNSET) return null; + const title = + file.metadata && + (file.metadata.title || + [file.metadata.id3artist, file.metadata.id3title].filter(el => !!el).join(' - ')); + return (
-
- +
+ {status === PLAYER_STATES.PLAYING ? : }
- +
+
{title}
+ +
+
+
+
diff --git a/src/components/bars/PlayerBar/styles.scss b/src/components/bars/PlayerBar/styles.scss index 9e428b87..5f8d460f 100644 --- a/src/components/bars/PlayerBar/styles.scss +++ b/src/components/bars/PlayerBar/styles.scss @@ -1,6 +1,6 @@ .place { position: relative; - height: 54px; + height: 64px; flex: 0 1 500px; display: flex; @@ -13,29 +13,30 @@ .wrap { display: flex; - border-radius: 27px; + border-radius: $radius $radius 0 0; background: $green_gradient; align-items: center; - box-shadow: rgba(0, 0, 0, 0.5) 0 2px 5px, inset rgba(255, 255, 255, 0.3) 0 1px, + box-shadow: rgba(0, 0, 0, 0.5) 0 2px 5px, inset rgba(255, 255, 255, 0.3) 1px 1px, inset rgba(0, 0, 0, 0.3) 0 -1px; position: absolute; top: 0; left: 0; width: 100%; - height: 54px; + height: 64px; flex-direction: column; transform: translate(0, 0); z-index: 3; + min-width: 0; } .status { - flex: 0 0 54px; + flex: 0 0 64px; display: flex; flex-direction: row; width: 100%; position: absolute; z-index: 1; - height: 54px; + height: 64px; } .playpause, @@ -60,3 +61,50 @@ height: 24px; } } + +.info { + display: flex; + min-width: 0; + align-items: center; + justify-content: center; + padding: 10px; + flex-direction: column; +} + +.title { + color: #222222; + font: $font_14_semibold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; +} + +.progress { + position: relative; + height: 20px; + width: 100%; + cursor: pointer; + + &::after { + content: ' '; + top: 9px; + left: 0; + width: 100%; + height: 2px; + background: #222222; + position: absolute; + border-radius: 2px; + opacity: 0.5; + } +} + +.bar { + top: 7px; + left: 0; + width: 100%; + height: 6px; + background: #222222; + position: absolute; + border-radius: 2px; +} diff --git a/src/components/media/AudioPlayer/index.tsx b/src/components/media/AudioPlayer/index.tsx index 7078d4db..8494333e 100644 --- a/src/components/media/AudioPlayer/index.tsx +++ b/src/components/media/AudioPlayer/index.tsx @@ -86,10 +86,11 @@ const AudioPlayerUnconnected = ({ {playing && status === PLAYER_STATES.PLAYING ? : }
+
{title || 'Unknown'}
+
-
{title || 'Unknown'}
); diff --git a/src/containers/main/BottomContainer/styles.scss b/src/containers/main/BottomContainer/styles.scss index 9354d2f4..f7582455 100644 --- a/src/containers/main/BottomContainer/styles.scss +++ b/src/containers/main/BottomContainer/styles.scss @@ -1,10 +1,10 @@ .wrap { position: fixed; transform: translateZ(0); - bottom: $gap; + bottom: 0; pointer-events: none; touch-action: none; - height: 54px; + height: 64px; display: flex; z-index: 10; width: 100%; diff --git a/src/containers/main/MainLayout/styles.scss b/src/containers/main/MainLayout/styles.scss index 5909cbb7..d98cb981 100644 --- a/src/containers/main/MainLayout/styles.scss +++ b/src/containers/main/MainLayout/styles.scss @@ -14,6 +14,6 @@ width: 100%; max-width: $content_width; display: flex; - padding-bottom: 10px; + padding-bottom: 64px; flex-direction: column; } diff --git a/src/containers/node/NodeLayout/index.tsx b/src/containers/node/NodeLayout/index.tsx index 02d7b10b..4153147b 100644 --- a/src/containers/node/NodeLayout/index.tsx +++ b/src/containers/node/NodeLayout/index.tsx @@ -56,6 +56,7 @@ const NodeLayoutUnconnected: FC = ({ }, [node, nodeUpdateTags] ); + const block = node && node.type && NODE_COMPONENTS[node.type] && NODE_COMPONENTS[node.type]; return (