diff --git a/src/renderer/js/component/media/index.js b/src/renderer/js/component/media/index.js index a23d35fda9f..4713a1e7bc5 100644 --- a/src/renderer/js/component/media/index.js +++ b/src/renderer/js/component/media/index.js @@ -13,7 +13,7 @@ import { import { makeSelectCostInfoForUri } from "redux/selectors/cost_info"; import { selectShowNsfw } from "redux/selectors/settings"; import Media from "./view"; -import { selectPlayingUri } from "redux/selectors/content"; +import { selectPlayingUri, selectOverlayable } from "redux/selectors/content"; const select = (state, props) => ({ costInfo: makeSelectCostInfoForUri(props.uri)(state), @@ -23,6 +23,7 @@ const select = (state, props) => ({ isLoading: makeSelectLoadingForUri(props.uri)(state), isDownloading: makeSelectDownloadingForUri(props.uri)(state), playingUri: selectPlayingUri(state), + overlayable: selectOverlayable(state), contentType: makeSelectContentTypeForUri(props.uri)(state), }); diff --git a/src/renderer/js/component/media/view.jsx b/src/renderer/js/component/media/view.jsx index 2453e7748ea..fc80e1fa131 100644 --- a/src/renderer/js/component/media/view.jsx +++ b/src/renderer/js/component/media/view.jsx @@ -54,27 +54,43 @@ class Media extends React.PureComponent { } determineClasses(isPlaying, mediaType) { - const { isLoading, isDownloading } = this.props; + const { isLoading, isDownloading, overlay, overlayable } = this.props; let classes = []; classes.push(this.isNSFW() ? "video--obscured " : ""); - if (isLoading || isDownloading) classes.push("video-embedded", "video"); + if (isLoading || isDownloading) classes.push("media-embedded", "video"); if (mediaType === "video") { - classes.push("video-embedded", "video"); + classes.push("media-embedded", "video"); classes.push(isPlaying ? "video--active" : "video--hidden"); } else if (mediaType === "application") { - classes.push("video-embedded"); - } else { - if (!isPlaying) classes.push("video-embedded"); + classes.push("media-embedded"); + } else if (!isPlaying) { + classes.push("media-embedded"); } + if (overlay && overlayable) { + classes.push("overlay"); - return classes.join(" "); + // We remove media-embedded on the overlay + if (classes.indexOf("media-embedded") != -1) { + classes.splice(classes.indexOf("media-embedded"), 1); + } + } + + return classes.join(" ").trim(); } render() { - const { metadata, playingUri, fileInfo, contentType, uri } = this.props; + const { + metadata, + playingUri, + fileInfo, + contentType, + uri, + overlay, + overlayable, + } = this.props; const isPlaying = playingUri === uri; const isReadyToPlay = fileInfo && fileInfo.written_bytes > 0; @@ -83,6 +99,10 @@ class Media extends React.PureComponent { fileInfo && fileInfo.file_name ); + if (overlay && !overlayable) { + return null; + } + return (
) : ( - + ))} {!isPlaying && (
; + return ; } return null; diff --git a/src/renderer/js/component/videoPlayer/index.js b/src/renderer/js/component/videoPlayer/index.js index 3487bc81248..d6b31b0064b 100644 --- a/src/renderer/js/component/videoPlayer/index.js +++ b/src/renderer/js/component/videoPlayer/index.js @@ -2,7 +2,11 @@ import React from "react"; import { connect } from "react-redux"; import { doChangeVolume } from "redux/actions/app"; import { doNavigate } from "redux/actions/navigation"; -import { doSetPlayingUri, doSetTime } from "redux/actions/content"; +import { + doSetPlayingUri, + doSetTime, + doSetOverlayable, +} from "redux/actions/content"; import { makeSelectMetadataForUri, makeSelectContentTypeForUri, @@ -25,6 +29,7 @@ const perform = dispatch => ({ setTime: currentTime => dispatch(doSetTime(currentTime)), changeVolume: volume => dispatch(doChangeVolume(volume)), cancelPlay: () => dispatch(doSetPlayingUri(null)), + setOverlayable: overlayable => dispatch(doSetOverlayable(overlayable)), }); export default connect(select, perform)(VideoPlayer); diff --git a/src/renderer/js/component/videoPlayer/view.jsx b/src/renderer/js/component/videoPlayer/view.jsx index 50a42788e25..43698b3a4d5 100644 --- a/src/renderer/js/component/videoPlayer/view.jsx +++ b/src/renderer/js/component/videoPlayer/view.jsx @@ -31,7 +31,6 @@ class VideoPlayer extends React.PureComponent { filename: _filename, downloadPath: _downloadPath, completed: _completed, - overlayable: false, }; this.togglePlayListener = this.togglePlay.bind(this); @@ -47,10 +46,8 @@ class VideoPlayer extends React.PureComponent { }; const renderMediaCallback = err => { if (err) { - this.setState({ - unplayable: true, - overlayable: false, - }); + this.setState({ unplayable: true }); + this.props.setOverlayable(false); } }; // Handle fullscreen change for the Windows platform @@ -66,9 +63,9 @@ class VideoPlayer extends React.PureComponent { // not all media is "overlayable" so this has to manually set/unset for such media // by default it is true for A/V, but it is set to false if the player errs if (["video", "audio"].indexOf(mediaType) !== -1) { - this.setState({ overlayable: true }); + this.props.setOverlayable(true); } else { - this.setState({ overlayable: false }); + this.props.setOverlayable(false); } // use renderAudio override for mp3 @@ -124,7 +121,7 @@ class VideoPlayer extends React.PureComponent { mediaElement.removeEventListener("click", this.togglePlayListener); const currentTime = mediaElement.currentTime; if (currentTime) { - this.props.setTime(mediaElement.currentTime); + this.props.setTime(currentTime); } } } @@ -140,6 +137,7 @@ class VideoPlayer extends React.PureComponent { audio.autoplay = autoplay; audio.controls = true; audio.src = downloadPath; + audio.style = "width: 100%;"; container.appendChild(audio); } @@ -197,46 +195,47 @@ class VideoPlayer extends React.PureComponent { return ["audio", "video"].indexOf(mediaType) !== -1; } + displayOverlayButtons() { + const { uri, navigate, cancelPlay } = this.props; + return ( +
+ cancelPlay()} + /> + navigate("/show", { uri })} + /> +
+ ); + } + render() { - const { metadata, overlay, uri, cancelPlay, navigate } = this.props; - const { mediaType } = this.state; - const { hasMetadata, unplayable, overlayable } = this.state; + const { metadata, overlay } = this.props; + const { hasMetadata, unplayable, mediaType } = this.state; const noMetadataMessage = "Waiting for metadata."; const unplayableMessage = "Sorry, looks like we can't play this file."; const poster = metadata.thumbnail; const needsMetadata = this.isPlayableType(); - const displayOverlay = overlay && overlayable; return ( -
+
{["audio", "application"].indexOf(mediaType) !== -1 && - !displayOverlay && (!this.isPlayableType() || hasMetadata) && - !unplayable && } + !unplayable && } {this.isPlayableType() && - !displayOverlay && !hasMetadata && - !unplayable && } + !unplayable && + !overlay && } {unplayable && - (!displayOverlay && ( + !overlay && ( - ))} - - {displayOverlay && ( - cancelPlay()} - /> - )} - {displayOverlay && ( - navigate("/show", { uri })} - /> - )} + )} + {overlay && this.displayOverlayButtons()}
(this.media = ref)} className="media" />
diff --git a/src/renderer/js/constants/action_types.js b/src/renderer/js/constants/action_types.js index 9ff8dde10e0..89b7f35db50 100644 --- a/src/renderer/js/constants/action_types.js +++ b/src/renderer/js/constants/action_types.js @@ -8,6 +8,7 @@ export const DAEMON_VERSION_MATCH = "DAEMON_VERSION_MATCH"; export const DAEMON_VERSION_MISMATCH = "DAEMON_VERSION_MISMATCH"; export const VOLUME_CHANGED = "VOLUME_CHANGED"; export const SET_CURRENT_TIME = "SET_CURRENT_TIME"; +export const SET_OVERLAYABLE = "SET_OVERLAYABLE"; // Navigation export const CHANGE_AFTER_AUTH_PATH = "CHANGE_AFTER_AUTH_PATH"; diff --git a/src/renderer/js/page/file/view.jsx b/src/renderer/js/page/file/view.jsx index 131b726a2e7..6d00fbb2e27 100644 --- a/src/renderer/js/page/file/view.jsx +++ b/src/renderer/js/page/file/view.jsx @@ -66,7 +66,7 @@ class FilePage extends React.PureComponent {
{isPlayable ? ( - + ) : metadata && metadata.thumbnail ? ( ) : ( diff --git a/src/renderer/js/redux/actions/content.js b/src/renderer/js/redux/actions/content.js index c3bba57123c..f4fc5c2674b 100644 --- a/src/renderer/js/redux/actions/content.js +++ b/src/renderer/js/redux/actions/content.js @@ -547,3 +547,12 @@ export function doSetTime(currentTime) { }); }; } + +export function doSetOverlayable(overlayable) { + return function(dispatch, getState) { + dispatch({ + type: types.SET_OVERLAYABLE, + data: { overlayable }, + }); + }; +} diff --git a/src/renderer/js/redux/reducers/content.js b/src/renderer/js/redux/reducers/content.js index 362ac208782..e7f82bbaff8 100644 --- a/src/renderer/js/redux/reducers/content.js +++ b/src/renderer/js/redux/reducers/content.js @@ -89,6 +89,12 @@ reducers[types.SET_CURRENT_TIME] = function(state, action) { }); }; +reducers[types.SET_OVERLAYABLE] = function(state, action) { + return Object.assign({}, state, { + overlayable: action.data.overlayable, + }); +}; + export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; if (handler) return handler(state, action); diff --git a/src/renderer/js/redux/selectors/content.js b/src/renderer/js/redux/selectors/content.js index 08ad21adddb..ee682380616 100644 --- a/src/renderer/js/redux/selectors/content.js +++ b/src/renderer/js/redux/selectors/content.js @@ -54,3 +54,8 @@ export const selectCurrentTime = createSelector( _selectState, state => state.currentTime ); + +export const selectOverlayable = createSelector( + _selectState, + state => state.overlayable +); diff --git a/src/renderer/scss/_vars.scss b/src/renderer/scss/_vars.scss index 44c6087aafd..2ad4d6e2bbf 100644 --- a/src/renderer/scss/_vars.scss +++ b/src/renderer/scss/_vars.scss @@ -27,7 +27,7 @@ $text-color: #000; /* Misc */ --content-max-width: 1000px; --nsfw-blur-intensity: 20px; - --height-video-embedded: $width-page-constrained * 9 / 16 ; + --height-media-embedded: $width-page-constrained * 9 / 16 ; /* Font */ --font-size: 16px; diff --git a/src/renderer/scss/component/_video.scss b/src/renderer/scss/component/_video.scss index dbe5f91b6b7..1113e80b4f7 100644 --- a/src/renderer/scss/component/_video.scss +++ b/src/renderer/scss/component/_video.scss @@ -1,5 +1,5 @@ -$height-video-embedded: $width-page-constrained * 9 / 16; +$height-media-embedded: $width-page-constrained * 9 / 16; video { object-fit: contain; @@ -16,10 +16,10 @@ video { color: white; } -.video-embedded { +.media-embedded { max-width: $width-page-constrained; - max-height: $height-video-embedded; - height: $height-video-embedded; + max-height: $height-media-embedded; + height: $height-media-embedded; position: relative; video { height: 100%; @@ -29,7 +29,7 @@ video { left: 0; } &.video--hidden { - height: $height-video-embedded; + height: $height-media-embedded; } } .video--obscured .video__cover @@ -134,48 +134,46 @@ video { .overlay { position: fixed; - max-height: 50%; - max-width: 50%; - width: 20%; - height: inherit; - bottom: 1%; - right: 1%; + max-width: 25%; + bottom: 2%; + right: 2%; z-index: 3; + border: black solid 1px; + box-sizing: border-box; box-shadow: var(--box-shadow-layer); - &:hover .button-close { - display: inline-block; - background: rgba(0, 0, 0, 0.5); - position: absolute; - height: 22px; - width: 22px; - top: 0px; - right: 0px; - color: #FFF; - text-align: center; - cursor: pointer; - z-index: 4; + .button-close, + .button-open-page { + display: none; } - &:hover .button-open-page { - display: inline-block; - background: rgba(0, 0, 0, 0.5); - position: absolute; - height: 22px; - width: 22px; - top: 0px; - left: 0px; - color: #FFF; - text-align: center; - cursor: pointer; - z-index: 4; + &:hover{ + .button-close, + .button-open-page { + display: inline-block; + background: rgba(0, 0, 0, 0.5); + position: absolute; + height: 22px; + width: 22px; + top: 0px; + color: #FFF; + text-align: center; + cursor: pointer; + z-index: 4; + } + + .button-close { + right: 0px; + } + + .button-open-page { + left: 0px; + } } -} -.overlay .button-close { - display: none; + img { + width: 100%; + height: auto; + } } -.overlay .button-open-page { - display: none; -}