diff --git a/app/src/component/mediaPlayer/view.js b/app/src/component/mediaPlayer/view.js index 2caafc3..6033f2d 100644 --- a/app/src/component/mediaPlayer/view.js +++ b/app/src/component/mediaPlayer/view.js @@ -93,9 +93,8 @@ class MediaPlayer extends React.PureComponent { } if (this.state.firstPlay) { - if (NativeModules.Mixpanel) { - const { uri } = this.props; - NativeModules.Mixpanel.track('Play', { Uri: uri }); + if (this.props.onPlaybackStarted) { + this.props.onPlaybackStarted(); } this.setState({ firstPlay: false }); this.hidePlayerControls(); diff --git a/app/src/page/file/view.js b/app/src/page/file/view.js index dece2a0..a1be260 100644 --- a/app/src/page/file/view.js +++ b/app/src/page/file/view.js @@ -1,5 +1,6 @@ import React from 'react'; import { Lbry, normalizeURI } from 'lbry-redux'; +import { Lbryio } from 'lbryinc'; import { ActivityIndicator, Alert, @@ -38,11 +39,14 @@ class FilePage extends React.PureComponent { player = null; + startTime = null; + constructor(props) { super(props); this.state = { + fileViewLogged: false, mediaLoaded: false, - autoplayMedia: false, + autoPlayMedia: false, downloadButtonShown: false, downloadPressed: false, fullscreenMode: false, @@ -73,7 +77,7 @@ class FilePage extends React.PureComponent { } } - componentDidUpdate() { + componentDidUpdate(prevProps) { this.fetchFileInfo(this.props); const { isResolvingUri, resolveUri, claim, navigation } = this.props; const { uri } = navigation.state.params; @@ -81,6 +85,18 @@ class FilePage extends React.PureComponent { if (!isResolvingUri && claim === undefined && 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) { @@ -127,7 +143,7 @@ class FilePage extends React.PureComponent { { text: 'No' }, { text: 'Yes', onPress: () => { deleteFile(fileInfo.outpoint, true); - this.setState({ downloadPressed: false, mediaLoaded: false }); + this.setState({ downloadPressed: false, fileViewLogged: false, mediaLoaded: false }); }} ], { cancelable: true } @@ -144,7 +160,7 @@ class FilePage extends React.PureComponent { { text: 'No' }, { text: 'Yes', onPress: () => { stopDownload(navigation.state.params.uri, fileInfo); - this.setState({ downloadPressed: false, mediaLoaded: false }); + this.setState({ downloadPressed: false, fileViewLogged: false, mediaLoaded: false }); } } ], { 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() { const { claim, @@ -320,7 +379,10 @@ class FilePage extends React.PureComponent { style={filePageStyle.downloadButton} openFile={openFile} 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 })} />} {!fileInfo && } @@ -331,25 +393,21 @@ class FilePage extends React.PureComponent { this.setState({ playerBgHeight: evt.nativeEvent.layout.height }); } }} />} - {canLoadMedia && fileInfo && { this.player = ref; }} - uri={uri} - style={playerStyle} - autoPlay={this.state.autoPlayMedia} - onFullscreenToggled={this.handleFullscreenToggle} - onMediaLoaded={() => { - this.setState({ mediaLoaded: true }); - window.currentMediaInfo = { - title: title, - channel: channelName - }; - }} - onLayout={(evt) => { - if (!this.state.playerHeight) { - this.setState({ playerHeight: evt.nativeEvent.layout.height }); - } - }} - />} + {canLoadMedia && fileInfo && { this.player = ref; }} + uri={uri} + style={playerStyle} + autoPlay={this.state.autoPlayMedia} + onFullscreenToggled={this.handleFullscreenToggle} + onLayout={(evt) => { + if (!this.state.playerHeight) { + this.setState({ playerHeight: evt.nativeEvent.layout.height }); + } + }} + onMediaLoaded={() => this.onMediaLoaded(title, channelName)} + onPlaybackStarted={this.onPlaybackStarted} + />} { showActions && diff --git a/app/src/redux/actions/file.js b/app/src/redux/actions/file.js index 06a9555..ec10e47 100644 --- a/app/src/redux/actions/file.js +++ b/app/src/redux/actions/file.js @@ -9,7 +9,7 @@ import { makeSelectMetadataForUri, selectDownloadingByOutpoint, } from 'lbry-redux'; -import { Lbryio, doClaimEligiblePurchaseRewards } from 'lbryinc'; +import { doClaimEligiblePurchaseRewards } from 'lbryinc'; import { Alert, NativeModules } from 'react-native'; import Constants from '../../constants'; @@ -140,16 +140,8 @@ export function doStopDownloadingFile(uri, fileInfo) { export function doDownloadFile(uri, streamInfo) { return dispatch => { - const { outpoint, claim_id: claimId } = streamInfo; + const { outpoint } = streamInfo; dispatch(doStartDownload(uri, outpoint)); - - // log the view - Lbryio.call('file', 'view', { - uri, - outpoint, - claim_id: claimId - }).catch(() => {}); - dispatch(doClaimEligiblePurchaseRewards()); }; }