feat: autoplay next file in related list

This commit is contained in:
Sean Yesmunt 2019-01-28 15:05:28 -05:00
parent fbb9c9fd35
commit af35e87dc6
7 changed files with 78 additions and 53 deletions

View file

@ -51,6 +51,7 @@
"flowtype/space-after-type-colon": [2, "always", { "allowLineBreak": true }],
"no-restricted-syntax": 0,
"no-empty": 0,
"react/prefer-stateless-function": 0
"react/prefer-stateless-function": 0,
"react/sort-comp": 0
}
}

View file

@ -3,6 +3,7 @@ import * as settings from 'constants/settings';
import { doChangeVolume } from 'redux/actions/app';
import { selectVolume } from 'redux/selectors/app';
import { doPlayUri, doSetPlayingUri, savePosition } from 'redux/actions/content';
import { doNavigate } from 'redux/actions/navigation';
import { doClaimEligiblePurchaseRewards } from 'lbryinc';
import {
makeSelectMetadataForUri,
@ -13,6 +14,7 @@ import {
makeSelectLoadingForUri,
makeSelectDownloadingForUri,
selectSearchBarFocused,
makeSelectFirstRecommendedFileForUri,
} from 'lbry-redux';
import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings';
import { selectPlayingUri, makeSelectContentPositionForUri } from 'redux/selectors/content';
@ -34,6 +36,7 @@ const select = (state, props) => ({
autoplay: makeSelectClientSetting(settings.AUTOPLAY)(state),
searchBarFocused: selectSearchBarFocused(state),
fileInfoErrors: selectFileInfoErrors(state),
nextFileToPlay: makeSelectFirstRecommendedFileForUri(props.uri)(state),
});
const perform = dispatch => ({
@ -43,6 +46,7 @@ const perform = dispatch => ({
claimRewards: () => dispatch(doClaimEligiblePurchaseRewards()),
savePosition: (claimId, outpoint, position) =>
dispatch(savePosition(claimId, outpoint, position)),
navigate: (path, params) => dispatch(doNavigate(path, params)),
});
export default connect(

View file

@ -46,14 +46,15 @@ class MediaPlayer extends React.PureComponent {
volume,
position,
claim,
startedPlayingCb,
onStartCb,
onFinishCb,
} = this.props;
const loadedMetadata = () => {
this.setState({ hasMetadata: true, startedPlaying: true });
if (startedPlayingCb) {
startedPlayingCb();
if (onStartCb) {
onStartCb();
}
this.media.children[0].play();
};
@ -105,6 +106,11 @@ class MediaPlayer extends React.PureComponent {
mediaElement.addEventListener('loadedmetadata', loadedMetadata.bind(this), {
once: true,
});
mediaElement.addEventListener('ended', () => {
if (onFinishCb) {
onFinishCb();
}
});
mediaElement.addEventListener('webkitfullscreenchange', win32FullScreenChange.bind(this));
mediaElement.addEventListener('volumechange', () => {
changeVolume(mediaElement.volume);

View file

@ -1,4 +1,5 @@
// @flow
import * as PAGES from 'constants/pages';
import React from 'react';
import classnames from 'classnames';
import analytics from 'analytics';
@ -42,7 +43,9 @@ type Props = {
searchBarFocused: boolean,
mediaType: string,
claimRewards: () => void,
costInfo: ?{ cost: number },
nextFileToPlay: ?string,
navigate: (string, {}) => void,
costInfo: ?{ cost: number }, // eslint-disable-line react/no-unused-prop-types
};
class FileViewer extends React.PureComponent<Props> {
@ -51,7 +54,8 @@ class FileViewer extends React.PureComponent<Props> {
(this: any).playContent = this.playContent.bind(this);
(this: any).handleKeyDown = this.handleKeyDown.bind(this);
(this: any).logTimeToStart = this.logTimeToStart.bind(this);
(this: any).startedPlayingCb = undefined;
(this: any).onFileFinishCb = this.onFileFinishCb.bind(this);
(this: any).onFileStartCb = undefined;
// Don't add these variables to state because we don't need to re-render when their values change
(this: any).startTime = undefined;
@ -61,7 +65,7 @@ class FileViewer extends React.PureComponent<Props> {
componentDidMount() {
const { fileInfo } = this.props;
if (!fileInfo) {
this.startedPlayingCb = this.logTimeToStart;
this.onFileStartCb = this.logTimeToStart;
}
this.handleAutoplay(this.props);
@ -83,10 +87,10 @@ class FileViewer extends React.PureComponent<Props> {
this.playTime = null;
// If this new file is already downloaded, remove the startedPlayingCallback
if (fileInfo && this.startedPlayingCb) {
this.startedPlayingCb = null;
} else if (!fileInfo && !this.startedPlayingCb) {
this.startedPlayingCb = this.logTimeToStart;
if (fileInfo && this.onFileStartCb) {
this.onFileStartCb = null;
} else if (!fileInfo && !this.onFileStartCb) {
this.onFileStartCb = this.logTimeToStart;
}
}
@ -149,10 +153,10 @@ class FileViewer extends React.PureComponent<Props> {
if (fileInfo || isDownloading || isLoading) {
// User may have pressed download before clicking play
this.startedPlayingCb = null;
this.onFileStartCb = null;
}
if (this.startedPlayingCb) {
if (this.onFileStartCb) {
this.startTime = Date.now();
}
@ -184,7 +188,15 @@ class FileViewer extends React.PureComponent<Props> {
analytics.apiLogView(`${name}#${claimId}`, outpoint, claimId, timeToStart, claimRewards);
}
startedPlayingCb: ?() => void;
onFileFinishCb() {
// If a user has `autoplay` enabled, start playing the next file at the top of "related"
const { autoplay, nextFileToPlay, navigate } = this.props;
if (autoplay && nextFileToPlay) {
navigate(PAGES.SHOW, { uri: nextFileToPlay });
}
}
onFileStartCb: ?() => void;
startTime: ?number;
playTime: ?number;
@ -251,7 +263,8 @@ class FileViewer extends React.PureComponent<Props> {
claim={claim}
uri={uri}
position={position}
startedPlayingCb={this.startedPlayingCb}
onStartCb={this.onFileStartCb}
onFinishCb={this.onFileFinishCb}
playingUri={playingUri}
/>
)}

View file

@ -4,7 +4,6 @@ import type { FileInfo } from 'types/file_info';
import * as MODALS from 'constants/modal_types';
import * as icons from 'constants/icons';
import * as React from 'react';
import * as settings from 'constants/settings';
import { buildURI, normalizeURI } from 'lbry-redux';
import FileViewer from 'component/fileViewer';
import Thumbnail from 'component/common/thumbnail';
@ -41,7 +40,6 @@ type Props = {
prepareEdit: ({}, string) => void,
navigate: (string, ?{}) => void,
openModal: (id: string, { uri: string }) => void,
setClientSetting: (string, string | boolean | number) => void,
markSubscriptionRead: (string, string) => void,
};
@ -59,12 +57,6 @@ class FilePage extends React.Component<Props> {
'application',
];
constructor(props: Props) {
super(props);
(this: any).onAutoplayChange = this.onAutoplayChange.bind(this);
}
componentDidMount() {
const { uri, fileInfo, fetchFileInfo, fetchCostInfo, setViewed, isSubscribed } = this.props;
@ -98,10 +90,6 @@ class FilePage extends React.Component<Props> {
}
}
onAutoplayChange(event: SyntheticInputEvent<*>) {
this.props.setClientSetting(settings.AUTOPLAY, event.target.checked);
}
removeFromSubscriptionNotifications() {
// Always try to remove
// If it doesn't exist, nothing will happen

View file

@ -287,26 +287,6 @@ class SettingsPage extends React.PureComponent<Props, State> {
</header>
<div className="card__content">
<FormRow>
<FormField
type="checkbox"
name="autoplay"
onChange={this.onAutoplayChange}
checked={autoplay}
postfix={__('Autoplay media files')}
/>
</FormRow>
<FormRow>
<FormField
type="checkbox"
name="auto_download"
onChange={this.onAutoDownloadChange}
checked={autoDownload}
postfix={__('Automatically download new content from your subscriptions')}
/>
</FormRow>
<FormRow>
<FormField
type="checkbox"
@ -420,6 +400,39 @@ class SettingsPage extends React.PureComponent<Props, State> {
</div>
</section>
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Experimental Settings')}</h2>
</header>
<div className="card__content">
<FormRow>
<FormField
type="checkbox"
name="auto_download"
onChange={this.onAutoDownloadChange}
checked={autoDownload}
postfix={__('Automatically download new content from my subscriptions')}
helper={__(
"The latest file from each of your subscriptions will be downloaded for quick access as soon as it's published."
)}
/>
</FormRow>
<FormRow>
<FormField
type="checkbox"
name="autoplay"
onChange={this.onAutoplayChange}
checked={autoplay}
postfix={__('Autoplay media files')}
helper={__(
'Autoplay video and audio files when navigating to a file, as well as the next related item when a file finishes playing.'
)}
/>
</FormRow>
</div>
</section>
<section className="card card--section">
<header className="card__header">
<h2 className="card__title">{__('Application Cache')}</h2>

View file

@ -18,7 +18,6 @@ import {
makeSelectFileInfoForUri,
selectFileInfosByOutpoint,
selectDownloadingByOutpoint,
selectTotalDownloadProgress,
selectBalance,
makeSelectChannelForClaimUri,
parseURI,
@ -27,7 +26,6 @@ import {
} from 'lbry-redux';
import { makeSelectClientSetting, selectosNotificationsEnabled } from 'redux/selectors/settings';
import setBadge from 'util/set-badge';
import setProgressBar from 'util/set-progress-bar';
import analytics from 'analytics';
const DOWNLOAD_POLL_INTERVAL = 250;
@ -66,8 +64,10 @@ export function doUpdateLoadStatus(uri: string, outpoint: string) {
const badgeNumber = selectBadgeNumber(state);
setBadge(badgeNumber === 0 ? '' : `${badgeNumber}`);
const totalProgress = selectTotalDownloadProgress(state);
setProgressBar(totalProgress);
// Disabling this for now because it's confusing for new users that don't realize files are actually being downloaded
// This should move inside of the app
// const totalProgress = selectTotalDownloadProgress(state);
// setProgressBar(totalProgress);
const channelUri = makeSelectChannelForClaimUri(uri, true)(state);
const { claimName: channelName } = parseURI(channelUri);
@ -120,8 +120,8 @@ export function doUpdateLoadStatus(uri: string, outpoint: string) {
},
});
const totalProgress = selectTotalDownloadProgress(getState());
setProgressBar(totalProgress);
// const totalProgress = selectTotalDownloadProgress(getState());
// setProgressBar(totalProgress);
setNextStatusUpdate();
}
});