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 AboutPage from '../page/about';
|
||||||
import DiscoverPage from '../page/discover';
|
import DiscoverPage from '../page/discover';
|
||||||
import FilePage from '../page/file';
|
import FilePage from '../page/file';
|
||||||
|
import FirstRunScreen from '../page/firstRun';
|
||||||
import SearchPage from '../page/search';
|
import SearchPage from '../page/search';
|
||||||
import TrendingPage from '../page/trending';
|
import TrendingPage from '../page/trending';
|
||||||
import SettingsPage from '../page/settings';
|
import SettingsPage from '../page/settings';
|
||||||
|
@ -99,6 +100,12 @@ const drawer = DrawerNavigator({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const AppNavigator = new StackNavigator({
|
export const AppNavigator = new StackNavigator({
|
||||||
|
FirstRun: {
|
||||||
|
screen: FirstRunScreen,
|
||||||
|
navigationOptions: {
|
||||||
|
drawerLockMode: 'locked-closed'
|
||||||
|
}
|
||||||
|
},
|
||||||
Splash: {
|
Splash: {
|
||||||
screen: SplashScreen,
|
screen: SplashScreen,
|
||||||
navigationOptions: {
|
navigationOptions: {
|
||||||
|
@ -114,7 +121,7 @@ export const AppNavigator = new StackNavigator({
|
||||||
|
|
||||||
class AppWithNavigationState extends React.Component {
|
class AppWithNavigationState extends React.Component {
|
||||||
static supportedDisplayTypes = ['toast'];
|
static supportedDisplayTypes = ['toast'];
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
AppState.addEventListener('change', this._handleAppStateChange);
|
AppState.addEventListener('change', this._handleAppStateChange);
|
||||||
BackHandler.addEventListener('hardwareBackPress', function() {
|
BackHandler.addEventListener('hardwareBackPress', function() {
|
||||||
|
@ -129,7 +136,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (nav.routes[0].routeName === 'Main') {
|
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());
|
dispatch(NavigationActions.back());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -138,17 +145,17 @@ class AppWithNavigationState extends React.Component {
|
||||||
return false;
|
return false;
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
Linking.addEventListener('url', this._handleUrl);
|
Linking.addEventListener('url', this._handleUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
AppState.removeEventListener('change', this._handleAppStateChange);
|
AppState.removeEventListener('change', this._handleAppStateChange);
|
||||||
BackHandler.removeEventListener('hardwareBackPress');
|
BackHandler.removeEventListener('hardwareBackPress');
|
||||||
Linking.removeEventListener('url', this._handleUrl);
|
Linking.removeEventListener('url', this._handleUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUpdate(nextProps) {
|
componentWillUpdate(nextProps) {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
const { notification } = nextProps;
|
const { notification } = nextProps;
|
||||||
|
@ -166,15 +173,15 @@ class AppWithNavigationState extends React.Component {
|
||||||
} else if (AppWithNavigationState.supportedDisplayTypes.indexOf(displayType) > -1) {
|
} else if (AppWithNavigationState.supportedDisplayTypes.indexOf(displayType) > -1) {
|
||||||
currentDisplayType = displayType;
|
currentDisplayType = displayType;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('toast' === currentDisplayType) {
|
if ('toast' === currentDisplayType) {
|
||||||
ToastAndroid.show(message, ToastAndroid.SHORT);
|
ToastAndroid.show(message, ToastAndroid.SHORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(doHideNotification());
|
dispatch(doHideNotification());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleAppStateChange = (nextAppState) => {
|
_handleAppStateChange = (nextAppState) => {
|
||||||
// Check if the app was suspended
|
// Check if the app was suspended
|
||||||
if (AppState.currentState && AppState.currentState.match(/inactive|background/)) {
|
if (AppState.currentState && AppState.currentState.match(/inactive|background/)) {
|
||||||
|
@ -187,7 +194,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleUrl = (evt) => {
|
_handleUrl = (evt) => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
if (evt.url) {
|
if (evt.url) {
|
||||||
|
@ -199,7 +206,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
dispatch(navigateAction);
|
dispatch(navigateAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { dispatch, nav } = this.props;
|
const { dispatch, nav } = this.props;
|
||||||
return (
|
return (
|
||||||
|
@ -220,5 +227,5 @@ const mapStateToProps = state => ({
|
||||||
keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state),
|
keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state),
|
||||||
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state)
|
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state)
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(AppWithNavigationState);
|
export default connect(mapStateToProps)(AppWithNavigationState);
|
||||||
|
|
|
@ -61,7 +61,7 @@ function enableBatching(reducer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const router = AppNavigator.router;
|
const router = AppNavigator.router;
|
||||||
const navAction = router.getActionForPathAndParams('Splash');
|
const navAction = router.getActionForPathAndParams('FirstRun');
|
||||||
const initialNavState = router.getStateForAction(navAction);
|
const initialNavState = router.getStateForAction(navAction);
|
||||||
const navigatorReducer = (state = initialNavState, action) => {
|
const navigatorReducer = (state = initialNavState, action) => {
|
||||||
const nextState = AppNavigator.router.getStateForAction(action, state);
|
const nextState = AppNavigator.router.getStateForAction(action, state);
|
||||||
|
@ -116,21 +116,11 @@ persistStore(store, persistOptions, err => {
|
||||||
});
|
});
|
||||||
|
|
||||||
class LBRYApp extends React.Component {
|
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() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<AppWithNavigationState />
|
<AppWithNavigationState />
|
||||||
</Provider>
|
</Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
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,15 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Lbry } from 'lbry-redux';
|
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 { NavigationActions } from 'react-navigation';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import Colors from '../../styles/colors';
|
||||||
import splashStyle from '../../styles/splash';
|
import splashStyle from '../../styles/splash';
|
||||||
|
|
||||||
class SplashScreen extends React.PureComponent {
|
class SplashScreen extends React.PureComponent {
|
||||||
static navigationOptions = {
|
static navigationOptions = {
|
||||||
title: 'Splash'
|
title: 'Splash'
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.setState({
|
this.setState({
|
||||||
details: 'Starting daemon',
|
details: 'Starting daemon',
|
||||||
|
@ -18,6 +19,21 @@ class SplashScreen extends React.PureComponent {
|
||||||
isLagging: false,
|
isLagging: false,
|
||||||
launchUrl: null
|
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() {
|
updateStatus() {
|
||||||
|
@ -25,7 +41,7 @@ class SplashScreen extends React.PureComponent {
|
||||||
this._updateStatusCallback(status);
|
this._updateStatusCallback(status);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateStatusCallback(status) {
|
_updateStatusCallback(status) {
|
||||||
const startupStatus = status.startup_status;
|
const startupStatus = status.startup_status;
|
||||||
if (startupStatus.code == 'started') {
|
if (startupStatus.code == 'started') {
|
||||||
|
@ -44,7 +60,7 @@ class SplashScreen extends React.PureComponent {
|
||||||
// Leave the splash screen
|
// Leave the splash screen
|
||||||
const { balanceSubscribe, navigation } = this.props;
|
const { balanceSubscribe, navigation } = this.props;
|
||||||
balanceSubscribe();
|
balanceSubscribe();
|
||||||
|
|
||||||
const resetAction = NavigationActions.reset({
|
const resetAction = NavigationActions.reset({
|
||||||
index: 0,
|
index: 0,
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -52,9 +68,10 @@ class SplashScreen extends React.PureComponent {
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
navigation.dispatch(resetAction);
|
navigation.dispatch(resetAction);
|
||||||
|
|
||||||
if (this.state.launchUrl) {
|
const launchUrl = navigation.state.params.launchUrl || this.state.launchUrl;
|
||||||
navigation.navigate({ routeName: 'File', key: this.state.launchUrl, params: { uri: this.state.launchUrl } });
|
if (launchUrl) {
|
||||||
|
navigation.navigate({ routeName: 'File', key: launchUrl, params: { uri: launchUrl } });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -78,7 +95,7 @@ class SplashScreen extends React.PureComponent {
|
||||||
this.updateStatus();
|
this.updateStatus();
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (NativeModules.Mixpanel) {
|
if (NativeModules.Mixpanel) {
|
||||||
NativeModules.Mixpanel.track('App Launch', null);
|
NativeModules.Mixpanel.track('App Launch', null);
|
||||||
|
@ -89,7 +106,7 @@ class SplashScreen extends React.PureComponent {
|
||||||
this.setState({ launchUrl: url });
|
this.setState({ launchUrl: url });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Lbry
|
Lbry
|
||||||
.connect()
|
.connect()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -107,10 +124,11 @@ class SplashScreen extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { message, details, isLagging, isRunning } = this.state;
|
const { message, details, isLagging, isRunning } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={splashStyle.container}>
|
<View style={splashStyle.container}>
|
||||||
<Text style={splashStyle.title}>LBRY</Text>
|
<Text style={splashStyle.title}>LBRY</Text>
|
||||||
|
<ActivityIndicator color={Colors.White} style={splashStyle.loading} size={"small"} />
|
||||||
<Text style={splashStyle.message}>{message}</Text>
|
<Text style={splashStyle.message}>{message}</Text>
|
||||||
<Text style={splashStyle.details}>{details}</Text>
|
<Text style={splashStyle.details}>{details}</Text>
|
||||||
</View>
|
</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 { StyleSheet } from 'react-native';
|
||||||
|
import Colors from './colors';
|
||||||
|
|
||||||
const splashStyle = StyleSheet.create({
|
const splashStyle = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
backgroundColor: '#40b89a'
|
backgroundColor: Colors.LbryGreen
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
fontFamily: 'Metropolis-Bold',
|
fontFamily: 'Metropolis-Bold',
|
||||||
fontSize: 64,
|
fontSize: 64,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
marginBottom: 48,
|
marginBottom: 48,
|
||||||
color: '#ffffff'
|
color: Colors.White
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
marginBottom: 36
|
||||||
},
|
},
|
||||||
details: {
|
details: {
|
||||||
fontFamily: 'Metropolis-Regular',
|
fontFamily: 'Metropolis-Regular',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
marginLeft: 16,
|
marginLeft: 16,
|
||||||
marginRight: 16,
|
marginRight: 16,
|
||||||
color: '#ffffff',
|
color: Colors.White,
|
||||||
textAlign: 'center'
|
textAlign: 'center'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
fontFamily: 'Metropolis-Bold',
|
fontFamily: 'Metropolis-Bold',
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: '#ffffff',
|
color: Colors.White,
|
||||||
marginLeft: 16,
|
marginLeft: 16,
|
||||||
marginRight: 16,
|
marginRight: 16,
|
||||||
marginBottom: 4,
|
marginBottom: 4,
|
||||||
|
|
|
@ -36,7 +36,7 @@ version.filename = %(source.dir)s/main.py
|
||||||
|
|
||||||
# (list) Application requirements
|
# (list) Application requirements
|
||||||
# comma seperated e.g. requirements = sqlite3,kivy
|
# 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
|
# (str) Custom source folders for requirements
|
||||||
# Sets custom source for any requirements with recipes
|
# Sets custom source for any requirements with recipes
|
||||||
|
|
|
@ -36,7 +36,7 @@ version.filename = %(source.dir)s/main.py
|
||||||
|
|
||||||
# (list) Application requirements
|
# (list) Application requirements
|
||||||
# comma seperated e.g. requirements = sqlite3,kivy
|
# 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
|
# (str) Custom source folders for requirements
|
||||||
# Sets custom source for any requirements with recipes
|
# Sets custom source for any requirements with recipes
|
||||||
|
|
|
@ -371,7 +371,7 @@ main.py that loads it.''')
|
||||||
args=args,
|
args=args,
|
||||||
url_scheme=url_scheme,
|
url_scheme=url_scheme,
|
||||||
private_version=str(time.time()))
|
private_version=str(time.time()))
|
||||||
|
|
||||||
# add colors.xml
|
# add colors.xml
|
||||||
render(
|
render(
|
||||||
'colors.tmpl.xml',
|
'colors.tmpl.xml',
|
||||||
|
@ -380,6 +380,14 @@ main.py that loads it.''')
|
||||||
url_scheme=url_scheme,
|
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
|
# add activity_service_control
|
||||||
render(
|
render(
|
||||||
'activity_service_control.xml',
|
'activity_service_control.xml',
|
||||||
|
@ -396,12 +404,12 @@ main.py that loads it.''')
|
||||||
aars=aars,
|
aars=aars,
|
||||||
android_api=android_api,
|
android_api=android_api,
|
||||||
build_tools_version=build_tools_version)
|
build_tools_version=build_tools_version)
|
||||||
|
|
||||||
render(
|
render(
|
||||||
'settings.tmpl.gradle',
|
'settings.tmpl.gradle',
|
||||||
'settings.gradle'
|
'settings.gradle'
|
||||||
)
|
)
|
||||||
|
|
||||||
# copy icon drawables
|
# copy icon drawables
|
||||||
for folder in ('drawable-hdpi', 'drawable-mdpi', 'drawable-xhdpi', 'drawable-xxhdpi', 'drawable-xxxhdpi'):
|
for folder in ('drawable-hdpi', 'drawable-mdpi', 'drawable-xhdpi', 'drawable-xxhdpi', 'drawable-xxxhdpi'):
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
<application android:label="@string/app_name"
|
<application android:label="@string/app_name"
|
||||||
android:icon="@drawable/icon"
|
android:icon="@drawable/icon"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:theme="@android:style/Theme.Material.Light"
|
android:theme="@style/LbryAppTheme"
|
||||||
android:hardwareAccelerated="true">
|
android:hardwareAccelerated="true">
|
||||||
|
|
||||||
{% for m in args.meta_data %}
|
{% for m in args.meta_data %}
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
android:configChanges="keyboardHidden|orientation{% if args.min_sdk_version >= 13 %}|screenSize{% endif %}"
|
android:configChanges="keyboardHidden|orientation{% if args.min_sdk_version >= 13 %}|screenSize{% endif %}"
|
||||||
android:screenOrientation="{{ args.orientation }}"
|
android:screenOrientation="{{ args.orientation }}"
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||||
|
|
||||||
<activity android:name="io.lbry.browser.MainActivity"
|
<activity android:name="io.lbry.browser.MainActivity"
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
android:screenOrientation="{{ args.orientation }}"
|
android:screenOrientation="{{ args.orientation }}"
|
||||||
android:launchMode="singleInstance"
|
android:launchMode="singleInstance"
|
||||||
>
|
>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
@ -99,9 +99,9 @@
|
||||||
{{- args.intent_filters -}}
|
{{- args.intent_filters -}}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<receiver android:name="io.lbry.browser.receivers.NotificationDeletedReceiver" />
|
<receiver android:name="io.lbry.browser.receivers.NotificationDeletedReceiver" />
|
||||||
|
|
||||||
{% if args.launcher %}
|
{% if args.launcher %}
|
||||||
<activity android:name="org.kivy.android.launcher.ProjectChooser"
|
<activity android:name="org.kivy.android.launcher.ProjectChooser"
|
||||||
android:icon="@drawable/icon"
|
android:icon="@drawable/icon"
|
||||||
|
|
|
@ -6,4 +6,5 @@
|
||||||
|
|
||||||
<color name="red">#FF0000</color>
|
<color name="red">#FF0000</color>
|
||||||
<color name="green">#00C000</color>
|
<color name="green">#00C000</color>
|
||||||
|
<color name="lbrygreen">#40B89A</color>
|
||||||
</resources>
|
</resources>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<resources>
|
||||||
|
<style name="LbryAppTheme" parent="@android:style/Theme.Material.Light">
|
||||||
|
<item name="android:windowBackground">@color/lbrygreen</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
|
@ -27,27 +27,27 @@ import io.lbry.browser.reactpackages.LbryReactPackage;
|
||||||
import io.lbry.browser.reactmodules.DownloadManagerModule;
|
import io.lbry.browser.reactmodules.DownloadManagerModule;
|
||||||
|
|
||||||
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
|
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
|
||||||
|
|
||||||
private static final int OVERLAY_PERMISSION_REQ_CODE = 101;
|
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 ReactRootView mReactRootView;
|
||||||
|
|
||||||
private ReactInstanceManager mReactInstanceManager;
|
private ReactInstanceManager mReactInstanceManager;
|
||||||
|
|
||||||
public static final String SHARED_PREFERENCES_NAME = "LBRY";
|
public static final String SHARED_PREFERENCES_NAME = "LBRY";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag which indicates whether or not the service is running. Will be updated in the
|
* Flag which indicates whether or not the service is running. Will be updated in the
|
||||||
* onResume method.
|
* onResume method.
|
||||||
*/
|
*/
|
||||||
private boolean serviceRunning;
|
private boolean serviceRunning;
|
||||||
|
|
||||||
protected String getMainComponentName() {
|
protected String getMainComponentName() {
|
||||||
return "LBRYApp";
|
return "LBRYApp";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
@ -63,15 +63,15 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
// Start the daemon service if it is not started
|
// Start the daemon service if it is not started
|
||||||
serviceRunning = isServiceRunning(LbrynetService.class);
|
serviceRunning = isServiceRunning(LbrynetService.class);
|
||||||
if (!serviceRunning) {
|
if (!serviceRunning) {
|
||||||
ServiceHelper.start(this, "", LbrynetService.class, "lbrynetservice");
|
ServiceHelper.start(this, "", LbrynetService.class, "lbrynetservice");
|
||||||
}
|
}
|
||||||
|
|
||||||
mReactRootView = new ReactRootView(this);
|
mReactRootView = new ReactRootView(this);
|
||||||
mReactInstanceManager = ReactInstanceManager.builder()
|
mReactInstanceManager = ReactInstanceManager.builder()
|
||||||
.setApplication(getApplication())
|
.setApplication(getApplication())
|
||||||
|
@ -87,7 +87,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
||||||
|
|
||||||
setContentView(mReactRootView);
|
setContentView(mReactRootView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
|
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
|
||||||
|
@ -98,7 +98,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
|
@ -127,30 +127,35 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
||||||
public void invokeDefaultOnBackPressed() {
|
public void invokeDefaultOnBackPressed() {
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
|
||||||
if (mReactInstanceManager != null) {
|
if (mReactInstanceManager != null) {
|
||||||
mReactInstanceManager.onHostPause(this);
|
mReactInstanceManager.onHostPause(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
serviceRunning = isServiceRunning(LbrynetService.class);
|
SharedPreferences sp = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||||
if (!serviceRunning) {
|
if (!sp.getBoolean("firstRun", true)) {
|
||||||
ServiceHelper.start(this, "", LbrynetService.class, "lbrynetservice");
|
// 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) {
|
if (mReactInstanceManager != null) {
|
||||||
mReactInstanceManager.onHostResume(this, this);
|
mReactInstanceManager.onHostResume(this, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
// check service running setting and end it here
|
// check service running setting and end it here
|
||||||
|
@ -164,7 +169,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
|
||||||
if (mReactInstanceManager != null) {
|
if (mReactInstanceManager != null) {
|
||||||
mReactInstanceManager.onHostDestroy(this);
|
mReactInstanceManager.onHostDestroy(this);
|
||||||
}
|
}
|
||||||
|
@ -178,7 +183,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNewIntent(Intent intent) {
|
public void onNewIntent(Intent intent) {
|
||||||
if (mReactInstanceManager != null) {
|
if (mReactInstanceManager != null) {
|
||||||
|
@ -186,7 +191,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
||||||
}
|
}
|
||||||
super.onNewIntent(intent);
|
super.onNewIntent(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isServiceRunning(Class<?> serviceClass) {
|
private boolean isServiceRunning(Class<?> serviceClass) {
|
||||||
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
||||||
for (ActivityManager.RunningServiceInfo serviceInfo : manager.getRunningServices(Integer.MAX_VALUE)) {
|
for (ActivityManager.RunningServiceInfo serviceInfo : manager.getRunningServices(Integer.MAX_VALUE)) {
|
||||||
|
|
|
@ -24,6 +24,11 @@ public class DaemonServiceControlModule extends ReactContextBaseJavaModule {
|
||||||
return "DaemonServiceControl";
|
return "DaemonServiceControl";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void startService() {
|
||||||
|
ServiceHelper.start(context, "", LbrynetService.class, "lbrynetservice");
|
||||||
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void stopService() {
|
public void stopService() {
|
||||||
ServiceHelper.stop(context, LbrynetService.class);
|
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;
|
package io.lbry.browser.reactmodules;
|
||||||
|
|
||||||
import android.content.Context;
|
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.Promise;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
import com.facebook.react.bridge.ReactMethod;
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
|
|
||||||
public class VersionInfoModule extends ReactContextBaseJavaModule {
|
public class VersionInfoModule extends ReactContextBaseJavaModule {
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.facebook.react.uimanager.ViewManager;
|
||||||
|
|
||||||
import io.lbry.browser.reactmodules.DaemonServiceControlModule;
|
import io.lbry.browser.reactmodules.DaemonServiceControlModule;
|
||||||
import io.lbry.browser.reactmodules.DownloadManagerModule;
|
import io.lbry.browser.reactmodules.DownloadManagerModule;
|
||||||
|
import io.lbry.browser.reactmodules.FirstRunModule;
|
||||||
import io.lbry.browser.reactmodules.MixpanelModule;
|
import io.lbry.browser.reactmodules.MixpanelModule;
|
||||||
import io.lbry.browser.reactmodules.ScreenOrientationModule;
|
import io.lbry.browser.reactmodules.ScreenOrientationModule;
|
||||||
import io.lbry.browser.reactmodules.VersionInfoModule;
|
import io.lbry.browser.reactmodules.VersionInfoModule;
|
||||||
|
@ -27,10 +28,11 @@ public class LbryReactPackage implements ReactPackage {
|
||||||
|
|
||||||
modules.add(new DaemonServiceControlModule(reactContext));
|
modules.add(new DaemonServiceControlModule(reactContext));
|
||||||
modules.add(new DownloadManagerModule(reactContext));
|
modules.add(new DownloadManagerModule(reactContext));
|
||||||
|
modules.add(new FirstRunModule(reactContext));
|
||||||
modules.add(new MixpanelModule(reactContext));
|
modules.add(new MixpanelModule(reactContext));
|
||||||
modules.add(new ScreenOrientationModule(reactContext));
|
modules.add(new ScreenOrientationModule(reactContext));
|
||||||
modules.add(new VersionInfoModule(reactContext));
|
modules.add(new VersionInfoModule(reactContext));
|
||||||
|
|
||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue