First run timing (#83)
* first run time tracking implementation * Fix values in AsyncStorage calls. Some tweaks to Mixpanel event properties. * remove first launch related items in AsyncStorage after final retrieval
This commit is contained in:
parent
77a86da984
commit
90d17604fc
9 changed files with 66 additions and 18 deletions
|
@ -8,6 +8,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"lbry-redux": "lbryio/lbry-redux",
|
||||
"moment": "^2.22.1",
|
||||
"react": "16.2.0",
|
||||
"react-native": "0.52.0",
|
||||
"react-native-vector-icons": "^4.5.0",
|
||||
|
|
|
@ -14,7 +14,13 @@ import {
|
|||
} from 'react-navigation';
|
||||
import { connect } from 'react-redux';
|
||||
import { addListener } from '../utils/redux';
|
||||
import { AppState, BackHandler, NativeModules, TextInput } from 'react-native';
|
||||
import {
|
||||
AppState,
|
||||
AsyncStorage,
|
||||
BackHandler,
|
||||
NativeModules,
|
||||
TextInput
|
||||
} from 'react-native';
|
||||
import { SETTINGS } from 'lbry-redux';
|
||||
import { makeSelectClientSetting } from '../redux/selectors/settings';
|
||||
import Feather from 'react-native-vector-icons/Feather';
|
||||
|
@ -102,16 +108,16 @@ class AppWithNavigationState extends React.Component {
|
|||
}
|
||||
|
||||
_handleAppStateChange = (nextAppState) => {
|
||||
// this is properly handled in native code at the moment
|
||||
/*const { keepDaemonRunning } = this.props;
|
||||
if (AppState.currentState &&
|
||||
AppState.currentState.match(/inactive|background/) &&
|
||||
NativeModules.DaemonServiceControl) {
|
||||
if (!keepDaemonRunning) {
|
||||
// terminate the daemon background service when is suspended / inactive
|
||||
//NativeModules.DaemonServiceControl.stopService();
|
||||
// Check if the app was suspended
|
||||
if (AppState.currentState && AppState.currentState.match(/inactive|background/)) {
|
||||
AsyncStorage.getItem('firstLaunchTime').then(start => {
|
||||
if (start !== null && !isNaN(parseInt(start, 10))) {
|
||||
// App suspended during first launch?
|
||||
// If so, this needs to be included as a property when tracking
|
||||
AsyncStorage.setItem('firstLaunchSuspended', 'true');
|
||||
}
|
||||
});
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -61,7 +61,7 @@ class FileDownloadButton extends React.PureComponent {
|
|||
return (
|
||||
<TouchableOpacity style={[style, fileDownloadButtonStyle.container]} onPress={() => {
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('Purchase Uri', { uri });
|
||||
NativeModules.Mixpanel.track('Purchase Uri', { Uri: uri });
|
||||
}
|
||||
purchaseUri(uri);
|
||||
}}>
|
||||
|
|
|
@ -59,7 +59,7 @@ class FileItem extends React.PureComponent {
|
|||
<View style={style}>
|
||||
<TouchableOpacity style={discoverStyle.container} onPress={() => {
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('Tap', { uri });
|
||||
NativeModules.Mixpanel.track('Discover Tap', { Uri: uri });
|
||||
}
|
||||
navigation.navigate('File', { uri: uri });
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ class MediaPlayer extends React.PureComponent {
|
|||
if (this.state.firstPlay) {
|
||||
if (NativeModules.Mixpanel) {
|
||||
const { uri } = this.props;
|
||||
NativeModules.Mixpanel.track('Play', { uri });
|
||||
NativeModules.Mixpanel.track('Play', { Uri: uri });
|
||||
}
|
||||
this.setState({ firstPlay: false });
|
||||
this.hidePlayerControls();
|
||||
|
|
|
@ -6,7 +6,7 @@ import SearchInput from './view';
|
|||
const perform = dispatch => ({
|
||||
search: search => {
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('Search', { query: search });
|
||||
NativeModules.Mixpanel.track('Search', { Query: search });
|
||||
}
|
||||
return dispatch(doSearch(search));
|
||||
},
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
import React from 'react';
|
||||
import { Provider, connect } from 'react-redux';
|
||||
import DiscoverPage from './page/discover';
|
||||
import { AppRegistry, AppState, StyleSheet, Text, View, AsyncStorage, NativeModules } from 'react-native';
|
||||
import {
|
||||
AppRegistry,
|
||||
AppState,
|
||||
AsyncStorage,
|
||||
Text,
|
||||
View,
|
||||
NativeModules
|
||||
} from 'react-native';
|
||||
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
|
||||
import {
|
||||
StackNavigator, addNavigationHelpers
|
||||
|
@ -21,6 +28,7 @@ import {
|
|||
walletReducer
|
||||
} from 'lbry-redux';
|
||||
import settingsReducer from './redux/reducers/settings';
|
||||
import moment from 'moment';
|
||||
import { reactNavigationMiddleware } from './utils/redux';
|
||||
|
||||
function isFunction(object) {
|
||||
|
@ -105,6 +113,16 @@ persistStore(store, persistOptions, err => {
|
|||
});
|
||||
|
||||
class LBRYApp extends React.Component {
|
||||
componentDidMount() {
|
||||
AsyncStorage.getItem('hasLaunched').then(value => {
|
||||
if (value == null || value !== 'true') {
|
||||
AsyncStorage.setItem('hasLaunched', 'true');
|
||||
// only set firstLaunchTime since we've determined that this is the first app launch ever
|
||||
AsyncStorage.setItem('firstLaunchTime', String(moment().unix()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
|
|
|
@ -1,12 +1,35 @@
|
|||
import React from 'react';
|
||||
import FeaturedCategory from '../../component/featuredCategory';
|
||||
import NavigationActions from 'react-navigation';
|
||||
import { Text, View, ScrollView } from 'react-native';
|
||||
import { AsyncStorage, NativeModules, ScrollView, Text, View } from 'react-native';
|
||||
import moment from 'moment';
|
||||
import discoverStyle from '../../styles/discover';
|
||||
import Feather from 'react-native-vector-icons/Feather';
|
||||
|
||||
class DiscoverPage extends React.PureComponent {
|
||||
componentWillMount() {
|
||||
// Track the total time taken if this is the first launch
|
||||
AsyncStorage.getItem('firstLaunchTime').then(startTime => {
|
||||
if (startTime !== null && !isNaN(parseInt(startTime, 10))) {
|
||||
// We don't need this value anymore once we've retrieved it
|
||||
AsyncStorage.removeItem('firstLaunchTime');
|
||||
|
||||
// We know this is the first app launch because firstLaunchTime is set and it's a valid number
|
||||
const start = parseInt(startTime, 10);
|
||||
const now = moment().unix();
|
||||
const delta = now - start;
|
||||
AsyncStorage.getItem('firstLaunchSuspended').then(suspended => {
|
||||
AsyncStorage.removeItem('firstLaunchSuspended');
|
||||
const appSuspended = (suspended === 'true');
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('First Run Time', {
|
||||
'Total Seconds': delta, 'App Suspended': appSuspended
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.props.fetchFeaturedUris();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class FilePage extends React.PureComponent {
|
|||
this.fetchFileInfo(this.props);
|
||||
this.fetchCostInfo(this.props);
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('Open File Page', { uri: this.props.navigation.state.params.uri });
|
||||
NativeModules.Mixpanel.track('Open File Page', { Uri: this.props.navigation.state.params.uri });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue