ADD: Updated Settings screen to match design (#84)

* ADD: Updated Settings screen to match design
This commit is contained in:
Marcos Rodriguez Vélez 2018-09-30 04:31:09 -04:00 committed by Igor Korsakov
parent 5a225a7a62
commit 682048414d
17 changed files with 360 additions and 222 deletions

2
App.js
View File

@ -5,7 +5,7 @@ import { Text, ScrollView, StyleSheet } from 'react-native';
import { createDrawerNavigator, SafeAreaView } from 'react-navigation';
import MainBottomTabs from './MainBottomTabs';
import Selftest from './screen/selftest';
import About from './screen/about';
import About from './screen/settings/about';
import PlausibleDeniability from './screen/plausibledeniability';
/** @type {AppStorage} */

View File

@ -2,7 +2,7 @@
import React from 'react';
import { WatchOnlyWallet, LegacyWallet, SegwitP2SHWallet, AppStorage } from './class';
import TestRenderer from 'react-test-renderer';
import Settings from './screen/settings';
import Settings from './screen/settings/settings';
import Selftest from './screen/selftest';
import { BlueHeader } from './BlueComponents';
import MockStorage from './MockStorage';

View File

@ -199,7 +199,6 @@ export class BlueListItem extends Component {
return (
<ListItem
bottomDivider
{...this.props}
containerStyle={{
backgroundColor: 'transparent',
borderBottomStartRadius: 20,
@ -213,6 +212,7 @@ export class BlueListItem extends Component {
}}
subtitleStyle={{ color: '#9aa0aa' }}
subtitleNumberOfLines={1}
{...this.props}
/>
);
}
@ -313,7 +313,6 @@ export class BlueHeaderDefaultSub extends Component {
return (
<SafeAreaView style={{ backgroundColor: '#FFFFFF' }}>
<Header
{...this.props}
backgroundColor="#FFFFFF"
outerContainerStyles={{
borderBottomColor: 'transparent',
@ -348,6 +347,7 @@ export class BlueHeaderDefaultSub extends Component {
</View>
</TouchableOpacity>
}
{...this.props}
/>
</SafeAreaView>
);

View File

@ -1,22 +1,91 @@
import { createStackNavigator } from 'react-navigation';
import wallets from './screen/wallets';
import settings from './screen/settings';
import AddWallet from './screen/wallets/add';
import ImportWallet from './screen/wallets/import';
import WalletDetails from './screen/wallets/details';
import WalletExport from './screen/wallets/export';
import scanQrWif from './screen/wallets/scanQrWif';
import details from './screen/transactions/details';
import rbf from './screen/transactions/RBF';
import createrbf from './screen/transactions/RBF-create';
import receiveDetails from './screen/receive/details';
import sendDetails from './screen/send/details';
import sendScanQrAddress from './screen/send/scanQrAddress';
import sendCreate from './screen/send/create';
import ManageFunds from './screen/lnd/manageFunds';
import ScanLndInvoice from './screen/lnd/scanLndInvoice';
const Tabs = createStackNavigator(
{
Wallets: {
screen: wallets,
path: 'wallets',
navigationOptions: {
header: null,
},
},
Settings: {
screen: settings,
path: 'settings',
AddWallet: {
screen: AddWallet,
},
ImportWallet: {
screen: ImportWallet,
},
ScanQrWif: {
screen: scanQrWif,
},
WalletDetails: {
screen: WalletDetails,
},
WalletExport: {
screen: WalletExport,
},
//
TransactionDetails: {
screen: details,
},
RBF: {
screen: rbf,
},
CreateRBF: {
screen: createrbf,
},
//
ReceiveDetails: {
screen: receiveDetails,
},
//
SendDetails: {
screen: sendDetails,
},
ScanQrAddress: {
screen: sendScanQrAddress,
},
CreateTransaction: {
screen: sendCreate,
},
// LND:
ManageFunds: {
screen: ManageFunds,
},
ScanLndInvoice: {
screen: ScanLndInvoice,
},
},
{
mode: 'modal',
headerMode: 'none',
},
);

View File

@ -125,7 +125,7 @@ module.exports = {
},
},
receive: {
header: 'Receive',
header: 'receive',
details: {
title: 'Share this address with payer',
share: 'share',
@ -133,7 +133,6 @@ module.exports = {
},
},
settings: {
tabBarLabel: 'Settings',
header: 'settings',
plausible_deniability: 'Plausible deniability...',
storage_not_encrypted: 'Storage: not encrypted',
@ -144,6 +143,8 @@ module.exports = {
passwords_do_not_match: 'Passwords do not match',
encrypt_storage: 'Encrypt storage',
about: 'About',
language: 'Language',
currency: 'Currency',
},
plausibledeniability: {
title: 'Plausible Deniability',

View File

@ -144,6 +144,8 @@ module.exports = {
passwords_do_not_match: 'Contraseñas deben ser iguales',
encrypt_storage: 'Cifrar almacenamiento',
about: 'Sobre nosotros',
language: 'Idioma',
currency: 'Moneda',
},
plausibledeniability: {
title: 'Plausible Deniability',

View File

@ -144,6 +144,8 @@ module.exports = {
passwords_do_not_match: 'Passwords não coincidem',
encrypt_storage: 'Encriptar armazenamento',
about: 'Sobre',
language: 'Language',
currency: 'Currency',
},
plausibledeniability: {
title: 'Negação plausível',

View File

@ -144,6 +144,8 @@ module.exports = {
passwords_do_not_match: 'Passwords não coincidem',
encrypt_storage: 'Encriptar armazenamento',
about: 'Sobre',
language: 'Language',
currency: 'Currency',
},
plausibledeniability: {
title: 'Negação plausível',

View File

@ -143,6 +143,8 @@ module.exports = {
passwords_do_not_match: 'Пароли не совпадают',
encrypt_storage: 'Зашифровать хранилище',
about: 'О программе',
language: 'Language',
currency: 'Currency',
},
plausibledeniability: {
title: 'Правдоподобное Отрицание',

View File

@ -144,6 +144,8 @@ module.exports = {
passwords_do_not_match: 'Паролі не збігаються',
encrypt_storage: 'Зашифрувати сховище',
about: 'Про програму',
language: 'Language',
currency: 'Currency',
},
plausibledeniability: {
title: 'Правдоподібне Заперечення',

View File

@ -93,7 +93,9 @@ export default class ReceiveDetails extends Component {
fgColor={BlueApp.settings.brandingColor}
/>
<TouchableOpacity onPress={this.copyToClipboard}>
<Animated.Text style={styles.address}>{this.state.addressText}</Animated.Text>
<Animated.Text style={styles.address} numberOfLines={0}>
{this.state.addressText}
</Animated.Text>
</TouchableOpacity>
</View>
<BlueButton

View File

@ -1,125 +0,0 @@
/* global alert */
import React, { Component } from 'react';
import { ScrollView, View, Picker } from 'react-native';
import { FormValidationMessage } from 'react-native-elements';
import { BlueLoading, BlueButton, SafeBlueArea, BlueCard, BlueText, BlueHeaderDefaultSub } from '../BlueComponents';
import PropTypes from 'prop-types';
/** @type {AppStorage} */
let BlueApp = require('../BlueApp');
let prompt = require('../prompt');
let loc = require('../loc');
export default class Settings extends Component {
static navigationOptions = {
tabBarVisible: false,
};
constructor(props) {
super(props);
this.state = {
isLoading: true,
language: loc.getLanguage(),
};
}
async componentDidMount() {
this.setState({
isLoading: false,
storageIsEncrypted: await BlueApp.storageIsEncrypted(),
});
}
render() {
if (this.state.isLoading) {
return <BlueLoading />;
}
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<BlueHeaderDefaultSub leftText={loc.settings.header} onClose={() => this.props.navigation.goBack()} />
<BlueCard>
<ScrollView maxHeight={450}>
{(() => {
if (this.state.storageIsEncrypted) {
return (
<View>
<BlueText>{loc.settings.storage_encrypted}</BlueText>
<BlueButton
onPress={() => this.props.navigation.navigate('PlausibleDeniability')}
title={loc.settings.plausible_deniability}
/>
</View>
);
} else {
return (
<View>
<FormValidationMessage>{loc.settings.storage_not_encrypted}</FormValidationMessage>
<BlueButton
icon={{
name: 'shield',
type: 'octicon',
color: BlueApp.settings.buttonTextColor,
}}
onPress={async () => {
this.setState({ isLoading: true });
let p1 = await prompt(loc.settings.password, loc.settings.password_explain).catch(() => {
this.setState({ isLoading: false });
this.props.navigation.goBack();
});
if (!p1) {
this.setState({ isLoading: false });
return;
}
let p2 = await prompt(loc.settings.password, loc.settings.retype_password).catch(() => {
this.setState({ isLoading: false });
this.props.navigation.goBack();
});
if (p1 === p2) {
await BlueApp.encryptStorage(p1);
this.setState({
isLoading: false,
storageIsEncrypted: await BlueApp.storageIsEncrypted(),
});
} else {
this.setState({ isLoading: false });
alert(loc.settings.passwords_do_not_match);
}
}}
title={loc.settings.encrypt_storage}
/>
</View>
);
}
})()}
<BlueButton onPress={() => this.props.navigation.navigate('About')} title={loc.settings.about} />
</ScrollView>
<Picker
selectedValue={this.state.language}
onValueChange={(itemValue, itemIndex) => {
console.log('setLanguage', itemValue);
loc.setLanguage(itemValue);
loc.saveLanguage(itemValue);
return this.setState({ language: itemValue });
}}
>
<Picker.Item color={BlueApp.settings.foregroundColor} label="English" value="en" />
<Picker.Item color={BlueApp.settings.foregroundColor} label="Русский" value="ru" />
<Picker.Item color={BlueApp.settings.foregroundColor} label="Українська" value="ua" />
<Picker.Item color={BlueApp.settings.foregroundColor} label="Spanish" value="es" />
<Picker.Item color={BlueApp.settings.foregroundColor} label="Portuguese" value="pt" />
</Picker>
</BlueCard>
</SafeBlueArea>
);
}
}
Settings.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
};

View File

@ -10,15 +10,19 @@ import {
BlueCard,
BlueText,
BlueHeaderDefaultSub,
} from '../BlueComponents';
} from '../../BlueComponents';
import PropTypes from 'prop-types';
/** @type {AppStorage} */
let BlueApp = require('../BlueApp');
let BlueApp = require('../../BlueApp');
const { width, height } = Dimensions.get('window');
export default class About extends Component {
static navigationOptions = {
tabBarVisible: false,
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
},
headerTintColor: '#0c2550',
};
constructor(props) {
@ -41,7 +45,7 @@ export default class About extends Component {
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<BlueHeaderDefaultSub leftText={'about'} onClose={() => this.props.navigation.goBack()} />
<BlueHeaderDefaultSub leftText={'about'} rightComponent={null} />
<BlueCard>
<ScrollView maxHeight={height - 100}>

View File

@ -0,0 +1,109 @@
/* global alert */
import React, { Component } from 'react';
import { View } from 'react-native';
import { FormValidationMessage } from 'react-native-elements';
import { BlueLoading, BlueButton, SafeBlueArea, BlueCard, BlueText, BlueHeaderDefaultSub } from '../../BlueComponents';
import PropTypes from 'prop-types';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
let prompt = require('../../prompt');
let loc = require('../../loc');
export default class EncryptStorage extends Component {
static navigationOptions = {
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
},
headerTintColor: '#0c2550',
};
constructor(props) {
super(props);
this.state = {
isLoading: true,
language: loc.getLanguage(),
};
}
async componentDidMount() {
this.setState({
isLoading: false,
storageIsEncrypted: await BlueApp.storageIsEncrypted(),
});
}
render() {
if (this.state.isLoading) {
return <BlueLoading />;
}
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<BlueHeaderDefaultSub leftText={loc.settings.encrypt_storage.toLowerCase()} rightComponent={null} />
<BlueCard>
{(() => {
if (this.state.storageIsEncrypted) {
return (
<View>
<BlueText>{loc.settings.storage_encrypted}</BlueText>
<BlueButton
onPress={() => this.props.navigation.navigate('PlausibleDeniability')}
title={loc.settings.plausible_deniability}
/>
</View>
);
} else {
return (
<View>
<FormValidationMessage>{loc.settings.storage_not_encrypted}</FormValidationMessage>
<BlueButton
icon={{
name: 'shield',
type: 'octicon',
color: BlueApp.settings.buttonTextColor,
}}
onPress={async () => {
this.setState({ isLoading: true });
let p1 = await prompt(loc.settings.password, loc.settings.password_explain).catch(() => {
this.setState({ isLoading: false });
this.props.navigation.goBack();
});
if (!p1) {
this.setState({ isLoading: false });
return;
}
let p2 = await prompt(loc.settings.password, loc.settings.retype_password).catch(() => {
this.setState({ isLoading: false });
this.props.navigation.goBack();
});
if (p1 === p2) {
await BlueApp.encryptStorage(p1);
this.setState({
isLoading: false,
storageIsEncrypted: await BlueApp.storageIsEncrypted(),
});
} else {
this.setState({ isLoading: false });
alert(loc.settings.passwords_do_not_match);
}
}}
title={loc.settings.encrypt_storage}
/>
</View>
);
}
})()}
</BlueCard>
</SafeBlueArea>
);
}
}
EncryptStorage.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
};

View File

@ -0,0 +1,69 @@
import React, { Component } from 'react';
import { Picker } from 'react-native';
import { BlueLoading, SafeBlueArea, BlueCard, BlueHeaderDefaultSub } from '../../BlueComponents';
import PropTypes from 'prop-types';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
let loc = require('../../loc');
export default class Language extends Component {
static navigationOptions = {
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
},
headerTintColor: '#0c2550',
};
constructor(props) {
super(props);
this.state = {
isLoading: true,
language: loc.getLanguage(),
};
}
async componentDidMount() {
this.setState({
isLoading: false,
storageIsEncrypted: await BlueApp.storageIsEncrypted(),
});
}
render() {
if (this.state.isLoading) {
return <BlueLoading />;
}
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<BlueHeaderDefaultSub leftText={loc.settings.language.toLowerCase()} rightComponent={null} />
<BlueCard>
<Picker
selectedValue={this.state.language}
onValueChange={(itemValue, itemIndex) => {
console.log('setLanguage', itemValue);
loc.setLanguage(itemValue);
loc.saveLanguage(itemValue);
return this.setState({ language: itemValue });
}}
>
<Picker.Item color={BlueApp.settings.foregroundColor} label="English" value="en" />
<Picker.Item color={BlueApp.settings.foregroundColor} label="Русский" value="ru" />
<Picker.Item color={BlueApp.settings.foregroundColor} label="Українська" value="ua" />
<Picker.Item color={BlueApp.settings.foregroundColor} label="Spanish" value="es" />
<Picker.Item color={BlueApp.settings.foregroundColor} label="Portuguese" value="pt" />
</Picker>
</BlueCard>
</SafeBlueArea>
);
}
}
Language.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
};

View File

@ -0,0 +1,57 @@
import React, { Component } from 'react';
import { ScrollView } from 'react-native';
import { BlueLoading, SafeBlueArea, BlueHeaderDefaultSub, BlueListItem } from '../../BlueComponents';
import PropTypes from 'prop-types';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
let loc = require('../../loc');
export default class Settings extends Component {
static navigationOptions = {
headerStyle: {
backgroundColor: '#FFFFFF',
borderBottomWidth: 0,
},
headerTintColor: '#0c2550',
};
constructor(props) {
super(props);
this.state = {
isLoading: true,
language: loc.getLanguage(),
};
}
async componentDidMount() {
this.setState({
isLoading: false,
storageIsEncrypted: await BlueApp.storageIsEncrypted(),
});
}
render() {
if (this.state.isLoading) {
return <BlueLoading />;
}
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<BlueHeaderDefaultSub leftText={loc.settings.header} rightComponent={null} />
<ScrollView maxHeight={450}>
<BlueListItem title={loc.settings.encrypt_storage} onPress={() => this.props.navigation.navigate('EncryptStorage')} />
<BlueListItem title={loc.settings.currency} />
<BlueListItem title={loc.settings.language} onPress={() => this.props.navigation.navigate('Language')} />
<BlueListItem title={loc.settings.about} onPress={() => this.props.navigation.navigate('About')} />
</ScrollView>
</SafeBlueArea>
);
}
}
Settings.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,
goBack: PropTypes.func,
}),
};

View File

@ -1,88 +1,30 @@
import { createStackNavigator } from 'react-navigation';
import WalletsList from './wallets/list';
import AddWallet from './wallets/add';
import ImportWallet from './wallets/import';
import WalletDetails from './wallets/details';
import WalletExport from './wallets/export';
import scanQrWif from './wallets/scanQrWif';
import Settings from '../screen/settings/settings';
import About from '../screen/settings/about';
import Language from '../screen/settings/language';
import EncryptStorage from '../screen/settings/encryptStorage';
import details from './transactions/details';
import rbf from './transactions/RBF';
import createrbf from './transactions/RBF-create';
import receiveDetails from './receive/details';
import sendDetails from './send/details';
import sendScanQrAddress from './send/scanQrAddress';
import sendCreate from './send/create';
import ManageFunds from './lnd/manageFunds';
import ScanLndInvoice from './lnd/scanLndInvoice';
const WalletsNavigator = createStackNavigator(
{
WalletsList: {
screen: WalletsList,
},
AddWallet: {
screen: AddWallet,
},
ImportWallet: {
screen: ImportWallet,
},
ScanQrWif: {
screen: scanQrWif,
},
WalletDetails: {
screen: WalletDetails,
},
WalletExport: {
screen: WalletExport,
},
//
TransactionDetails: {
screen: details,
},
RBF: {
screen: rbf,
},
CreateRBF: {
screen: createrbf,
},
//
ReceiveDetails: {
screen: receiveDetails,
},
//
SendDetails: {
screen: sendDetails,
},
ScanQrAddress: {
screen: sendScanQrAddress,
},
CreateTransaction: {
screen: sendCreate,
},
// LND:
ManageFunds: {
screen: ManageFunds,
},
ScanLndInvoice: {
screen: ScanLndInvoice,
},
const WalletsNavigator = createStackNavigator({
WalletsList: {
screen: WalletsList,
},
{
mode: 'modal',
Settings: {
screen: Settings,
path: 'Settings',
},
);
About: {
screen: About,
path: 'About',
},
Language: {
screen: Language,
path: 'Language',
},
EncryptStorage: {
screen: EncryptStorage,
path: 'EncryptStorage',
},
});
export default WalletsNavigator;