Merge pull request #166 from lbryio/first-run-improvements
implement extendable first run experience starting with welcome page
This commit is contained in:
commit
31168d9ed8
19 changed files with 333 additions and 78 deletions
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import AboutPage from '../page/about';
|
||||
import DiscoverPage from '../page/discover';
|
||||
import FilePage from '../page/file';
|
||||
import FirstRunScreen from '../page/firstRun';
|
||||
import SearchPage from '../page/search';
|
||||
import TrendingPage from '../page/trending';
|
||||
import SettingsPage from '../page/settings';
|
||||
|
@ -99,6 +100,12 @@ const drawer = DrawerNavigator({
|
|||
});
|
||||
|
||||
export const AppNavigator = new StackNavigator({
|
||||
FirstRun: {
|
||||
screen: FirstRunScreen,
|
||||
navigationOptions: {
|
||||
drawerLockMode: 'locked-closed'
|
||||
}
|
||||
},
|
||||
Splash: {
|
||||
screen: SplashScreen,
|
||||
navigationOptions: {
|
||||
|
|
|
@ -61,7 +61,7 @@ function enableBatching(reducer) {
|
|||
}
|
||||
|
||||
const router = AppNavigator.router;
|
||||
const navAction = router.getActionForPathAndParams('Splash');
|
||||
const navAction = router.getActionForPathAndParams('FirstRun');
|
||||
const initialNavState = router.getStateForAction(navAction);
|
||||
const navigatorReducer = (state = initialNavState, action) => {
|
||||
const nextState = AppNavigator.router.getStateForAction(action, state);
|
||||
|
@ -116,16 +116,6 @@ 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}>
|
||||
|
|
6
app/src/page/firstRun/index.js
Normal file
6
app/src/page/firstRun/index.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { connect } from 'react-redux';
|
||||
import FirstRun from './view';
|
||||
|
||||
const perform = dispatch => ({});
|
||||
|
||||
export default connect(null, perform)(FirstRun);
|
21
app/src/page/firstRun/internal/welcome-page.js
Normal file
21
app/src/page/firstRun/internal/welcome-page.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import React from 'react';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import { View, Text, Linking } from 'react-native';
|
||||
import Colors from '../../../styles/colors';
|
||||
import firstRunStyle from '../../../styles/firstRun';
|
||||
|
||||
class WelcomePage extends React.PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<View style={firstRunStyle.container}>
|
||||
<Text style={firstRunStyle.title}>Welcome to LBRY.</Text>
|
||||
<Text style={firstRunStyle.paragraph}>LBRY is a decentralized peer-to-peer content sharing platform where
|
||||
you can upload and download videos, music, ebooks and other forms of digital content.</Text>
|
||||
<Text style={firstRunStyle.paragraph}>We make use of a blockchain which needs to be synchronized before
|
||||
you can use the app. Synchronization may take a while because this is the first app launch.</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default WelcomePage;
|
96
app/src/page/firstRun/view.js
Normal file
96
app/src/page/firstRun/view.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
import React from 'react';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import {
|
||||
Linking,
|
||||
NativeModules,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View
|
||||
} from 'react-native';
|
||||
import { NavigationActions } from 'react-navigation';
|
||||
import Colors from '../../styles/colors';
|
||||
import WelcomePage from './internal/welcome-page';
|
||||
import firstRunStyle from '../../styles/firstRun';
|
||||
|
||||
class FirstRunScreen extends React.PureComponent {
|
||||
static pages = ['welcome'];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
currentPage: null,
|
||||
launchUrl: null,
|
||||
isFirstRun: false
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
Linking.getInitialURL().then((url) => {
|
||||
if (url) {
|
||||
this.setState({ launchUrl: url });
|
||||
}
|
||||
});
|
||||
|
||||
if (NativeModules.FirstRun) {
|
||||
NativeModules.FirstRun.isFirstRun().then(firstRun => {
|
||||
this.setState({ isFirstRun: firstRun });
|
||||
if (firstRun) {
|
||||
this.setState({ currentPage: FirstRunScreen.pages[0] });
|
||||
} else {
|
||||
// Not the first run. Navigate to the splash screen right away
|
||||
this.launchSplashScreen();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// The first run module was not detected. Go straight to the splash screen.
|
||||
this.launchSplashScreen();
|
||||
}
|
||||
}
|
||||
|
||||
launchSplashScreen() {
|
||||
const { navigation } = this.props;
|
||||
const resetAction = NavigationActions.reset({
|
||||
index: 0,
|
||||
actions: [
|
||||
NavigationActions.navigate({ routeName: 'Splash', params: { launchUri: this.state.launchUri } })
|
||||
]
|
||||
});
|
||||
navigation.dispatch(resetAction);
|
||||
}
|
||||
|
||||
handleContinuePressed = () => {
|
||||
const pageIndex = FirstRunScreen.pages.indexOf(this.state.currentPage);
|
||||
if (pageIndex === (FirstRunScreen.pages.length - 1)) {
|
||||
// Final page. Let the app know that first run experience is completed.
|
||||
if (NativeModules.FirstRun) {
|
||||
NativeModules.FirstRun.firstRunCompleted();
|
||||
}
|
||||
|
||||
// Navigate to the splash screen
|
||||
this.launchSplashScreen();
|
||||
} else {
|
||||
// TODO: Page transition animation?
|
||||
this.state.currentPage = FirstRunScreen.pages[pageIndex + 1];
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let page = null;
|
||||
if (this.state.currentPage === 'welcome') {
|
||||
// show welcome page
|
||||
page = (<WelcomePage />);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={firstRunStyle.screenContainer}>
|
||||
{page}
|
||||
{this.state.currentPage &&
|
||||
<TouchableOpacity style={firstRunStyle.button} onPress={this.handleContinuePressed}>
|
||||
<Text style={firstRunStyle.buttonText}>Continue</Text>
|
||||
</TouchableOpacity>}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default FirstRunScreen;
|
|
@ -1,8 +1,9 @@
|
|||
import React from 'react';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import { View, Text, Linking, NativeModules } from 'react-native';
|
||||
import { ActivityIndicator, View, Text, Linking, NativeModules } from 'react-native';
|
||||
import { NavigationActions } from 'react-navigation';
|
||||
import PropTypes from 'prop-types';
|
||||
import Colors from '../../styles/colors';
|
||||
import splashStyle from '../../styles/splash';
|
||||
|
||||
class SplashScreen extends React.PureComponent {
|
||||
|
@ -18,6 +19,21 @@ class SplashScreen extends React.PureComponent {
|
|||
isLagging: false,
|
||||
launchUrl: null
|
||||
});
|
||||
|
||||
if (NativeModules.DaemonServiceControl) {
|
||||
NativeModules.DaemonServiceControl.startService();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// Start measuring the first launch time from the splash screen (time from daemon start to user interaction)
|
||||
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()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateStatus() {
|
||||
|
@ -53,8 +69,9 @@ class SplashScreen extends React.PureComponent {
|
|||
});
|
||||
navigation.dispatch(resetAction);
|
||||
|
||||
if (this.state.launchUrl) {
|
||||
navigation.navigate({ routeName: 'File', key: this.state.launchUrl, params: { uri: this.state.launchUrl } });
|
||||
const launchUrl = navigation.state.params.launchUrl || this.state.launchUrl;
|
||||
if (launchUrl) {
|
||||
navigation.navigate({ routeName: 'File', key: launchUrl, params: { uri: launchUrl } });
|
||||
}
|
||||
});
|
||||
return;
|
||||
|
@ -111,6 +128,7 @@ class SplashScreen extends React.PureComponent {
|
|||
return (
|
||||
<View style={splashStyle.container}>
|
||||
<Text style={splashStyle.title}>LBRY</Text>
|
||||
<ActivityIndicator color={Colors.White} style={splashStyle.loading} size={"small"} />
|
||||
<Text style={splashStyle.message}>{message}</Text>
|
||||
<Text style={splashStyle.details}>{details}</Text>
|
||||
</View>
|
||||
|
|
44
app/src/styles/firstRun.js
Normal file
44
app/src/styles/firstRun.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
import Colors from './colors';
|
||||
|
||||
const firstRunStyle = StyleSheet.create({
|
||||
screenContainer: {
|
||||
flex: 1,
|
||||
backgroundColor: Colors.LbryGreen
|
||||
},
|
||||
container: {
|
||||
flex: 9,
|
||||
justifyContent: 'center',
|
||||
backgroundColor: Colors.LbryGreen
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Metropolis-SemiBold',
|
||||
fontSize: 40,
|
||||
marginLeft: 32,
|
||||
marginRight: 32,
|
||||
marginBottom: 32,
|
||||
color: Colors.White
|
||||
},
|
||||
paragraph: {
|
||||
fontFamily: 'Metropolis-Regular',
|
||||
fontSize: 18,
|
||||
lineHeight: 24,
|
||||
marginLeft: 32,
|
||||
marginRight: 32,
|
||||
marginBottom: 20,
|
||||
color: Colors.White
|
||||
},
|
||||
button: {
|
||||
flex: 1,
|
||||
alignSelf: 'flex-end',
|
||||
marginLeft: 32,
|
||||
marginRight: 32
|
||||
},
|
||||
buttonText: {
|
||||
fontFamily: 'Metropolis-Regular',
|
||||
fontSize: 28,
|
||||
color: Colors.White
|
||||
}
|
||||
});
|
||||
|
||||
export default firstRunStyle;
|
|
@ -1,30 +1,34 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
import Colors from './colors';
|
||||
|
||||
const splashStyle = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
backgroundColor: '#40b89a'
|
||||
backgroundColor: Colors.LbryGreen
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Metropolis-Bold',
|
||||
fontSize: 64,
|
||||
textAlign: 'center',
|
||||
marginBottom: 48,
|
||||
color: '#ffffff'
|
||||
color: Colors.White
|
||||
},
|
||||
loading: {
|
||||
marginBottom: 36
|
||||
},
|
||||
details: {
|
||||
fontFamily: 'Metropolis-Regular',
|
||||
fontSize: 14,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
color: '#ffffff',
|
||||
color: Colors.White,
|
||||
textAlign: 'center'
|
||||
},
|
||||
message: {
|
||||
fontFamily: 'Metropolis-Bold',
|
||||
fontSize: 18,
|
||||
color: '#ffffff',
|
||||
color: Colors.White,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
marginBottom: 4,
|
||||
|
|
|
@ -36,7 +36,7 @@ version.filename = %(source.dir)s/main.py
|
|||
|
||||
# (list) Application requirements
|
||||
# comma seperated e.g. requirements = sqlite3,kivy
|
||||
requirements = openssl, sqlite3, hostpython2, android, pyjnius, certifi==2018.4.16, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, keyring==10.4.0, git+https://github.com/lbryio/lbryschema.git@v0.0.15#egg=lbryschema, git+https://github.com/lbryio/lbryum.git#egg=lbryum, git+https://github.com/lbryio/lbry.git#egg=lbrynet, asn1crypto, cryptography==2.2.2, pyopenssl==17.4.0, treq==17.8.0, funcsigs, mock, pbr, unqlite
|
||||
requirements = openssl, sqlite3, hostpython2, android, distro, pyjnius, certifi==2018.4.16, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, keyring==10.4.0, git+https://github.com/lbryio/lbryschema.git@v0.0.15#egg=lbryschema, git+https://github.com/lbryio/lbryum.git#egg=lbryum, git+https://github.com/lbryio/lbry.git#egg=lbrynet, asn1crypto, cryptography==2.2.2, pyopenssl==17.4.0, treq==17.8.0, funcsigs, mock, pbr, unqlite
|
||||
|
||||
# (str) Custom source folders for requirements
|
||||
# Sets custom source for any requirements with recipes
|
||||
|
|
|
@ -36,7 +36,7 @@ version.filename = %(source.dir)s/main.py
|
|||
|
||||
# (list) Application requirements
|
||||
# comma seperated e.g. requirements = sqlite3,kivy
|
||||
requirements = openssl, sqlite3, hostpython2, android, pyjnius, certifi==2018.4.16, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, keyring==10.4.0, git+https://github.com/lbryio/lbryschema.git@v0.0.15#egg=lbryschema, git+https://github.com/lbryio/lbryum.git#egg=lbryum, git+https://github.com/lbryio/lbry.git#egg=lbrynet, asn1crypto, cryptography==2.2.2, pyopenssl==17.4.0, treq==17.8.0, funcsigs, mock, pbr, unqlite
|
||||
requirements = openssl, sqlite3, hostpython2, android, distro, pyjnius, certifi==2018.4.16, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, seccure==0.3.1.3, attrs==18.1.0, pyasn1, pyasn1-modules, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, keyring==10.4.0, git+https://github.com/lbryio/lbryschema.git@v0.0.15#egg=lbryschema, git+https://github.com/lbryio/lbryum.git#egg=lbryum, git+https://github.com/lbryio/lbry.git#egg=lbrynet, asn1crypto, cryptography==2.2.2, pyopenssl==17.4.0, treq==17.8.0, funcsigs, mock, pbr, unqlite
|
||||
|
||||
# (str) Custom source folders for requirements
|
||||
# Sets custom source for any requirements with recipes
|
||||
|
|
|
@ -380,6 +380,14 @@ main.py that loads it.''')
|
|||
url_scheme=url_scheme,
|
||||
)
|
||||
|
||||
# add themes.xml
|
||||
render(
|
||||
'themes.tmpl.xml',
|
||||
'src/main/res/values/themes.xml',
|
||||
args=args,
|
||||
url_scheme=url_scheme,
|
||||
)
|
||||
|
||||
# add activity_service_control
|
||||
render(
|
||||
'activity_service_control.xml',
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<application android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:allowBackup="true"
|
||||
android:theme="@android:style/Theme.Material.Light"
|
||||
android:theme="@style/LbryAppTheme"
|
||||
android:hardwareAccelerated="true">
|
||||
|
||||
{% for m in args.meta_data %}
|
||||
|
|
|
@ -6,4 +6,5 @@
|
|||
|
||||
<color name="red">#FF0000</color>
|
||||
<color name="green">#00C000</color>
|
||||
<color name="lbrygreen">#40B89A</color>
|
||||
</resources>
|
|
@ -0,0 +1,5 @@
|
|||
<resources>
|
||||
<style name="LbryAppTheme" parent="@android:style/Theme.Material.Light">
|
||||
<item name="android:windowBackground">@color/lbrygreen</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -141,9 +141,14 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
|||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
serviceRunning = isServiceRunning(LbrynetService.class);
|
||||
if (!serviceRunning) {
|
||||
ServiceHelper.start(this, "", LbrynetService.class, "lbrynetservice");
|
||||
SharedPreferences sp = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
if (!sp.getBoolean("firstRun", true)) {
|
||||
// We're not showing the welcome page, so it's okay to start the daemon service
|
||||
// because this is not the first run experience
|
||||
serviceRunning = isServiceRunning(LbrynetService.class);
|
||||
if (!serviceRunning) {
|
||||
ServiceHelper.start(this, "", LbrynetService.class, "lbrynetservice");
|
||||
}
|
||||
}
|
||||
|
||||
if (mReactInstanceManager != null) {
|
||||
|
|
|
@ -24,6 +24,11 @@ public class DaemonServiceControlModule extends ReactContextBaseJavaModule {
|
|||
return "DaemonServiceControl";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void startService() {
|
||||
ServiceHelper.start(context, "", LbrynetService.class, "lbrynetservice");
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void stopService() {
|
||||
ServiceHelper.stop(context, LbrynetService.class);
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package io.lbry.browser.reactmodules;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
|
||||
import io.lbry.browser.MainActivity;
|
||||
|
||||
public class FirstRunModule extends ReactContextBaseJavaModule {
|
||||
private Context context;
|
||||
|
||||
private SharedPreferences sp;
|
||||
|
||||
public FirstRunModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
this.context = reactContext;
|
||||
this.sp = reactContext.getSharedPreferences(MainActivity.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "FirstRun";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void isFirstRun(final Promise promise) {
|
||||
// If firstRun flag does not exist, default to true
|
||||
boolean firstRun = sp.getBoolean("firstRun", true);
|
||||
promise.resolve(firstRun);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void firstRunCompleted() {
|
||||
SharedPreferences.Editor editor = sp.edit();
|
||||
editor.putBoolean("firstRun", false);
|
||||
editor.commit();
|
||||
}
|
||||
}
|
|
@ -1,15 +1,14 @@
|
|||
package io.lbry.browser.reactmodules;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
public class VersionInfoModule extends ReactContextBaseJavaModule {
|
||||
private Context context;
|
||||
|
||||
|
|
|
@ -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.FirstRunModule;
|
||||
import io.lbry.browser.reactmodules.MixpanelModule;
|
||||
import io.lbry.browser.reactmodules.ScreenOrientationModule;
|
||||
import io.lbry.browser.reactmodules.VersionInfoModule;
|
||||
|
@ -27,6 +28,7 @@ public class LbryReactPackage implements ReactPackage {
|
|||
|
||||
modules.add(new DaemonServiceControlModule(reactContext));
|
||||
modules.add(new DownloadManagerModule(reactContext));
|
||||
modules.add(new FirstRunModule(reactContext));
|
||||
modules.add(new MixpanelModule(reactContext));
|
||||
modules.add(new ScreenOrientationModule(reactContext));
|
||||
modules.add(new VersionInfoModule(reactContext));
|
||||
|
|
Loading…
Reference in a new issue