add time to start (in seconds) to Play track event for new downloads #269

Merged
akinwale merged 3 commits from time-to-start into master 2018-08-30 19:11:04 +02:00
3 changed files with 86 additions and 37 deletions

View file

@ -93,9 +93,8 @@ class MediaPlayer extends React.PureComponent {
} }
if (this.state.firstPlay) { if (this.state.firstPlay) {
if (NativeModules.Mixpanel) { if (this.props.onPlaybackStarted) {
const { uri } = this.props; this.props.onPlaybackStarted();
NativeModules.Mixpanel.track('Play', { Uri: uri });
} }
this.setState({ firstPlay: false }); this.setState({ firstPlay: false });
this.hidePlayerControls(); this.hidePlayerControls();

View file

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { Lbry, normalizeURI } from 'lbry-redux'; import { Lbry, normalizeURI } from 'lbry-redux';
import { Lbryio } from 'lbryinc';
import { import {
ActivityIndicator, ActivityIndicator,
Alert, Alert,
@ -38,11 +39,14 @@ class FilePage extends React.PureComponent {
player = null; player = null;
startTime = null;
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
fileViewLogged: false,
mediaLoaded: false, mediaLoaded: false,
autoplayMedia: false, autoPlayMedia: false,
downloadButtonShown: false, downloadButtonShown: false,
downloadPressed: false, downloadPressed: false,
fullscreenMode: false, fullscreenMode: false,
@ -73,7 +77,7 @@ class FilePage extends React.PureComponent {
} }
} }
componentDidUpdate() { componentDidUpdate(prevProps) {
this.fetchFileInfo(this.props); this.fetchFileInfo(this.props);
const { isResolvingUri, resolveUri, claim, navigation } = this.props; const { isResolvingUri, resolveUri, claim, navigation } = this.props;
const { uri } = navigation.state.params; const { uri } = navigation.state.params;
@ -81,6 +85,18 @@ class FilePage extends React.PureComponent {
if (!isResolvingUri && claim === undefined && uri) { if (!isResolvingUri && claim === undefined && uri) {
resolveUri(uri); resolveUri(uri);
} }
const prevFileInfo = prevProps.fileInfo;
const { fileInfo, contentType } = this.props;
if (!prevFileInfo && fileInfo) {
// started downloading
const mediaType = Lbry.getMediaType(contentType);
const isPlayable = mediaType === 'video' || mediaType === 'audio';
// If the media is playable, file/view will be done in onPlaybackStarted
if (!isPlayable && !this.state.fileViewLogged) {
this.logFileView(uri, fileInfo);
}
}
} }
fetchFileInfo(props) { fetchFileInfo(props) {
@ -127,7 +143,7 @@ class FilePage extends React.PureComponent {
{ text: 'No' }, { text: 'No' },
{ text: 'Yes', onPress: () => { { text: 'Yes', onPress: () => {
deleteFile(fileInfo.outpoint, true); deleteFile(fileInfo.outpoint, true);
this.setState({ downloadPressed: false, mediaLoaded: false }); this.setState({ downloadPressed: false, fileViewLogged: false, mediaLoaded: false });
}} }}
], ],
{ cancelable: true } { cancelable: true }
@ -144,7 +160,7 @@ class FilePage extends React.PureComponent {
{ text: 'No' }, { text: 'No' },
{ text: 'Yes', onPress: () => { { text: 'Yes', onPress: () => {
stopDownload(navigation.state.params.uri, fileInfo); stopDownload(navigation.state.params.uri, fileInfo);
this.setState({ downloadPressed: false, mediaLoaded: false }); this.setState({ downloadPressed: false, fileViewLogged: false, mediaLoaded: false });
} } } }
], ],
{ cancelable: true } { cancelable: true }
@ -220,6 +236,49 @@ class FilePage extends React.PureComponent {
} }
} }
onMediaLoaded = (title, channelName) => {
this.setState({ mediaLoaded: true });
window.currentMediaInfo = {
title: title,
channel: channelName
};
}
onPlaybackStarted = () => {
let timeToStartMillis, timeToStart;
if (this.startTime) {
timeToStartMillis = Date.now() - this.startTime;
timeToStart = Math.ceil(timeToStartMillis / 1000);
this.startTime = null;
}
const { fileInfo, navigation } = this.props;
const { uri } = navigation.state.params;
this.logFileView(uri, fileInfo, timeToStartMillis);
let payload = { 'Uri': uri };
if (!isNaN(timeToStart)) {
payload['Time to Start (seconds)'] = timeToStart;
payload['Time to Start (ms)'] = timeToStartMillis;
}
NativeModules.Mixpanel.track('Play', payload);
}
logFileView = (uri, fileInfo, timeToStart) => {
const { outpoint, claim_id: claimId } = fileInfo;
const params = {
uri,
outpoint,
claim_id: claimId
};
if (!isNaN(timeToStart)) {
params.time_to_start = timeToStart;
}
Lbryio.call('file', 'view', params).catch(() => {});
this.setState({ fileViewLogged: true });
}
render() { render() {
const { const {
claim, claim,
@ -320,7 +379,10 @@ class FilePage extends React.PureComponent {
style={filePageStyle.downloadButton} style={filePageStyle.downloadButton}
openFile={openFile} openFile={openFile}
isPlayable={isPlayable} isPlayable={isPlayable}
onPlay={() => this.setState({ downloadPressed: true, autoPlayMedia: true })} onPlay={() => {
this.startTime = Date.now();
this.setState({ downloadPressed: true, autoPlayMedia: true });
}}
onButtonLayout={() => this.setState({ downloadButtonShown: true })} />} onButtonLayout={() => this.setState({ downloadButtonShown: true })} />}
{!fileInfo && <FilePrice uri={uri} style={filePageStyle.filePriceContainer} textStyle={filePageStyle.filePriceText} />} {!fileInfo && <FilePrice uri={uri} style={filePageStyle.filePriceContainer} textStyle={filePageStyle.filePriceText} />}
</View> </View>
@ -331,24 +393,20 @@ class FilePage extends React.PureComponent {
this.setState({ playerBgHeight: evt.nativeEvent.layout.height }); this.setState({ playerBgHeight: evt.nativeEvent.layout.height });
} }
}} />} }} />}
{canLoadMedia && fileInfo && <MediaPlayer fileInfo={fileInfo} {canLoadMedia && fileInfo && <MediaPlayer
fileInfo={fileInfo}
ref={(ref) => { this.player = ref; }} ref={(ref) => { this.player = ref; }}
uri={uri} uri={uri}
style={playerStyle} style={playerStyle}
autoPlay={this.state.autoPlayMedia} autoPlay={this.state.autoPlayMedia}
onFullscreenToggled={this.handleFullscreenToggle} onFullscreenToggled={this.handleFullscreenToggle}
onMediaLoaded={() => {
this.setState({ mediaLoaded: true });
window.currentMediaInfo = {
title: title,
channel: channelName
};
}}
onLayout={(evt) => { onLayout={(evt) => {
if (!this.state.playerHeight) { if (!this.state.playerHeight) {
this.setState({ playerHeight: evt.nativeEvent.layout.height }); this.setState({ playerHeight: evt.nativeEvent.layout.height });
} }
}} }}
onMediaLoaded={() => this.onMediaLoaded(title, channelName)}
onPlaybackStarted={this.onPlaybackStarted}
/>} />}
{ showActions && { showActions &&

View file

@ -9,7 +9,7 @@ import {
makeSelectMetadataForUri, makeSelectMetadataForUri,
selectDownloadingByOutpoint, selectDownloadingByOutpoint,
} from 'lbry-redux'; } from 'lbry-redux';
import { Lbryio, doClaimEligiblePurchaseRewards } from 'lbryinc'; import { doClaimEligiblePurchaseRewards } from 'lbryinc';
import { Alert, NativeModules } from 'react-native'; import { Alert, NativeModules } from 'react-native';
import Constants from '../../constants'; import Constants from '../../constants';
@ -140,16 +140,8 @@ export function doStopDownloadingFile(uri, fileInfo) {
export function doDownloadFile(uri, streamInfo) { export function doDownloadFile(uri, streamInfo) {
return dispatch => { return dispatch => {
const { outpoint, claim_id: claimId } = streamInfo; const { outpoint } = streamInfo;
dispatch(doStartDownload(uri, outpoint)); dispatch(doStartDownload(uri, outpoint));
// log the view
Lbryio.call('file', 'view', {
uri,
outpoint,
claim_id: claimId
}).catch(() => {});
dispatch(doClaimEligiblePurchaseRewards()); dispatch(doClaimEligiblePurchaseRewards());
}; };
} }