diff --git a/app/src/component/AppNavigator.js b/app/src/component/AppNavigator.js
index 218fd89e..91a4f0a1 100644
--- a/app/src/component/AppNavigator.js
+++ b/app/src/component/AppNavigator.js
@@ -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: {
@@ -114,7 +121,7 @@ export const AppNavigator = new StackNavigator({
class AppWithNavigationState extends React.Component {
static supportedDisplayTypes = ['toast'];
-
+
componentWillMount() {
AppState.addEventListener('change', this._handleAppStateChange);
BackHandler.addEventListener('hardwareBackPress', function() {
@@ -129,7 +136,7 @@ class AppWithNavigationState extends React.Component {
return true;
}
if (nav.routes[0].routeName === 'Main') {
- if (nav.routes[0].routes[0].routes[0].index > 0) {
+ if (nav.routes[0].routes[0].routes[0].index > 0) {
dispatch(NavigationActions.back());
return true;
}
@@ -138,17 +145,17 @@ class AppWithNavigationState extends React.Component {
return false;
}.bind(this));
}
-
+
componentDidMount() {
Linking.addEventListener('url', this._handleUrl);
}
-
+
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
BackHandler.removeEventListener('hardwareBackPress');
Linking.removeEventListener('url', this._handleUrl);
}
-
+
componentWillUpdate(nextProps) {
const { dispatch } = this.props;
const { notification } = nextProps;
@@ -166,15 +173,15 @@ class AppWithNavigationState extends React.Component {
} else if (AppWithNavigationState.supportedDisplayTypes.indexOf(displayType) > -1) {
currentDisplayType = displayType;
}
-
+
if ('toast' === currentDisplayType) {
ToastAndroid.show(message, ToastAndroid.SHORT);
}
-
+
dispatch(doHideNotification());
}
}
-
+
_handleAppStateChange = (nextAppState) => {
// Check if the app was suspended
if (AppState.currentState && AppState.currentState.match(/inactive|background/)) {
@@ -187,7 +194,7 @@ class AppWithNavigationState extends React.Component {
});
}
}
-
+
_handleUrl = (evt) => {
const { dispatch } = this.props;
if (evt.url) {
@@ -199,7 +206,7 @@ class AppWithNavigationState extends React.Component {
dispatch(navigateAction);
}
}
-
+
render() {
const { dispatch, nav } = this.props;
return (
@@ -220,5 +227,5 @@ const mapStateToProps = state => ({
keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state),
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state)
});
-
+
export default connect(mapStateToProps)(AppWithNavigationState);
diff --git a/app/src/index.js b/app/src/index.js
index a371b919..8e3f74ef 100644
--- a/app/src/index.js
+++ b/app/src/index.js
@@ -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,21 +116,11 @@ 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 (
-
-
+
+
);
}
}
diff --git a/app/src/page/firstRun/index.js b/app/src/page/firstRun/index.js
new file mode 100644
index 00000000..5e9ec0c1
--- /dev/null
+++ b/app/src/page/firstRun/index.js
@@ -0,0 +1,6 @@
+import { connect } from 'react-redux';
+import FirstRun from './view';
+
+const perform = dispatch => ({});
+
+export default connect(null, perform)(FirstRun);
\ No newline at end of file
diff --git a/app/src/page/firstRun/internal/welcome-page.js b/app/src/page/firstRun/internal/welcome-page.js
new file mode 100644
index 00000000..abc0eaea
--- /dev/null
+++ b/app/src/page/firstRun/internal/welcome-page.js
@@ -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 (
+
+ Welcome to LBRY.
+ 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.
+ 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.
+
+ );
+ }
+}
+
+export default WelcomePage;
diff --git a/app/src/page/firstRun/view.js b/app/src/page/firstRun/view.js
new file mode 100644
index 00000000..2e868376
--- /dev/null
+++ b/app/src/page/firstRun/view.js
@@ -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 = ();
+ }
+
+ return (
+
+ {page}
+ {this.state.currentPage &&
+
+ Continue
+ }
+
+ )
+ }
+}
+
+export default FirstRunScreen;
diff --git a/app/src/page/splash/view.js b/app/src/page/splash/view.js
index b1318cab..931446e3 100644
--- a/app/src/page/splash/view.js
+++ b/app/src/page/splash/view.js
@@ -1,15 +1,16 @@
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 {
static navigationOptions = {
title: 'Splash'
};
-
+
componentWillMount() {
this.setState({
details: 'Starting daemon',
@@ -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() {
@@ -25,7 +41,7 @@ class SplashScreen extends React.PureComponent {
this._updateStatusCallback(status);
});
}
-
+
_updateStatusCallback(status) {
const startupStatus = status.startup_status;
if (startupStatus.code == 'started') {
@@ -44,7 +60,7 @@ class SplashScreen extends React.PureComponent {
// Leave the splash screen
const { balanceSubscribe, navigation } = this.props;
balanceSubscribe();
-
+
const resetAction = NavigationActions.reset({
index: 0,
actions: [
@@ -52,9 +68,10 @@ 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;
@@ -78,7 +95,7 @@ class SplashScreen extends React.PureComponent {
this.updateStatus();
}, 500);
}
-
+
componentDidMount() {
if (NativeModules.Mixpanel) {
NativeModules.Mixpanel.track('App Launch', null);
@@ -89,7 +106,7 @@ class SplashScreen extends React.PureComponent {
this.setState({ launchUrl: url });
}
});
-
+
Lbry
.connect()
.then(() => {
@@ -107,10 +124,11 @@ class SplashScreen extends React.PureComponent {
render() {
const { message, details, isLagging, isRunning } = this.state;
-
+
return (
LBRY
+
{message}
{details}
diff --git a/app/src/styles/firstRun.js b/app/src/styles/firstRun.js
new file mode 100644
index 00000000..c5d3f4c6
--- /dev/null
+++ b/app/src/styles/firstRun.js
@@ -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;
diff --git a/app/src/styles/splash.js b/app/src/styles/splash.js
index dec85d75..f1b442e1 100644
--- a/app/src/styles/splash.js
+++ b/app/src/styles/splash.js
@@ -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,
diff --git a/buildozer.spec.sample b/buildozer.spec.sample
index 64b879d1..4707c06e 100644
--- a/buildozer.spec.sample
+++ b/buildozer.spec.sample
@@ -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
diff --git a/buildozer.spec.travis b/buildozer.spec.travis
index 64b879d1..4707c06e 100644
--- a/buildozer.spec.travis
+++ b/buildozer.spec.travis
@@ -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
diff --git a/p4a/pythonforandroid/bootstraps/lbry/build/build.py b/p4a/pythonforandroid/bootstraps/lbry/build/build.py
index 67bf3450..6c64175d 100755
--- a/p4a/pythonforandroid/bootstraps/lbry/build/build.py
+++ b/p4a/pythonforandroid/bootstraps/lbry/build/build.py
@@ -371,7 +371,7 @@ main.py that loads it.''')
args=args,
url_scheme=url_scheme,
private_version=str(time.time()))
-
+
# add colors.xml
render(
'colors.tmpl.xml',
@@ -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',
@@ -396,12 +404,12 @@ main.py that loads it.''')
aars=aars,
android_api=android_api,
build_tools_version=build_tools_version)
-
+
render(
'settings.tmpl.gradle',
'settings.gradle'
)
-
+
# copy icon drawables
for folder in ('drawable-hdpi', 'drawable-mdpi', 'drawable-xhdpi', 'drawable-xxhdpi', 'drawable-xxxhdpi'):
shutil.copy(
diff --git a/p4a/pythonforandroid/bootstraps/lbry/build/templates/AndroidManifest.tmpl.xml b/p4a/pythonforandroid/bootstraps/lbry/build/templates/AndroidManifest.tmpl.xml
index 0b93dc0b..198f4a4d 100644
--- a/p4a/pythonforandroid/bootstraps/lbry/build/templates/AndroidManifest.tmpl.xml
+++ b/p4a/pythonforandroid/bootstraps/lbry/build/templates/AndroidManifest.tmpl.xml
@@ -52,7 +52,7 @@
{% for m in args.meta_data %}
@@ -64,7 +64,7 @@
android:configChanges="keyboardHidden|orientation{% if args.min_sdk_version >= 13 %}|screenSize{% endif %}"
android:screenOrientation="{{ args.orientation }}"
-->
-
+
-
+
@@ -99,9 +99,9 @@
{{- args.intent_filters -}}
{%- endif -%}
-
+
-
+
{% if args.launcher %}
#FF0000
#00C000
+ #40B89A
\ No newline at end of file
diff --git a/p4a/pythonforandroid/bootstraps/lbry/build/templates/themes.tmpl.xml b/p4a/pythonforandroid/bootstraps/lbry/build/templates/themes.tmpl.xml
new file mode 100644
index 00000000..0b50d993
--- /dev/null
+++ b/p4a/pythonforandroid/bootstraps/lbry/build/templates/themes.tmpl.xml
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/src/main/java/io/lbry/browser/MainActivity.java b/src/main/java/io/lbry/browser/MainActivity.java
index 853056a6..11b5f842 100644
--- a/src/main/java/io/lbry/browser/MainActivity.java
+++ b/src/main/java/io/lbry/browser/MainActivity.java
@@ -27,27 +27,27 @@ import io.lbry.browser.reactpackages.LbryReactPackage;
import io.lbry.browser.reactmodules.DownloadManagerModule;
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
-
+
private static final int OVERLAY_PERMISSION_REQ_CODE = 101;
-
- private static final int STORAGE_PERMISSION_REQ_CODE = 201;
-
+
+ private static final int STORAGE_PERMISSION_REQ_CODE = 201;
+
private ReactRootView mReactRootView;
-
+
private ReactInstanceManager mReactInstanceManager;
-
+
public static final String SHARED_PREFERENCES_NAME = "LBRY";
-
+
/**
* Flag which indicates whether or not the service is running. Will be updated in the
* onResume method.
*/
private boolean serviceRunning;
-
+
protected String getMainComponentName() {
return "LBRYApp";
}
-
+
@Override
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -63,15 +63,15 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
}
}
}
-
+
super.onCreate(savedInstanceState);
-
+
// Start the daemon service if it is not started
serviceRunning = isServiceRunning(LbrynetService.class);
if (!serviceRunning) {
ServiceHelper.start(this, "", LbrynetService.class, "lbrynetservice");
}
-
+
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
@@ -87,7 +87,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
setContentView(mReactRootView);
}
-
+
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
@@ -98,7 +98,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
}
}
}
-
+
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
@@ -127,30 +127,35 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
-
+
@Override
protected void onPause() {
super.onPause();
-
+
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostPause(this);
}
}
-
+
@Override
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) {
mReactInstanceManager.onHostResume(this, this);
}
}
-
+
@Override
protected void onDestroy() {
// check service running setting and end it here
@@ -164,7 +169,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
}
super.onDestroy();
-
+
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostDestroy(this);
}
@@ -178,7 +183,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
super.onBackPressed();
}
}
-
+
@Override
public void onNewIntent(Intent intent) {
if (mReactInstanceManager != null) {
@@ -186,7 +191,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
}
super.onNewIntent(intent);
}
-
+
private boolean isServiceRunning(Class> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo serviceInfo : manager.getRunningServices(Integer.MAX_VALUE)) {
diff --git a/src/main/java/io/lbry/browser/reactmodules/DaemonServiceControlModule.java b/src/main/java/io/lbry/browser/reactmodules/DaemonServiceControlModule.java
index a8d859c5..eddff238 100644
--- a/src/main/java/io/lbry/browser/reactmodules/DaemonServiceControlModule.java
+++ b/src/main/java/io/lbry/browser/reactmodules/DaemonServiceControlModule.java
@@ -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);
diff --git a/src/main/java/io/lbry/browser/reactmodules/FirstRunModule.java b/src/main/java/io/lbry/browser/reactmodules/FirstRunModule.java
new file mode 100644
index 00000000..6e8b2b80
--- /dev/null
+++ b/src/main/java/io/lbry/browser/reactmodules/FirstRunModule.java
@@ -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();
+ }
+}
diff --git a/src/main/java/io/lbry/browser/reactmodules/VersionInfoModule.java b/src/main/java/io/lbry/browser/reactmodules/VersionInfoModule.java
index ed52dad1..387f1d9c 100644
--- a/src/main/java/io/lbry/browser/reactmodules/VersionInfoModule.java
+++ b/src/main/java/io/lbry/browser/reactmodules/VersionInfoModule.java
@@ -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;
diff --git a/src/main/java/io/lbry/browser/reactpackages/LbryReactPackage.java b/src/main/java/io/lbry/browser/reactpackages/LbryReactPackage.java
index b2bd0068..6fa4c9f1 100644
--- a/src/main/java/io/lbry/browser/reactpackages/LbryReactPackage.java
+++ b/src/main/java/io/lbry/browser/reactpackages/LbryReactPackage.java
@@ -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,10 +28,11 @@ 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));
-
+
return modules;
}
}
\ No newline at end of file