Merge pull request #68 from lbryio/mixpanel
Implemented Mixpanel analytics
This commit is contained in:
commit
a4798c3cf9
11 changed files with 98 additions and 11 deletions
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Text, View, TouchableOpacity } from 'react-native';
|
||||
import { NativeModules, Text, View, TouchableOpacity } from 'react-native';
|
||||
import fileDownloadButtonStyle from '../../styles/fileDownloadButton';
|
||||
|
||||
class FileDownloadButton extends React.PureComponent {
|
||||
|
@ -60,6 +60,9 @@ class FileDownloadButton extends React.PureComponent {
|
|||
}
|
||||
return (
|
||||
<TouchableOpacity style={[style, fileDownloadButtonStyle.container]} onPress={() => {
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('Purchase Uri', { uri });
|
||||
}
|
||||
purchaseUri(uri);
|
||||
}}>
|
||||
<Text style={fileDownloadButtonStyle.text}>Download</Text>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { normalizeURI } from 'lbry-redux';
|
||||
import { NavigationActions } from 'react-navigation';
|
||||
import { Text, View, TouchableOpacity } from 'react-native';
|
||||
import { NativeModules, Text, View, TouchableOpacity } from 'react-native';
|
||||
import FileItemMedia from '../fileItemMedia';
|
||||
import FilePrice from '../filePrice';
|
||||
import NsfwOverlay from '../nsfwOverlay';
|
||||
|
@ -58,6 +58,9 @@ class FileItem extends React.PureComponent {
|
|||
return (
|
||||
<View style={style}>
|
||||
<TouchableOpacity style={discoverStyle.container} onPress={() => {
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('Tap', { uri });
|
||||
}
|
||||
navigation.navigate('File', { uri: uri });
|
||||
}
|
||||
}>
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
import React from 'react';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import { PanResponder, Text, View, ScrollView, TouchableOpacity } from 'react-native';
|
||||
import {
|
||||
NativeModules,
|
||||
PanResponder,
|
||||
Text,
|
||||
View,
|
||||
ScrollView,
|
||||
TouchableOpacity
|
||||
} from 'react-native';
|
||||
import Video from 'react-native-video';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
import FileItemMedia from '../fileItemMedia';
|
||||
|
@ -76,6 +83,10 @@ class MediaPlayer extends React.PureComponent {
|
|||
}
|
||||
|
||||
if (this.state.firstPlay) {
|
||||
if (NativeModules.Mixpanel) {
|
||||
const { uri } = this.props;
|
||||
NativeModules.Mixpanel.track('Play', { uri });
|
||||
}
|
||||
this.setState({ firstPlay: false });
|
||||
this.hidePlayerControls();
|
||||
}
|
||||
|
@ -232,7 +243,7 @@ class MediaPlayer extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { fileInfo, title, thumbnail, style, fullScreenStyle } = this.props;
|
||||
const { fileInfo, thumbnail, style, fullScreenStyle } = this.props;
|
||||
const flexCompleted = this.getCurrentTimePercentage() * 100;
|
||||
const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
|
||||
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { NativeModules } from 'react-native';
|
||||
import { doSearch, doUpdateSearchQuery } from 'lbry-redux';
|
||||
import SearchInput from './view';
|
||||
|
||||
const perform = dispatch => ({
|
||||
search: search => dispatch(doSearch(search)),
|
||||
search: search => {
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('Search', { query: search });
|
||||
}
|
||||
return dispatch(doSearch(search));
|
||||
},
|
||||
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query, false))
|
||||
});
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ class FilePage extends React.PureComponent {
|
|||
StatusBar.setHidden(false);
|
||||
this.fetchFileInfo(this.props);
|
||||
this.fetchCostInfo(this.props);
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('Open File Page', { uri: this.props.navigation.state.params.uri });
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
|
@ -136,6 +139,7 @@ class FilePage extends React.PureComponent {
|
|||
{isPlayable && !this.state.mediaLoaded && <ActivityIndicator size="large" color={Colors.LbryGreen} style={filePageStyle.loading} />}
|
||||
{!completed && <FileDownloadButton uri={navigation.state.params.uri} style={filePageStyle.downloadButton} />}
|
||||
{fileInfo && isPlayable && <MediaPlayer fileInfo={fileInfo}
|
||||
uri={navigation.state.params.uri}
|
||||
style={filePageStyle.player}
|
||||
onFullscreenToggled={this.handleFullscreenToggle}
|
||||
onMediaLoaded={() => { this.setState({ mediaLoaded: true }); }}/>}
|
||||
|
|
|
@ -14,7 +14,7 @@ const select = (state) => ({
|
|||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
search: (query) => dispatch(doSearch(query)),
|
||||
search: (query) => dispatch(doSearch(query))
|
||||
});
|
||||
|
||||
export default connect(select, perform)(SearchPage);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import { View, Text } from 'react-native';
|
||||
import { View, Text, NativeModules } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import splashStyle from '../../styles/splash';
|
||||
|
||||
|
@ -66,6 +66,10 @@ class SplashScreen extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (NativeModules.Mixpanel) {
|
||||
NativeModules.Mixpanel.track('App Launch', null);
|
||||
}
|
||||
|
||||
Lbry
|
||||
.connect()
|
||||
.then(() => {
|
||||
|
|
|
@ -86,7 +86,7 @@ fullscreen = 0
|
|||
#android.presplash_color = #FFFFFF
|
||||
|
||||
# (list) Permissions
|
||||
android.permissions = INTERNET,READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE
|
||||
android.permissions = ACCESS_NETWORK_STATE,BLUETOOTH,INTERNET,READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE
|
||||
|
||||
# (int) Android API to use
|
||||
android.api = 23
|
||||
|
@ -148,7 +148,7 @@ android.react_src = ./app
|
|||
|
||||
# (list) Gradle dependencies to add (currently works only with sdl2_gradle
|
||||
# bootstrap)
|
||||
android.gradle_dependencies = com.android.support:appcompat-v7:23.4.0, com.facebook.react:react-native:+
|
||||
android.gradle_dependencies = com.android.support:appcompat-v7:23.4.0, com.facebook.react:react-native:+, com.mixpanel.android:mixpanel-android:5+, com.google.android.gms:play-services-gcm:11.0.4+
|
||||
|
||||
# (str) python-for-android branch to use, defaults to master
|
||||
#p4a.branch = stable
|
||||
|
|
|
@ -86,7 +86,7 @@ fullscreen = 0
|
|||
#android.presplash_color = #FFFFFF
|
||||
|
||||
# (list) Permissions
|
||||
android.permissions = INTERNET,READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE
|
||||
android.permissions = ACCESS_NETWORK_STATE,BLUETOOTH,INTERNET,READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE
|
||||
|
||||
# (int) Android API to use
|
||||
android.api = 23
|
||||
|
@ -148,7 +148,7 @@ android.react_src = ./app
|
|||
|
||||
# (list) Gradle dependencies to add (currently works only with sdl2_gradle
|
||||
# bootstrap)
|
||||
android.gradle_dependencies = com.android.support:appcompat-v7:23.4.0, com.facebook.react:react-native:+
|
||||
android.gradle_dependencies = com.android.support:appcompat-v7:23.4.0, com.facebook.react:react-native:+, com.mixpanel.android:mixpanel-android:5+, com.google.android.gms:play-services-gcm:11.0.4+
|
||||
|
||||
# (str) python-for-android branch to use, defaults to master
|
||||
#p4a.branch = stable
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package io.lbry.browser.reactmodules;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
import com.mixpanel.android.mpmetrics.MixpanelAPI;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONException;
|
||||
|
||||
public class MixpanelModule extends ReactContextBaseJavaModule {
|
||||
|
||||
private static final String MIXPANEL_TOKEN = "93b81fb957cb0ddcd3198c10853a6a95";
|
||||
|
||||
private Context context;
|
||||
|
||||
private MixpanelAPI mixpanel;
|
||||
|
||||
public MixpanelModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
this.context = reactContext;
|
||||
this.mixpanel = MixpanelAPI.getInstance(this.context, MIXPANEL_TOKEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Mixpanel";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void track(String name, ReadableMap payload) {
|
||||
JSONObject props = new JSONObject();
|
||||
try {
|
||||
if (payload != null) {
|
||||
HashMap<String, Object> payloadMap = payload.toHashMap();
|
||||
for (Map.Entry<String, Object> entry : payloadMap.entrySet()) {
|
||||
props.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
// Cannot use props. Stick with empty props.
|
||||
}
|
||||
|
||||
if (mixpanel != null) {
|
||||
mixpanel.track(name, props);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import com.facebook.react.uimanager.ViewManager;
|
|||
|
||||
import io.lbry.browser.reactmodules.DaemonServiceControlModule;
|
||||
import io.lbry.browser.reactmodules.DownloadManagerModule;
|
||||
import io.lbry.browser.reactmodules.MixpanelModule;
|
||||
import io.lbry.browser.reactmodules.ScreenOrientationModule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -25,6 +26,7 @@ public class LbryReactPackage implements ReactPackage {
|
|||
|
||||
modules.add(new DaemonServiceControlModule(reactContext));
|
||||
modules.add(new DownloadManagerModule(reactContext));
|
||||
modules.add(new MixpanelModule(reactContext));
|
||||
modules.add(new ScreenOrientationModule(reactContext));
|
||||
|
||||
return modules;
|
||||
|
|
Loading…
Reference in a new issue