summaryrefslogtreecommitdiffhomepage
path: root/app/components
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2018-06-01 16:13:10 +0200
committerAndrej Mihajlov <and@mullvad.net>2018-06-05 12:11:55 +0200
commitca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087 (patch)
treeb1f7754eb50896ab3681e35fa4e08be642b940c9 /app/components
parent5852c980980de53e00d76a0bdb4b41bf5c0f5b39 (diff)
downloadmullvadvpn-ca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087.tar.xz
mullvadvpn-ca2f6fbfcad7b73d4ea63ef46cb1cab943ec9087.zip
Add formatted source code
Diffstat (limited to 'app/components')
-rw-r--r--app/components/Accordion.js86
-rw-r--r--app/components/Account.js46
-rw-r--r--app/components/AccountInput.js108
-rw-r--r--app/components/AccountStyles.js6
-rw-r--r--app/components/AdvancedSettings.js172
-rw-r--r--app/components/AdvancedSettingsStyles.js8
-rw-r--r--app/components/Connect.js240
-rw-r--r--app/components/ConnectStyles.js11
-rw-r--r--app/components/CustomScrollbars.android.js5
-rw-r--r--app/components/CustomScrollbars.js87
-rw-r--r--app/components/HeaderBar.js46
-rw-r--r--app/components/HeaderBarPlatformStyles.js2
-rw-r--r--app/components/HeaderBarStyles.js6
-rw-r--r--app/components/Img.android.js26
-rw-r--r--app/components/Img.js53
-rw-r--r--app/components/Layout.js22
-rw-r--r--app/components/LayoutStyles.js2
-rw-r--r--app/components/Login.js320
-rw-r--r--app/components/LoginStyles.js14
-rw-r--r--app/components/Map.js65
-rw-r--r--app/components/PlatformWindow.android.js10
-rw-r--r--app/components/PlatformWindow.js10
-rw-r--r--app/components/Preferences.js48
-rw-r--r--app/components/PreferencesStyles.js12
-rw-r--r--app/components/SelectLocation.js144
-rw-r--r--app/components/SelectLocationStyles.js6
-rw-r--r--app/components/Settings.js168
-rw-r--r--app/components/SettingsStyles.js121
-rw-r--r--app/components/Support.js323
-rw-r--r--app/components/SupportStyles.js311
-rw-r--r--app/components/SvgMap.js173
-rw-r--r--app/components/Switch.android.js18
-rw-r--r--app/components/Switch.js66
-rw-r--r--app/components/TransitionContainer.js260
-rw-r--r--app/components/TransitionContainerStyles.android.js36
-rw-r--r--app/components/TransitionContainerStyles.js4
-rw-r--r--app/components/styled/AppButton.js57
-rw-r--r--app/components/styled/AppButtonStyles.js22
-rw-r--r--app/components/styled/BlurAppButtonStyles.android.js12
-rw-r--r--app/components/styled/BlurAppButtonStyles.js12
-rw-r--r--app/components/styled/CellButton.js82
-rw-r--r--app/components/styled/index.js8
42 files changed, 1714 insertions, 1514 deletions
diff --git a/app/components/Accordion.js b/app/components/Accordion.js
index 3f2ceb1a06..f69389f6c7 100644
--- a/app/components/Accordion.js
+++ b/app/components/Accordion.js
@@ -6,7 +6,7 @@ import { Component, View, Styles, Animated, UserInterface } from 'reactxp';
export type AccordionProps = {
height: number | 'auto',
animationDuration?: number,
- children?: React.Node
+ children?: React.Node,
};
export type AccordionState = {
@@ -18,7 +18,7 @@ const containerOverflowStyle = Styles.createViewStyle({ overflow: 'hidden' });
export default class Accordion extends Component<AccordionProps, AccordionState> {
static defaultProps = {
height: 'auto',
- animationDuration: 350
+ animationDuration: 350,
};
state: AccordionState = {
@@ -34,36 +34,44 @@ export default class Accordion extends Component<AccordionProps, AccordionState>
super(props);
// set the initial height if it's known
- if(typeof(props.height) === 'number') {
+ if (typeof props.height === 'number') {
this.state = {
- animatedValue: Animated.createValue(props.height)
+ animatedValue: Animated.createValue(props.height),
};
}
}
componentWillUnmount() {
- if(this._animation) {
+ if (this._animation) {
this._animation.stop();
}
}
shouldComponentUpdate(nextProps: AccordionProps, nextState: AccordionState) {
- return nextState.animatedValue !== this.state.animatedValue ||
- nextProps.height !== this.props.height ||
- nextProps.children !== this.props.children;
+ return (
+ nextState.animatedValue !== this.state.animatedValue ||
+ nextProps.height !== this.props.height ||
+ nextProps.children !== this.props.children
+ );
}
componentDidUpdate(prevProps: AccordionProps, _prevState: AccordionState) {
- if(prevProps.height !== this.props.height) {
+ if (prevProps.height !== this.props.height) {
this._animateHeightChanges();
}
}
render() {
- const { style: style, height: _height, children, animationDuration: _animationDuration, ...otherProps } = this.props;
+ const {
+ style: style,
+ height: _height,
+ children,
+ animationDuration: _animationDuration,
+ ...otherProps
+ } = this.props;
const containerStyles = [style];
- if(this.state.animatedValue !== null) {
+ if (this.state.animatedValue !== null) {
const animatedStyle = Styles.createAnimatedViewStyle({
height: this.state.animatedValue,
});
@@ -72,59 +80,59 @@ export default class Accordion extends Component<AccordionProps, AccordionState>
}
return (
- <Animated.View { ...otherProps } style={ containerStyles } ref={ (node) => this._containerView = node }>
- <View onLayout={ this._contentLayoutDidChange }>
- { children }
- </View>
+ <Animated.View
+ {...otherProps}
+ style={containerStyles}
+ ref={(node) => (this._containerView = node)}>
+ <View onLayout={this._contentLayoutDidChange}>{children}</View>
</Animated.View>
);
}
_animateHeightChanges() {
const containerView = this._containerView;
- if(!containerView) {
+ if (!containerView) {
return;
}
- if(this._animation) {
+ if (this._animation) {
this._animation.stop();
this._animation = null;
}
- UserInterface.measureLayoutRelativeToWindow(containerView)
- .then((layout) => {
- const fromValue = this.state.animatedValue || Animated.createValue(layout.height);
- const toValue = this.props.height === 'auto' ? this._contentHeight : this.props.height;
+ UserInterface.measureLayoutRelativeToWindow(containerView).then((layout) => {
+ const fromValue = this.state.animatedValue || Animated.createValue(layout.height);
+ const toValue = this.props.height === 'auto' ? this._contentHeight : this.props.height;
- // calculate the animation duration based on travel distance
- const multiplier = Math.abs(toValue - layout.height) / Math.max(1, this._contentHeight);
- const duration = Math.ceil(this.props.animationDuration * multiplier);
+ // calculate the animation duration based on travel distance
+ const multiplier = Math.abs(toValue - layout.height) / Math.max(1, this._contentHeight);
+ const duration = Math.ceil(this.props.animationDuration * multiplier);
- const animation = Animated.timing(fromValue, {
- toValue: toValue,
- easing: Animated.Easing.InOut(),
- duration: duration,
- useNativeDriver: true,
- });
+ const animation = Animated.timing(fromValue, {
+ toValue: toValue,
+ easing: Animated.Easing.InOut(),
+ duration: duration,
+ useNativeDriver: true,
+ });
- this._animation = animation;
- this.setState({ animatedValue: fromValue }, () => {
- animation.start(this._onAnimationEnd);
- });
+ this._animation = animation;
+ this.setState({ animatedValue: fromValue }, () => {
+ animation.start(this._onAnimationEnd);
});
+ });
}
_onAnimationEnd = ({ finished }) => {
- if(finished) {
+ if (finished) {
this._animation = null;
// reset height after transition to let element layout naturally
// if animation finished without interruption
- if(this.props.height === 'auto') {
+ if (this.props.height === 'auto') {
this.setState({ animatedValue: null });
}
}
- }
+ };
- _contentLayoutDidChange = ({ height }) => this._contentHeight = height;
-} \ No newline at end of file
+ _contentLayoutDidChange = ({ height }) => (this._contentHeight = height);
+}
diff --git a/app/components/Account.js b/app/components/Account.js
index 4ec57aaf1e..b4eef86712 100644
--- a/app/components/Account.js
+++ b/app/components/Account.js
@@ -11,10 +11,10 @@ import { formatAccount } from '../lib/formatters';
import type { AccountReduxState } from '../redux/account/reducers';
export type AccountProps = {
- account: AccountReduxState;
- onLogout: () => void;
- onClose: () => void;
- onBuyMore: () => void;
+ account: AccountReduxState,
+ onLogout: () => void,
+ onClose: () => void,
+ onBuyMore: () => void,
};
export default class Account extends Component {
@@ -30,51 +30,49 @@ export default class Account extends Component {
<Layout>
<Container>
<View style={styles.account}>
- <Button style={styles.account__close}
- onPress={ this.props.onClose }
- testName='account__close'>
+ <Button
+ style={styles.account__close}
+ onPress={this.props.onClose}
+ testName="account__close">
<Img height={24} width={24} style={styles.account__close_icon} source="icon-back" />
<Text style={styles.account__close_title}>Settings</Text>
</Button>
<View style={styles.account__container}>
-
<View style={styles.account__header}>
<Text style={styles.account__title}>Account</Text>
</View>
<View style={styles.account__content}>
<View style={styles.account__main}>
-
<View style={styles.account__row}>
<Text style={styles.account__row_label}>Account ID</Text>
- <Text style={styles.account__row_value}>{ formattedAccountToken }</Text>
+ <Text style={styles.account__row_value}>{formattedAccountToken}</Text>
</View>
<View style={styles.account__row}>
<Text style={styles.account__row_label}>Paid until</Text>
- { isOutOfTime ?
- <Text style={styles.account__out_of_time} testName='account__out_of_time'>OUT OF TIME</Text>
- :
- <Text style={styles.account__row_value}>{ formattedExpiry }</Text>
- }
+ {isOutOfTime ? (
+ <Text style={styles.account__out_of_time} testName="account__out_of_time">
+ OUT OF TIME
+ </Text>
+ ) : (
+ <Text style={styles.account__row_value}>{formattedExpiry}</Text>
+ )}
</View>
<View style={styles.account__footer}>
<GreenButton
- onPress={ this.props.onBuyMore }
- text='Buy more credit'
- icon='icon-extLink'
- testName='account__buymore'>
+ onPress={this.props.onBuyMore}
+ text="Buy more credit"
+ icon="icon-extLink"
+ testName="account__buymore">
<Label>Buy more credit</Label>
- <Img source='icon-extLink' height={16} width={16} />
+ <Img source="icon-extLink" height={16} width={16} />
</GreenButton>
- <RedButton
- onPress={ this.props.onLogout }
- testName='account__logout'>
+ <RedButton onPress={this.props.onLogout} testName="account__logout">
Log out
</RedButton>
</View>
-
</View>
</View>
</View>
diff --git a/app/components/AccountInput.js b/app/components/AccountInput.js
index e113b1679c..5a8fa47336 100644
--- a/app/components/AccountInput.js
+++ b/app/components/AccountInput.js
@@ -18,14 +18,14 @@ declare class ClipboardEvent extends Event {
}
export type AccountInputProps = {
- value: string;
- onEnter: ?(() => void);
- onChange: ?((newValue: string) => void);
+ value: string,
+ onEnter: ?() => void,
+ onChange: ?(newValue: string) => void,
};
type AccountInputState = {
- value: string;
- selectionRange: SelectionRange;
+ value: string,
+ selectionRange: SelectionRange,
};
type SelectionRange = [number, number];
@@ -34,12 +34,12 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
static defaultProps = {
value: '',
onEnter: null,
- onChange: null
+ onChange: null,
};
state = {
value: '',
- selectionRange: [0, 0]
+ selectionRange: [0, 0],
};
_ref: ?TextInput;
@@ -53,25 +53,27 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
this.state = {
value: val,
- selectionRange: [val.length, val.length]
+ selectionRange: [val.length, val.length],
};
}
componentWillReceiveProps(nextProps: AccountInputProps) {
const nextVal = this.sanitize(nextProps.value);
- if(nextVal !== this.state.value) {
+ if (nextVal !== this.state.value) {
const len = nextVal.length;
this.setState({ value: nextVal, selectionRange: [len, len] });
}
}
shouldComponentUpdate(nextProps: AccountInputProps, nextState: AccountInputState) {
- return (this.props.value !== nextProps.value ||
- this.props.onEnter !== nextProps.onEnter ||
- this.props.onChange !== nextProps.onChange ||
- this.state.value !== nextState.value ||
- this.state.selectionRange[0] !== nextState.selectionRange[0] ||
- this.state.selectionRange[1] !== nextState.selectionRange[1]);
+ return (
+ this.props.value !== nextProps.value ||
+ this.props.onEnter !== nextProps.onEnter ||
+ this.props.onChange !== nextProps.onChange ||
+ this.state.value !== nextState.value ||
+ this.state.selectionRange[0] !== nextState.selectionRange[0] ||
+ this.state.selectionRange[1] !== nextState.selectionRange[1]
+ );
}
render() {
@@ -79,19 +81,20 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
// eslint-disable-next-line no-unused-vars
const { value, onChange, onEnter, ...otherProps } = this.props;
return (
- <TextInput { ...otherProps }
- value={ displayString }
- onSelectionChange={ this.onSelect }
- onPaste={ this.onPaste }
- onCut={ this.onCut }
- ref={ (ref) => this.onRef(ref) }
- autoCorrect={ false }
- onChangeText={ () => {} }
- onKeyPress={ this.onKeyPress }
+ <TextInput
+ {...otherProps}
+ value={displayString}
+ onSelectionChange={this.onSelect}
+ onPaste={this.onPaste}
+ onCut={this.onCut}
+ ref={(ref) => this.onRef(ref)}
+ autoCorrect={false}
+ onChangeText={() => {}}
+ onKeyPress={this.onKeyPress}
returnKeyType="done"
keyboardType="numeric"
placeholderTextColor={colors.blue20}
- testName='AccountInput'
+ testName="AccountInput"
/>
);
}
@@ -123,7 +126,6 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
return { value: newVal, selectionRange: [selectionOffset, selectionOffset] };
}
-
/**
* Modify string by removing single character or range of characters based on selection range.
*
@@ -137,7 +139,7 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
remove(val: string, selRange: SelectionRange): AccountInputState {
let newVal, selectionOffset;
- if(selRange[0] === selRange[1]) {
+ if (selRange[0] === selRange[1]) {
const oneOff = Math.max(0, selRange[0] - 1);
const head = val.slice(0, oneOff);
const tail = val.slice(selRange[0], val.length);
@@ -153,7 +155,6 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
return { value: newVal, selectionRange: [selectionOffset, selectionOffset] };
}
-
/**
* Convert DOM selection range to internal selection range
*
@@ -176,12 +177,11 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
const within = countSpaces(fmt.slice(start, end));
start -= before;
- end -= (before + within);
+ end -= before + within;
- return [ start, end ];
+ return [start, end];
}
-
/**
* Convert internal selection range to DOM selection range
*
@@ -194,7 +194,9 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
*/
toDomSelection(val: string, selRange: SelectionRange): SelectionRange {
const countSpaces = (val, untilIndex) => {
- if(val.length > 12) { return 0; }
+ if (val.length > 12) {
+ return 0;
+ }
return Math.floor(untilIndex / 4); // groups of 4 digits
};
@@ -206,7 +208,7 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
start += startSpaces;
end += startSpaces + (endSpaces - startSpaces);
- return [ start, end ];
+ return [start, end];
}
// Events
@@ -214,40 +216,42 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
onKeyPress = (e: KeyboardEvent) => {
const { value, selectionRange } = this.state;
- if(e.which === 8) { // backspace
+ if (e.which === 8) {
+ // backspace
this._ignoreSelect = true;
const result = this.remove(value, selectionRange);
e.preventDefault();
this.setState(result, () => {
this._ignoreSelect = false;
- if(this.props.onChange) {
+ if (this.props.onChange) {
this.props.onChange(result.value);
}
});
- } else if(/^[0-9]$/.test(e.key)) { // digits or cmd+v
+ } else if (/^[0-9]$/.test(e.key)) {
+ // digits or cmd+v
this._ignoreSelect = true;
const result = this.insert(value, e.key, selectionRange);
e.preventDefault();
this.setState(result, () => {
this._ignoreSelect = false;
- if(this.props.onChange) {
+ if (this.props.onChange) {
this.props.onChange(result.value);
}
});
- } else if(e.which === 13 && this.props.onEnter) {
+ } else if (e.which === 13 && this.props.onEnter) {
this.props.onEnter();
}
- }
+ };
onSelect = (start: number, end: number) => {
- if (this._ignoreSelect){
+ if (this._ignoreSelect) {
return;
}
const selRange = this.toInternalSelectionRange(this.sanitize(this.state.value), [start, end]);
this.setState({ selectionRange: selRange });
- }
+ };
onPaste = (e: ClipboardEvent) => {
const { value, selectionRange } = this.state;
@@ -256,15 +260,15 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
const result = this.insert(value, filteredData, selectionRange);
e.preventDefault();
this.setState(result, () => {
- if(this.props.onChange) {
+ if (this.props.onChange) {
this.props.onChange(result.value);
}
});
- }
+ };
onCut = (e: ClipboardEvent) => {
const target = e.target;
- if(!(target instanceof HTMLInputElement)) {
+ if (!(target instanceof HTMLInputElement)) {
throw new Error('ref must be an instance of HTMLInputElement');
}
@@ -273,7 +277,7 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
e.preventDefault();
// range is not empty?
- if(selectionRange[0] !== selectionRange[1]) {
+ if (selectionRange[0] !== selectionRange[1]) {
const result = this.remove(value, selectionRange);
const domSelectionRange = this.toDomSelection(value, selectionRange);
const slice = target.value.slice(domSelectionRange[0], domSelectionRange[1]);
@@ -281,26 +285,28 @@ export default class AccountInput extends React.Component<AccountInputProps, Acc
e.clipboardData.setData('text', slice);
this.setState(result, () => {
- if(this.props.onChange) {
+ if (this.props.onChange) {
this.props.onChange(result.value);
}
});
}
- }
+ };
onRef = (ref: ?TextInput) => {
this._ref = ref;
- if(!ref) { return; }
+ if (!ref) {
+ return;
+ }
const { value, selectionRange } = this.state;
const domRange = this.toDomSelection(value, selectionRange);
ref.selectRange(domRange[0], domRange[1]);
- }
+ };
focus() {
- if(this._ref) {
+ if (this._ref) {
this._ref.focus();
}
}
-} \ No newline at end of file
+}
diff --git a/app/components/AccountStyles.js b/app/components/AccountStyles.js
index b5ac785fe0..67c16900a7 100644
--- a/app/components/AccountStyles.js
+++ b/app/components/AccountStyles.js
@@ -104,6 +104,6 @@ export default {
lineHeight: 20,
letterSpacing: -0.2,
color: colors.white80,
- }
- })
-}; \ No newline at end of file
+ },
+ }),
+};
diff --git a/app/components/AdvancedSettings.js b/app/components/AdvancedSettings.js
index c4f014d210..eca00a4da1 100644
--- a/app/components/AdvancedSettings.js
+++ b/app/components/AdvancedSettings.js
@@ -9,7 +9,6 @@ import styles from './AdvancedSettingsStyles';
import Img from './Img';
export class AdvancedSettings extends Component {
-
props: {
protocol: string,
port: string | number,
@@ -27,62 +26,66 @@ export class AdvancedSettings extends Component {
portSelector = this._createPortSelector();
}
- return <BaseLayout onClose={ this.props.onClose }>
-
- <Selector
- title={ 'Network protocols' }
- values={ ['Automatic', 'UDP', 'TCP'] }
- value={ protocol }
- onSelect={ protocol => {
- this.props.onUpdate(protocol, 'Automatic');
- }}/>
+ return (
+ <BaseLayout onClose={this.props.onClose}>
+ <Selector
+ title={'Network protocols'}
+ values={['Automatic', 'UDP', 'TCP']}
+ value={protocol}
+ onSelect={(protocol) => {
+ this.props.onUpdate(protocol, 'Automatic');
+ }}
+ />
- <View style={ styles.advanced_settings__cell_spacer }></View>
+ <View style={styles.advanced_settings__cell_spacer} />
- { portSelector }
-
- </BaseLayout>;
+ {portSelector}
+ </BaseLayout>
+ );
}
_createPortSelector() {
const protocol = this.props.protocol.toUpperCase();
- const ports = protocol === 'TCP'
- ? ['Automatic', 80, 443]
- : ['Automatic', 1194, 1195, 1196, 1197, 1300, 1301, 1302];
+ const ports =
+ protocol === 'TCP'
+ ? ['Automatic', 80, 443]
+ : ['Automatic', 1194, 1195, 1196, 1197, 1300, 1301, 1302];
- return <Selector
- title={ protocol + ' port' }
- values={ ports }
- value={ this.props.port }
- onSelect={ port => {
- this.props.onUpdate(protocol, port);
- }} />;
+ return (
+ <Selector
+ title={protocol + ' port'}
+ values={ports}
+ value={this.props.port}
+ onSelect={(port) => {
+ this.props.onUpdate(protocol, port);
+ }}
+ />
+ );
}
}
class Selector extends Component {
-
props: {
title: string,
values: Array<*>,
value: *,
onSelect: (*) => void,
- }
+ };
state = { hoveredButtonIndex: -1 };
handleButtonHover = (value) => {
this.setState({ hoveredButtonIndex: value });
- }
+ };
render() {
- return <View>
- <View style={ styles.advanced_settings__section_title }>
- { this.props.title }
- </View>
+ return (
+ <View>
+ <View style={styles.advanced_settings__section_title}>{this.props.title}</View>
- { this.props.values.map(value => this._renderCell(value)) }
- </View>;
+ {this.props.values.map((value) => this._renderCell(value))}
+ </View>
+ );
}
_renderCell(value) {
@@ -95,54 +98,75 @@ class Selector extends Component {
}
_renderSelectedCell(value) {
- return <Button style={[ styles.advanced_settings__cell, value === this.state.hoveredButtonIndex ? styles.advanced_settings__cell_selected_hover : null ]}
- onPress={ () => this.props.onSelect(value) }
- onHoverStart={() => this.handleButtonHover(value)}
- onHoverEnd={() => this.handleButtonHover(-1)}
- key={ value }>
- <Img style={ styles.advanced_settings__cell_icon }
- source='icon-tick'
- tintColor='currentColor'/>
- <Text style={ styles.advanced_settings__cell_label }>{ value }</Text>
- </Button>;
+ return (
+ <Button
+ style={[
+ styles.advanced_settings__cell,
+ value === this.state.hoveredButtonIndex
+ ? styles.advanced_settings__cell_selected_hover
+ : null,
+ ]}
+ onPress={() => this.props.onSelect(value)}
+ onHoverStart={() => this.handleButtonHover(value)}
+ onHoverEnd={() => this.handleButtonHover(-1)}
+ key={value}>
+ <Img
+ style={styles.advanced_settings__cell_icon}
+ source="icon-tick"
+ tintColor="currentColor"
+ />
+ <Text style={styles.advanced_settings__cell_label}>{value}</Text>
+ </Button>
+ );
}
_renderUnselectedCell(value) {
- return <Button style={[ styles.advanced_settings__cell_dimmed, value === this.state.hoveredButtonIndex ? styles.advanced_settings__cell_hover : null ]}
- onPress={ () => this.props.onSelect(value) }
- onHoverStart={() => this.handleButtonHover(value)}
- onHoverEnd={() => this.handleButtonHover(-1)}
- key={ value }>
- <View style={ styles.advanced_settings__cell_icon }></View>
- <Text style={ styles.advanced_settings__cell_label }>{ value }</Text>
- </Button>;
+ return (
+ <Button
+ style={[
+ styles.advanced_settings__cell_dimmed,
+ value === this.state.hoveredButtonIndex ? styles.advanced_settings__cell_hover : null,
+ ]}
+ onPress={() => this.props.onSelect(value)}
+ onHoverStart={() => this.handleButtonHover(value)}
+ onHoverEnd={() => this.handleButtonHover(-1)}
+ key={value}>
+ <View style={styles.advanced_settings__cell_icon} />
+ <Text style={styles.advanced_settings__cell_label}>{value}</Text>
+ </Button>
+ );
}
}
function BaseLayout(props) {
- return <Layout>
- <Container>
- <View style={ styles.advanced_settings }>
- <Button style={ styles.advanced_settings__close }
- onPress={ props.onClose }
- testName='closeButton'>
- <View style={ styles.advanced_settings__close_content }>
- <Img height={24} width={24} style={ styles.advanced_settings__close_icon } source="icon-back" />
- <Text style={ styles.advanced_settings__close_title }>Settings</Text>
- </View>
- </Button>
- <View style={ styles.advanced_settings__container }>
- <View style={ styles.advanced_settings__header }>
- <Text style={ styles.advanced_settings__title }>Advanced</Text>
- </View>
- <CustomScrollbars style={styles.advanced_settings__scrollview} autoHide={ true }>
- <View style={ styles.advanced_settings__content }>
- { props.children }
+ return (
+ <Layout>
+ <Container>
+ <View style={styles.advanced_settings}>
+ <Button
+ style={styles.advanced_settings__close}
+ onPress={props.onClose}
+ testName="closeButton">
+ <View style={styles.advanced_settings__close_content}>
+ <Img
+ height={24}
+ width={24}
+ style={styles.advanced_settings__close_icon}
+ source="icon-back"
+ />
+ <Text style={styles.advanced_settings__close_title}>Settings</Text>
</View>
- </CustomScrollbars>
+ </Button>
+ <View style={styles.advanced_settings__container}>
+ <View style={styles.advanced_settings__header}>
+ <Text style={styles.advanced_settings__title}>Advanced</Text>
+ </View>
+ <CustomScrollbars style={styles.advanced_settings__scrollview} autoHide={true}>
+ <View style={styles.advanced_settings__content}>{props.children}</View>
+ </CustomScrollbars>
+ </View>
</View>
- </View>
- </Container>
- </Layout>;
+ </Container>
+ </Layout>
+ );
}
-
diff --git a/app/components/AdvancedSettingsStyles.js b/app/components/AdvancedSettingsStyles.js
index 75ed925b70..95ec71fb41 100644
--- a/app/components/AdvancedSettingsStyles.js
+++ b/app/components/AdvancedSettingsStyles.js
@@ -137,7 +137,7 @@ export default {
fontWeight: '600',
lineHeight: 20,
letterSpacing: -0.2,
- color: 'rgba(255,255,255,0.8)'
- }
- })
-}; \ No newline at end of file
+ color: 'rgba(255,255,255,0.8)',
+ },
+ }),
+};
diff --git a/app/components/Connect.js b/app/components/Connect.js
index 79d14df743..3fbe04cefa 100644
--- a/app/components/Connect.js
+++ b/app/components/Connect.js
@@ -50,7 +50,6 @@ export default class Connect extends Component<ConnectProps, ConnectState> {
// shallow compare the connection
!shallowCompare(prevConnection, nextConnection) ||
!shallowCompare(otherPrevProps, otherNextProps) ||
-
prevState.mapOffset[0] !== nextState.mapOffset[0] ||
prevState.mapOffset[1] !== nextState.mapOffset[1] ||
prevState.showCopyIPMessage !== nextState.showCopyIPMessage
@@ -58,7 +57,7 @@ export default class Connect extends Component<ConnectProps, ConnectState> {
}
componentWillUnmount() {
- if(this._copyTimer) {
+ if (this._copyTimer) {
clearTimeout(this._copyTimer);
}
}
@@ -69,10 +68,13 @@ export default class Connect extends Component<ConnectProps, ConnectState> {
return (
<Layout>
- <Header style={ this.headerStyle() } showSettings={ true } onSettings={ this.props.onSettings } testName='header'/>
- <Container>
- { child }
- </Container>
+ <Header
+ style={this.headerStyle()}
+ showSettings={true}
+ onSettings={this.props.onSettings}
+ testName="header"
+ />
+ <Container>{child}</Container>
</Layout>
);
}
@@ -84,21 +86,16 @@ export default class Connect extends Component<ConnectProps, ConnectState> {
<Img source="icon-fail" height={60} width={60} alt="" />
</View>
<View style={styles.status}>
- <View style={styles.error_title}>
- { error.title }
- </View>
- <View style={styles.error_message}>
- { error.message }
- </View>
- { error.type === 'NO_CREDIT' ?
+ <View style={styles.error_title}>{error.title}</View>
+ <View style={styles.error_message}>{error.message}</View>
+ {error.type === 'NO_CREDIT' ? (
<View>
- <GreenButton onPress={ this.onExternalLink.bind(this, 'purchase') }>
+ <GreenButton onPress={this.onExternalLink.bind(this, 'purchase')}>
<Label>Buy more time</Label>
- <Img source='icon-extLink' height={16} width={16} />
+ <Img source="icon-extLink" height={16} width={16} />
</GreenButton>
</View>
- : null
- }
+ ) : null}
</View>
</View>
);
@@ -108,7 +105,7 @@ export default class Connect extends Component<ConnectProps, ConnectState> {
const { longitude, latitude, status } = this.props.connection;
// when the user location is known
- if(typeof(longitude) === 'number' && typeof(latitude) === 'number') {
+ if (typeof longitude === 'number' && typeof latitude === 'number') {
return {
center: [longitude, latitude],
// do not show the marker when connecting
@@ -133,141 +130,158 @@ export default class Connect extends Component<ConnectProps, ConnectState> {
}
_updateMapOffset = (spinnerNode: ?HTMLElement) => {
- if(spinnerNode) {
+ if (spinnerNode) {
// calculate the vertical offset from the center of the map
// to shift the center of the map upwards to align the centers
// of spinner and marker on the map
const y = spinnerNode.offsetTop + spinnerNode.clientHeight * 0.5;
this.setState({
- mapOffset: [0, y]
+ mapOffset: [0, y],
});
}
- }
+ };
renderMap() {
- let [ isConnecting, isConnected, isDisconnected ] = [false, false, false];
- switch(this.props.connection.status) {
- case 'connecting': isConnecting = true; break;
- case 'connected': isConnected = true; break;
- case 'disconnected': isDisconnected = true; break;
+ let [isConnecting, isConnected, isDisconnected] = [false, false, false];
+ switch (this.props.connection.status) {
+ case 'connecting':
+ isConnecting = true;
+ break;
+ case 'connected':
+ isConnected = true;
+ break;
+ case 'disconnected':
+ isDisconnected = true;
+ break;
}
return (
<View style={styles.connect}>
<View style={styles.map}>
- <Map style={{ width: '100%', height: '100%' }} { ...this._getMapProps() } />
+ <Map style={{ width: '100%', height: '100%' }} {...this._getMapProps()} />
</View>
<View style={styles.container}>
+ {this._renderIsBlockingInternetMessage()}
- { this._renderIsBlockingInternetMessage() }
-
- { /* show spinner when connecting */ }
- { isConnecting ?
- <View style={ styles.status_icon }>
- <Img source='icon-spinner' height={60} width={60} alt="" ref={ this._updateMapOffset } />
+ {/* show spinner when connecting */}
+ {isConnecting ? (
+ <View style={styles.status_icon}>
+ <Img
+ source="icon-spinner"
+ height={60}
+ width={60}
+ alt=""
+ ref={this._updateMapOffset}
+ />
</View>
- : null
- }
+ ) : null}
<View style={styles.status}>
+ <View style={this.networkSecurityStyle()} testName="networkSecurityMessage">
+ {this.networkSecurityMessage()}
+ </View>
- <View style={ this.networkSecurityStyle() } testName='networkSecurityMessage'>{ this.networkSecurityMessage() }</View>
-
- { /*
+ {/*
**********************************
Begin: Location block
**********************************
- */ }
+ */}
- { /* location when connecting or disconnected */ }
- { isConnecting || isDisconnected ?
- <Text style={styles.status_location} testName='location'>
- { this.props.connection.country }
+ {/* location when connecting or disconnected */}
+ {isConnecting || isDisconnected ? (
+ <Text style={styles.status_location} testName="location">
+ {this.props.connection.country}
</Text>
- : null
- }
+ ) : null}
- { /* location when connected */ }
- { isConnected ?
- <Text style={styles.status_location} testName='location'>
- { this.props.connection.city }
- { this.props.connection.city && <br/> }
- { this.props.connection.country }
+ {/* location when connected */}
+ {isConnected ? (
+ <Text style={styles.status_location} testName="location">
+ {this.props.connection.city}
+ {this.props.connection.city && <br />}
+ {this.props.connection.country}
</Text>
- :null
- }
+ ) : null}
- { /*
+ {/*
**********************************
End: Location block
**********************************
- */ }
+ */}
- <Text style={ this.ipAddressStyle() } onPress={ this.onIPAddressClick.bind(this) }>
- { (isConnected || isDisconnected) ? (
- <Text testName='ipAddress'>{
- this.state.showCopyIPMessage ?
- 'IP copied to clipboard!' :
- this.props.connection.ip
- }</Text>) : null }
+ <Text style={this.ipAddressStyle()} onPress={this.onIPAddressClick.bind(this)}>
+ {isConnected || isDisconnected ? (
+ <Text testName="ipAddress">
+ {this.state.showCopyIPMessage
+ ? 'IP copied to clipboard!'
+ : this.props.connection.ip}
+ </Text>
+ ) : null}
</Text>
</View>
-
- { /*
+ {/*
**********************************
Begin: Footer block
**********************************
- */ }
+ */}
- { /* footer when disconnected */ }
- { isDisconnected ?
+ {/* footer when disconnected */}
+ {isDisconnected ? (
<View style={styles.footer}>
- <TransparentButton onPress={ this.props.onSelectLocation }>
- <Label>{ this.props.selectedRelayName }</Label>
- <Img height={12} width={7} source='icon-chevron' />
+ <TransparentButton onPress={this.props.onSelectLocation}>
+ <Label>{this.props.selectedRelayName}</Label>
+ <Img height={12} width={7} source="icon-chevron" />
</TransparentButton>
- <GreenButton onPress={ this.props.onConnect } testName='secureConnection'>Secure my connection</GreenButton>
+ <GreenButton onPress={this.props.onConnect} testName="secureConnection">
+ Secure my connection
+ </GreenButton>
</View>
- : null
- }
+ ) : null}
- { /* footer when connecting */ }
- { isConnecting ?
+ {/* footer when connecting */}
+ {isConnecting ? (
<View style={styles.footer}>
- <TransparentButton onPress={ this.props.onSelectLocation }>Switch location</TransparentButton>
- <RedTransparentButton onPress={ this.props.onDisconnect }>Cancel</RedTransparentButton>
+ <TransparentButton onPress={this.props.onSelectLocation}>
+ Switch location
+ </TransparentButton>
+ <RedTransparentButton onPress={this.props.onDisconnect}>Cancel</RedTransparentButton>
</View>
- : null
- }
+ ) : null}
- { /* footer when connected */ }
- { isConnected ?
+ {/* footer when connected */}
+ {isConnected ? (
<View style={styles.footer}>
- <TransparentButton onPress={ this.props.onSelectLocation }>Switch location</TransparentButton>
- <RedTransparentButton onPress={ this.props.onDisconnect } testName='disconnect'>Disconnect</RedTransparentButton>
+ <TransparentButton onPress={this.props.onSelectLocation}>
+ Switch location
+ </TransparentButton>
+ <RedTransparentButton onPress={this.props.onDisconnect} testName="disconnect">
+ Disconnect
+ </RedTransparentButton>
</View>
- : null
- }
+ ) : null}
- { /*
+ {/*
**********************************
End: Footer block
**********************************
- */ }
-
+ */}
</View>
</View>
);
}
_renderIsBlockingInternetMessage() {
- return <Accordion style={styles.blocking_container} height={ (this.props.connection.status === 'connecting') ? 'auto' : 0 }>
- <Text style={styles.blocking_message}>
- <Text style={styles.blocking_icon}>&nbsp;</Text>
- <Text>BLOCKING INTERNET</Text>
- </Text>
- </Accordion>;
+ return (
+ <Accordion
+ style={styles.blocking_container}
+ height={this.props.connection.status === 'connecting' ? 'auto' : 0}>
+ <Text style={styles.blocking_message}>
+ <Text style={styles.blocking_icon}>&nbsp;</Text>
+ <Text>BLOCKING INTERNET</Text>
+ </Text>
+ </Accordion>
+ );
}
// Handlers
@@ -286,37 +300,40 @@ export default class Connect extends Component<ConnectProps, ConnectState> {
// Private
headerStyle(): HeaderBarStyle {
- switch(this.props.connection.status) {
- case 'disconnected':
- return 'error';
- case 'connecting':
- case 'connected':
- return 'success';
+ switch (this.props.connection.status) {
+ case 'disconnected':
+ return 'error';
+ case 'connecting':
+ case 'connected':
+ return 'success';
}
throw new Error('Invalid ConnectionState');
}
networkSecurityStyle(): Types.Style {
let classes = [styles.status_security];
- if(this.props.connection.status === 'connected') {
+ if (this.props.connection.status === 'connected') {
classes.push(styles.status_security__secure);
- } else if(this.props.connection.status === 'disconnected') {
+ } else if (this.props.connection.status === 'disconnected') {
classes.push(styles.status_security__unsecured);
}
return classes;
}
networkSecurityMessage(): string {
- switch(this.props.connection.status) {
- case 'connected': return 'SECURE CONNECTION';
- case 'connecting': return 'CREATING SECURE CONNECTION';
- default: return 'UNSECURED CONNECTION';
+ switch (this.props.connection.status) {
+ case 'connected':
+ return 'SECURE CONNECTION';
+ case 'connecting':
+ return 'CREATING SECURE CONNECTION';
+ default:
+ return 'UNSECURED CONNECTION';
}
}
ipAddressStyle(): Types.Style {
var classes = [styles.status_ipaddress];
- if(this.props.connection.status === 'connecting') {
+ if (this.props.connection.status === 'connecting') {
classes.push(styles.status_ipaddress__invisible);
}
return classes;
@@ -324,13 +341,13 @@ export default class Connect extends Component<ConnectProps, ConnectState> {
displayError(): ?BackendError {
// Offline?
- if(!this.props.connection.isOnline) {
+ if (!this.props.connection.isOnline) {
return new BackendError('NO_INTERNET');
}
// No credit?
const expiry = this.props.accountExpiry;
- if(expiry && moment(expiry).isSameOrBefore(moment())) {
+ if (expiry && moment(expiry).isSameOrBefore(moment())) {
return new BackendError('NO_CREDIT');
}
@@ -340,8 +357,5 @@ export default class Connect extends Component<ConnectProps, ConnectState> {
function shallowCompare(lhs: Object, rhs: Object) {
const keys = Object.keys(lhs);
- return (
- keys.length === Object.keys(rhs).length &&
- keys.every(key => lhs[key] === rhs[key])
- );
+ return keys.length === Object.keys(rhs).length && keys.every((key) => lhs[key] === rhs[key]);
}
diff --git a/app/components/ConnectStyles.js b/app/components/ConnectStyles.js
index 413d2f0c1d..85558d6a12 100644
--- a/app/components/ConnectStyles.js
+++ b/app/components/ConnectStyles.js
@@ -21,11 +21,10 @@ export default {
container: {
flexDirection: 'column',
flex: 1,
- position: 'relative', /* need this for z-index to work to cover map */
+ position: 'relative' /* need this for z-index to work to cover map */,
zIndex: 1,
-
},
- footer:{
+ footer: {
flex: 0,
marginBottom: 16,
},
@@ -62,7 +61,7 @@ export default {
flex: 1,
},
status_icon: {
- position:'absolute',
+ position: 'absolute',
alignSelf: 'center',
width: 60,
height: 60,
@@ -92,7 +91,7 @@ export default {
letterSpacing: -0.7,
color: colors.white,
marginBottom: 7,
- flex:0,
+ flex: 0,
},
error_title: {
fontFamily: 'DINPro',
@@ -143,4 +142,4 @@ export default {
marginBottom: 4,
},
}),
-}; \ No newline at end of file
+};
diff --git a/app/components/CustomScrollbars.android.js b/app/components/CustomScrollbars.android.js
index 8c9ea03da2..dadc462234 100644
--- a/app/components/CustomScrollbars.android.js
+++ b/app/components/CustomScrollbars.android.js
@@ -28,9 +28,6 @@ export default class CustomScrollbars extends Component<Props, State> {
render() {
const { autoHide: _autoHide, thumbInset: _thumbInset, children, ...otherProps } = this.props;
- return (
- <View { ...otherProps }>
- { children }
- </View>);
+ return <View {...otherProps}>{children}</View>;
}
}
diff --git a/app/components/CustomScrollbars.js b/app/components/CustomScrollbars.js
index cb1014fd0a..6539a91185 100644
--- a/app/components/CustomScrollbars.js
+++ b/app/components/CustomScrollbars.js
@@ -39,7 +39,7 @@ export default class CustomScrollbars extends React.Component<Props, State> {
scrollTo(x: number, y: number) {
const scrollable = this._scrollableElement;
- if(scrollable) {
+ if (scrollable) {
scrollable.scrollLeft = x;
scrollable.scrollTop = y;
}
@@ -47,10 +47,12 @@ export default class CustomScrollbars extends React.Component<Props, State> {
scrollToElement(child: HTMLElement, scrollPosition: ScrollPosition) {
const scrollable = this._scrollableElement;
- if(scrollable) {
+ if (scrollable) {
// throw if child is not a descendant of scroll view
- if(!scrollable.contains(child)) {
- throw new Error('Cannot scroll to an element which is not a descendant of CustomScrollbars.');
+ if (!scrollable.contains(child)) {
+ throw new Error(
+ 'Cannot scroll to an element which is not a descendant of CustomScrollbars.',
+ );
}
const scrollTop = this._computeScrollTop(scrollable, child, scrollPosition);
@@ -62,11 +64,11 @@ export default class CustomScrollbars extends React.Component<Props, State> {
componentDidMount() {
this._updateScrollbarsHelper({
position: true,
- size: true
+ size: true,
});
// show scroll indicators briefly when mounted
- if(this.props.autoHide) {
+ if (this.props.autoHide) {
this._startAutoHide();
}
}
@@ -78,7 +80,7 @@ export default class CustomScrollbars extends React.Component<Props, State> {
componentDidUpdate() {
this._updateScrollbarsHelper({
position: true,
- size: true
+ size: true,
});
}
@@ -87,15 +89,18 @@ export default class CustomScrollbars extends React.Component<Props, State> {
const showScrollbars = this.state.canScroll && this.state.showScrollIndicators;
const thumbAnimationClass = showScrollbars ? ' custom-scrollbars__thumb--visible' : '';
return (
- <div {...otherProps } className="custom-scrollbars">
- <div className={ `custom-scrollbars__thumb ${thumbAnimationClass}` }
+ <div {...otherProps} className="custom-scrollbars">
+ <div
+ className={`custom-scrollbars__thumb ${thumbAnimationClass}`}
style={{ position: 'absolute', top: 0, right: 0 }}
- ref={ this._onThumbRef }></div>
- <div className="custom-scrollbars__scrollable"
+ ref={this._onThumbRef}
+ />
+ <div
+ className="custom-scrollbars__scrollable"
style={{ overflow: 'auto' }}
- onScroll={ this._onScroll }
- ref={ this._onScrollableRef }>
- { children }
+ onScroll={this._onScroll}
+ ref={this._onScrollableRef}>
+ {children}
</div>
</div>
);
@@ -103,22 +108,22 @@ export default class CustomScrollbars extends React.Component<Props, State> {
_onScrollableRef = (ref) => {
this._scrollableElement = ref;
- }
+ };
_onThumbRef = (ref) => {
this._thumbElement = ref;
- }
+ };
_onScroll = () => {
this._updateScrollbarsHelper({ position: true });
- if(this.props.autoHide) {
+ if (this.props.autoHide) {
this._startAutoHide();
}
- }
+ };
_startAutoHide() {
- if(this._autoHideTimer) {
+ if (this._autoHideTimer) {
clearTimeout(this._autoHideTimer);
}
@@ -128,7 +133,7 @@ export default class CustomScrollbars extends React.Component<Props, State> {
});
}, AUTOHIDE_TIMEOUT);
- if(!this.state.showScrollIndicators) {
+ if (!this.state.showScrollIndicators) {
this.setState({
showScrollIndicators: true,
});
@@ -136,25 +141,25 @@ export default class CustomScrollbars extends React.Component<Props, State> {
}
_stopAutoHide() {
- if(this._autoHideTimer) {
+ if (this._autoHideTimer) {
clearTimeout(this._autoHideTimer);
this._autoHideTimer = null;
}
}
_computeScrollTop(scrollable: HTMLElement, child: HTMLElement, scrollPosition: ScrollPosition) {
- switch(scrollPosition) {
- case 'top':
- return child.offsetTop;
+ switch (scrollPosition) {
+ case 'top':
+ return child.offsetTop;
- case 'bottom':
- return child.offsetTop - (scrollable.offsetHeight - child.clientHeight);
+ case 'bottom':
+ return child.offsetTop - (scrollable.offsetHeight - child.clientHeight);
- case 'middle':
- return child.offsetTop - ((scrollable.offsetHeight - child.clientHeight) * 0.5);
+ case 'middle':
+ return child.offsetTop - (scrollable.offsetHeight - child.clientHeight) * 0.5;
- default:
- throw new Error(`Unknown enum type for ScrollPosition: ${ scrollPosition }`);
+ default:
+ throw new Error(`Unknown enum type for ScrollPosition: ${scrollPosition}`);
}
}
@@ -178,11 +183,11 @@ export default class CustomScrollbars extends React.Component<Props, State> {
// calculate the thumb boundary to make sure that the visual appearance of
// a thumb at lowest point matches the bottom of scrollable view
- const thumbBoundary = visibleHeight - thumbHeight - (this.props.thumbInset.y * 2);
+ const thumbBoundary = visibleHeight - thumbHeight - this.props.thumbInset.y * 2;
// calculate thumb position based on scroll progress and thumb boundary
// adding vertical inset to adjust the thumb's appearance
- const thumbPosition = (thumbBoundary * scrollPosition) + this.props.thumbInset.y;
+ const thumbPosition = thumbBoundary * scrollPosition + this.props.thumbInset.y;
return {
x: -this.props.thumbInset.x,
@@ -203,29 +208,33 @@ export default class CustomScrollbars extends React.Component<Props, State> {
_updateScrollbarsHelper(updateFlags: $Shape<ScrollbarUpdateContext>) {
const scrollable = this._scrollableElement;
const thumb = this._thumbElement;
- if(scrollable && thumb) {
+ if (scrollable && thumb) {
this._updateScrollbars(scrollable, thumb, updateFlags);
}
}
- _updateScrollbars(scrollable: HTMLElement, thumb: HTMLElement, context: $Shape<ScrollbarUpdateContext>) {
- if(context.size) {
+ _updateScrollbars(
+ scrollable: HTMLElement,
+ thumb: HTMLElement,
+ context: $Shape<ScrollbarUpdateContext>,
+ ) {
+ if (context.size) {
const thumbHeight = this._computeThumbHeight(scrollable);
thumb.style.setProperty('height', thumbHeight + 'px');
// hide thumb when there is nothing to scroll
- const canScroll = (thumbHeight < scrollable.offsetHeight);
- if(this.state.canScroll !== canScroll) {
+ const canScroll = thumbHeight < scrollable.offsetHeight;
+ if (this.state.canScroll !== canScroll) {
this.setState({ canScroll });
// flash the scroll indicators when the view becomes scrollable
- if(this.props.autoHide && canScroll) {
+ if (this.props.autoHide && canScroll) {
this._startAutoHide();
}
}
}
- if(context.position) {
+ if (context.position) {
const { x, y } = this._computeThumbPosition(scrollable, thumb);
thumb.style.setProperty('transform', `translate(${x}px, ${y}px)`);
}
diff --git a/app/components/HeaderBar.js b/app/components/HeaderBar.js
index 6f44ff7a00..4472b05dcc 100644
--- a/app/components/HeaderBar.js
+++ b/app/components/HeaderBar.js
@@ -1,11 +1,6 @@
// @flow
import React from 'react';
-import {
- Component,
- Text,
- Button,
- View
-} from 'reactxp';
+import { Component, Text, Button, View } from 'reactxp';
import Img from './Img';
@@ -14,10 +9,10 @@ import platformStyles from './HeaderBarPlatformStyles';
export type HeaderBarStyle = 'default' | 'defaultDark' | 'error' | 'success';
export type HeaderBarProps = {
- style: HeaderBarStyle;
- hidden: boolean;
- showSettings: boolean;
- onSettings: ?(() => void);
+ style: HeaderBarStyle,
+ hidden: boolean,
+ showSettings: boolean,
+ onSettings: ?() => void,
};
export default class HeaderBar extends Component {
@@ -26,34 +21,43 @@ export default class HeaderBar extends Component {
style: 'default',
hidden: false,
showSettings: false,
- onSettings: null
+ onSettings: null,
};
render() {
let containerClass = [
styles['headerbar'],
platformStyles[process.platform],
- styles['style_' + this.props.style]
+ styles['style_' + this.props.style],
];
- if(this.props.hidden) {
+ if (this.props.hidden) {
containerClass.push(styles['hidden']);
}
return (
- <View style={ containerClass }>
- {!this.props.hidden ?
+ <View style={containerClass}>
+ {!this.props.hidden ? (
<View style={styles.container} testName="headerbar__container">
- <Img height={50} width={50} source='logo-icon'/>
+ <Img height={50} width={50} source="logo-icon" />
<Text style={styles.title}>MULLVAD VPN</Text>
</View>
- : null}
+ ) : null}
- {this.props.showSettings ?
- <Button style={ styles.settings } onPress={ this.props.onSettings } testName="headerbar__settings">
- <Img height={24} width={24} source='icon-settings' style={[ styles.settings_icon, platformStyles.settings_icon ]} hoverStyle={ styles.settings_icon_hover }/>
+ {this.props.showSettings ? (
+ <Button
+ style={styles.settings}
+ onPress={this.props.onSettings}
+ testName="headerbar__settings">
+ <Img
+ height={24}
+ width={24}
+ source="icon-settings"
+ style={[styles.settings_icon, platformStyles.settings_icon]}
+ hoverStyle={styles.settings_icon_hover}
+ />
</Button>
- : null}
+ ) : null}
</View>
);
}
diff --git a/app/components/HeaderBarPlatformStyles.js b/app/components/HeaderBarPlatformStyles.js
index 241bdb1a60..c60967797a 100644
--- a/app/components/HeaderBarPlatformStyles.js
+++ b/app/components/HeaderBarPlatformStyles.js
@@ -12,5 +12,5 @@ export default {
settings_icon: {
WebkitAppRegion: 'no-drag',
},
- })
+ }),
};
diff --git a/app/components/HeaderBarStyles.js b/app/components/HeaderBarStyles.js
index c3e0e2ad5c..01b3c89f5c 100644
--- a/app/components/HeaderBarStyles.js
+++ b/app/components/HeaderBarStyles.js
@@ -35,7 +35,7 @@ export default {
alignItems: 'center',
},
settings: {
- padding: 0
+ padding: 0,
},
settings_icon: {
color: colors.white60,
@@ -53,6 +53,6 @@ export default {
letterSpacing: -0.5,
color: colors.white60,
marginLeft: 8,
- }
- })
+ },
+ }),
};
diff --git a/app/components/Img.android.js b/app/components/Img.android.js
index c1deb53bf7..229cb2c1b7 100644
--- a/app/components/Img.android.js
+++ b/app/components/Img.android.js
@@ -1,5 +1,5 @@
// @flow
-import React, { Component } from 'react';
+import React, { Component } from 'react';
import { StyleSheet } from 'react-native';
import { Image, Styles } from 'reactxp';
@@ -9,10 +9,10 @@ export default class Img extends Component {
style: Object,
tintColor?: string,
height?: number,
- width?:number,
+ width?: number,
};
- render(){
+ render() {
const width = this.props.width || 7;
const height = this.props.height || 12;
const source = this.props.source || 'icon-chevron';
@@ -20,12 +20,24 @@ export default class Img extends Component {
if (tintColor === 'currentColor' && this.props.style) {
const { color: tint, ...otherStyles } = StyleSheet.flatten(this.props.style);
- return(
- <Image style={Styles.createViewStyle({ ...otherStyles, tintColor: tint, height: height, width: width }, false)} source={ source }/>
+ return (
+ <Image
+ style={Styles.createViewStyle(
+ { ...otherStyles, tintColor: tint, height: height, width: width },
+ false,
+ )}
+ source={source}
+ />
);
} else {
- return(
- <Image style={Styles.createViewStyle({ ...this.props.style, height: height, width: width }, false)} source={ source }/>
+ return (
+ <Image
+ style={Styles.createViewStyle(
+ { ...this.props.style, height: height, width: width },
+ false,
+ )}
+ source={source}
+ />
);
}
}
diff --git a/app/components/Img.js b/app/components/Img.js
index d124eb7f49..fb74ac9fe6 100644
--- a/app/components/Img.js
+++ b/app/components/Img.js
@@ -3,22 +3,21 @@ import * as React from 'react';
import { View, Component, Types } from 'reactxp';
type ImgProps = {
- source: string,
- tintColor?: string,
- hoverStyle?: Types.ViewStyle,
- disabled?: boolean,
- };
+ source: string,
+ tintColor?: string,
+ hoverStyle?: Types.ViewStyle,
+ disabled?: boolean,
+};
type State = { hovered: boolean };
export default class Img extends Component<ImgProps, State> {
-
state = { hovered: false };
- onHoverStart = () => !this.props.disabled ? this.setState({ hovered: true }) : null;
- onHoverEnd = () => !this.props.disabled ? this.setState({ hovered: false }) : null;
+ onHoverStart = () => (!this.props.disabled ? this.setState({ hovered: true }) : null);
+ onHoverEnd = () => (!this.props.disabled ? this.setState({ hovered: false }) : null);
- getHoverStyle = () => this.state.hovered ? this.props.hoverStyle || null : null;
+ getHoverStyle = () => (this.state.hovered ? this.props.hoverStyle || null : null);
render() {
const { source, style, onMouseEnter, onMouseLeave, ...otherProps } = this.props;
@@ -26,31 +25,35 @@ export default class Img extends Component<ImgProps, State> {
const url = './assets/images/' + source + '.svg';
let image;
- if(tintColor) {
+ if (tintColor) {
image = (
- <div style={{
- WebkitMaskImage: `url('${url}')`,
- WebkitMaskRepeat: 'no-repeat',
- backgroundColor: tintColor,
- lineHeight: 0,
- }}>
- <img src={ url } style={{
- visibility: 'hidden',
- }} />
+ <div
+ style={{
+ WebkitMaskImage: `url('${url}')`,
+ WebkitMaskRepeat: 'no-repeat',
+ backgroundColor: tintColor,
+ lineHeight: 0,
+ }}>
+ <img
+ src={url}
+ style={{
+ visibility: 'hidden',
+ }}
+ />
</div>
);
} else {
- image = (
- <img src={ url } />
- );
+ image = <img src={url} />;
}
return (
- <View { ...otherProps }
+ <View
+ {...otherProps}
onMouseEnter={onMouseEnter || this.onHoverStart}
onMouseLeave={onMouseLeave || this.onHoverEnd}
style={[style, this.getHoverStyle()]}>
- { image }
- </View>);
+ {image}
+ </View>
+ );
}
}
diff --git a/app/components/Layout.js b/app/components/Layout.js
index dea641919c..23d8e7c20c 100644
--- a/app/components/Layout.js
+++ b/app/components/Layout.js
@@ -14,7 +14,7 @@ export class Header extends Component {
render() {
return (
<View style={styles.header}>
- <HeaderBar { ...this.props } />
+ <HeaderBar {...this.props} />
</View>
);
}
@@ -22,28 +22,20 @@ export class Header extends Component {
export class Container extends Component {
props: {
- children: React.Node
- }
+ children: React.Node,
+ };
render() {
- return (
- <View style={styles.container}>
- { this.props.children }
- </View>
- );
+ return <View style={styles.container}>{this.props.children}</View>;
}
}
export class Layout extends Component {
props: {
- children: Array<React.Node> | React.Node
- }
+ children: Array<React.Node> | React.Node,
+ };
render() {
- return (
- <View style={styles.layout}>
- { this.props.children }
- </View>
- );
+ return <View style={styles.layout}>{this.props.children}</View>;
}
}
diff --git a/app/components/LayoutStyles.js b/app/components/LayoutStyles.js
index ab32d45e7b..b3ef4f462e 100644
--- a/app/components/LayoutStyles.js
+++ b/app/components/LayoutStyles.js
@@ -15,6 +15,6 @@ export default {
flex: 1,
backgroundColor: colors.blue,
overflow: 'hidden',
- }
+ },
}),
};
diff --git a/app/components/Login.js b/app/components/Login.js
index b711f089b5..3100cc54f0 100644
--- a/app/components/Login.js
+++ b/app/components/Login.js
@@ -16,7 +16,7 @@ import type { AccountToken } from '../lib/ipc-facade';
export type LoginPropTypes = {
account: AccountReduxState,
onLogin: (accountToken: AccountToken) => void,
- onSettings: ?(() => void),
+ onSettings: ?() => void,
onFirstChangeAfterFailure: () => void,
onExternalLink: (type: string) => void,
onAccountTokenChange: (accountToken: AccountToken) => void,
@@ -48,14 +48,18 @@ export default class Login extends Component<LoginPropTypes, State> {
constructor(props: LoginPropTypes) {
super(props);
- if(props.account.status === 'failed') {
+ if (props.account.status === 'failed') {
this.state.notifyOnFirstChangeAfterFailure = true;
}
this.state.footerAnimationStyle = Styles.createAnimatedViewStyle({
- transform: [{translateY: this.state.animatedFooterValue }]
+ transform: [{ translateY: this.state.animatedFooterValue }],
});
this.state.loginButtonAnimationStyle = Styles.createAnimatedViewStyle({
- backgroundColor: Animated.interpolate(this.state.animatedLoginButtonValue, [0.0, 1.0], [colors.white, colors.green]),
+ backgroundColor: Animated.interpolate(
+ this.state.animatedLoginButtonValue,
+ [0.0, 1.0],
+ [colors.white, colors.green],
+ ),
});
}
@@ -63,7 +67,7 @@ export default class Login extends Component<LoginPropTypes, State> {
const prev = this.props.account || {};
const next = nextProps.account || {};
- if(prev.status !== next.status && next.status === 'failed') {
+ if (prev.status !== next.status && next.status === 'failed') {
this.setState({ notifyOnFirstChangeAfterFailure: true });
}
@@ -73,36 +77,38 @@ export default class Login extends Component<LoginPropTypes, State> {
render() {
return (
<Layout>
- <Header showSettings={ true } onSettings={ this.props.onSettings } />
+ <Header showSettings={true} onSettings={this.props.onSettings} />
<Container>
<View style={styles.login_form}>
- { this._getStatusIcon() }
- <Text style={styles.title}>{ this._formTitle() }</Text>
+ {this._getStatusIcon()}
+ <Text style={styles.title}>{this._formTitle()}</Text>
- {this._shouldShowLoginForm() && <View>
- { this._createLoginForm() }
- </View>}
+ {this._shouldShowLoginForm() && <View>{this._createLoginForm()}</View>}
</View>
- <Animated.View onLayout={this._onFooterLayout} style={[styles.login_footer, this.state.footerAnimationStyle]} testName={'footerVisibility ' + this._shouldShowFooter(this.props).toString()}>
- { this._createFooter() }
+ <Animated.View
+ onLayout={this._onFooterLayout}
+ style={[styles.login_footer, this.state.footerAnimationStyle]}
+ testName={'footerVisibility ' + this._shouldShowFooter(this.props).toString()}>
+ {this._createFooter()}
</Animated.View>
</Container>
</Layout>
);
}
- _onCreateAccount = () => this.props.onExternalLink('createAccount')
+ _onCreateAccount = () => this.props.onExternalLink('createAccount');
- _onFocus = () => this.setState({ isActive: true }, () => {
- this._animate(this.props);
- })
+ _onFocus = () =>
+ this.setState({ isActive: true }, () => {
+ this._animate(this.props);
+ });
_onBlur = (e) => {
const relatedTarget = e.relatedTarget;
// restore focus if click happened within dropdown
- if(relatedTarget) {
+ if (relatedTarget) {
e.target.focus();
return;
}
@@ -110,7 +116,7 @@ export default class Login extends Component<LoginPropTypes, State> {
this.setState({ isActive: false }, () => {
this._animate(this.props);
});
- }
+ };
_animate = (props: LoginPropTypes) => {
if (this.state.animation) {
@@ -119,95 +125,103 @@ export default class Login extends Component<LoginPropTypes, State> {
const accountToken = props.account.accountToken || [];
const footerPosition = this._shouldShowFooter(props) ? 0 : this.state.footerHeight;
- const loginButtonValue = (accountToken.length) > 0 ? 1 : 0;
- this._setAnimation(this._getFooterAnimation(footerPosition), this._getLoginButtonAnimation(loginButtonValue));
- }
+ const loginButtonValue = accountToken.length > 0 ? 1 : 0;
+ this._setAnimation(
+ this._getFooterAnimation(footerPosition),
+ this._getLoginButtonAnimation(loginButtonValue),
+ );
+ };
- _setAnimation = (footerAnimation: Animated.CompositeAnimation, loginButtonAnimation: Animated.CompositeAnimation) => {
- let compositeAnimation = Animated.parallel([ footerAnimation, loginButtonAnimation]);
- this.setState({animation: compositeAnimation}, () => {
- compositeAnimation.start(() => this.setState({
- animation: null
- }));
+ _setAnimation = (
+ footerAnimation: Animated.CompositeAnimation,
+ loginButtonAnimation: Animated.CompositeAnimation,
+ ) => {
+ let compositeAnimation = Animated.parallel([footerAnimation, loginButtonAnimation]);
+ this.setState({ animation: compositeAnimation }, () => {
+ compositeAnimation.start(() =>
+ this.setState({
+ animation: null,
+ }),
+ );
});
- }
+ };
_onLogin = () => {
const accountToken = this.props.account.accountToken;
- if(accountToken && accountToken.length > 0) {
+ if (accountToken && accountToken.length > 0) {
this.props.onLogin(accountToken);
}
- }
+ };
_onInputChange = (value: string) => {
// notify delegate on first change after login failure
- if(this.state.notifyOnFirstChangeAfterFailure) {
+ if (this.state.notifyOnFirstChangeAfterFailure) {
this.setState({ notifyOnFirstChangeAfterFailure: false });
this.props.onFirstChangeAfterFailure();
}
this.props.onAccountTokenChange(value);
- }
+ };
_formTitle() {
- switch(this.props.account.status) {
- case 'logging in':
- return 'Logging in...';
- case 'failed':
- return 'Login failed';
- case 'ok':
- return 'Login successful';
- default:
- return 'Login';
+ switch (this.props.account.status) {
+ case 'logging in':
+ return 'Logging in...';
+ case 'failed':
+ return 'Login failed';
+ case 'ok':
+ return 'Login successful';
+ default:
+ return 'Login';
}
}
_formSubtitle() {
const { status, error } = this.props.account;
- switch(status) {
- case 'failed':
- return (error && error.message) || 'Unknown error';
- case 'logging in':
- return 'Checking account number';
- default:
- return 'Enter your account number';
+ switch (status) {
+ case 'failed':
+ return (error && error.message) || 'Unknown error';
+ case 'logging in':
+ return 'Checking account number';
+ default:
+ return 'Enter your account number';
}
}
_getStatusIcon() {
const statusIconPath = this._getStatusIconPath();
- return <View style={ styles.status_icon}>
- { statusIconPath ?
- <Img source={ statusIconPath } height={48} width={48} alt="" /> :
- null }
- </View>;
+ return (
+ <View style={styles.status_icon}>
+ {statusIconPath ? <Img source={statusIconPath} height={48} width={48} alt="" /> : null}
+ </View>
+ );
}
_getStatusIconPath(): ?string {
- switch(this.props.account.status) {
- case 'logging in':
- return 'icon-spinner';
- case 'failed':
- return 'icon-fail';
- case 'ok':
- return 'icon-success';
- default:
- return undefined;
+ switch (this.props.account.status) {
+ case 'logging in':
+ return 'icon-spinner';
+ case 'failed':
+ return 'icon-fail';
+ case 'ok':
+ return 'icon-success';
+ default:
+ return undefined;
}
}
_accountInputGroupStyles(): Array<Object> {
const classes = [styles.account_input_group];
- if(this.state.isActive) {
+ if (this.state.isActive) {
classes.push(styles.account_input_group__active);
}
- switch(this.props.account.status) {
- case 'logging in':
- classes.push(styles.account_input_group__inactive);
- break;
- case 'failed':
- classes.push(styles.account_input_group__error);
- break;
+ switch (this.props.account.status) {
+ case 'logging in':
+ classes.push(styles.account_input_group__inactive);
+ break;
+ case 'failed':
+ classes.push(styles.account_input_group__error);
+ break;
}
return classes;
@@ -217,7 +231,7 @@ export default class Login extends Component<LoginPropTypes, State> {
const { status } = this.props.account;
const classes = [styles.input_button];
- if(status === 'logging in') {
+ if (status === 'logging in') {
classes.push(styles.input_button__invisible);
}
@@ -230,11 +244,11 @@ export default class Login extends Component<LoginPropTypes, State> {
const { accountToken, status } = this.props.account;
const classes = [styles.input_arrow];
- if(accountToken && accountToken.length > 0) {
+ if (accountToken && accountToken.length > 0) {
classes.push(styles.input_arrow__active);
}
- if(status === 'logging in') {
+ if (status === 'logging in') {
classes.push(styles.input_arrow__invisible);
}
@@ -247,9 +261,11 @@ export default class Login extends Component<LoginPropTypes, State> {
}
_shouldShowAccountHistory(props: LoginPropTypes) {
- return this._shouldEnableAccountInput(props) &&
+ return (
+ this._shouldEnableAccountInput(props) &&
this.state.isActive &&
- props.account.accountHistory.length > 0;
+ props.account.accountHistory.length > 0
+ );
}
_shouldShowLoginForm() {
@@ -261,7 +277,7 @@ export default class Login extends Component<LoginPropTypes, State> {
return (status === 'none' || status === 'failed') && !this._shouldShowAccountHistory(props);
}
- _getFooterAnimation(toValue: number){
+ _getFooterAnimation(toValue: number) {
return Animated.timing(this.state.animatedFooterValue, {
toValue: toValue,
easing: Animated.Easing.InOut(),
@@ -271,10 +287,10 @@ export default class Login extends Component<LoginPropTypes, State> {
}
_onFooterLayout = (layout) => {
- this.setState({footerHeight: layout.height});
- }
+ this.setState({ footerHeight: layout.height });
+ };
- _getLoginButtonAnimation(toValue: number){
+ _getLoginButtonAnimation(toValue: number) {
return Animated.timing(this.state.animatedLoginButtonValue, {
toValue: toValue,
easing: Animated.Easing.Linear(),
@@ -286,7 +302,7 @@ export default class Login extends Component<LoginPropTypes, State> {
_onSelectAccountFromHistory = (accountToken) => {
this.props.onAccountTokenChange(accountToken);
this.props.onLogin(accountToken);
- }
+ };
_createLoginForm() {
const { accountHistory, accountToken } = this.props.account;
@@ -295,50 +311,68 @@ export default class Login extends Component<LoginPropTypes, State> {
// do not refactor this into instance method,
// it has to be new function each time to be called on each render
const autoFocusOnFailure = (input) => {
- if(this.props.account.status === 'failed' && input) {
+ if (this.props.account.status === 'failed' && input) {
input.focus();
}
};
- return <View>
- <Text style={ styles.subtitle }>{ this._formSubtitle() }</Text>
- <View style={ this._accountInputGroupStyles() }>
- <View style={ styles.account_input_backdrop}>
- <AccountInput style={styles.account_input_textfield}
- type="text"
- placeholder="0000 0000 0000 0000"
- placeholderTextColor={colors.blue40}
- onFocus={ this._onFocus }
- onBlur={ this._onBlur }
- onChange={ this._onInputChange }
- onEnter={ this._onLogin }
- value={ accountToken || '' }
- disabled={ !this._shouldEnableAccountInput(this.props) }
- autoFocus={ true }
- ref={ autoFocusOnFailure }
- testName='AccountInput'/>
- <Animated.View style={this._accountInputButtonStyles()} onPress={ this._onLogin } testName='account-input-button'>
- <Img style={this._accountInputArrowStyles()} source='icon-arrow' height={16} width={24} tintColor='currentColor' />
- </Animated.View>
+ return (
+ <View>
+ <Text style={styles.subtitle}>{this._formSubtitle()}</Text>
+ <View style={this._accountInputGroupStyles()}>
+ <View style={styles.account_input_backdrop}>
+ <AccountInput
+ style={styles.account_input_textfield}
+ type="text"
+ placeholder="0000 0000 0000 0000"
+ placeholderTextColor={colors.blue40}
+ onFocus={this._onFocus}
+ onBlur={this._onBlur}
+ onChange={this._onInputChange}
+ onEnter={this._onLogin}
+ value={accountToken || ''}
+ disabled={!this._shouldEnableAccountInput(this.props)}
+ autoFocus={true}
+ ref={autoFocusOnFailure}
+ testName="AccountInput"
+ />
+ <Animated.View
+ style={this._accountInputButtonStyles()}
+ onPress={this._onLogin}
+ testName="account-input-button">
+ <Img
+ style={this._accountInputArrowStyles()}
+ source="icon-arrow"
+ height={16}
+ width={24}
+ tintColor="currentColor"
+ />
+ </Animated.View>
+ </View>
+ <Accordion height={this._shouldShowAccountHistory(this.props) ? 'auto' : 0}>
+ {
+ <AccountDropdown
+ items={accountHistory.slice().reverse()}
+ onSelect={this._onSelectAccountFromHistory}
+ onRemove={this.props.onRemoveAccountTokenFromHistory}
+ />
+ }
+ </Accordion>
</View>
- <Accordion height={ this._shouldShowAccountHistory(this.props) ? 'auto' : 0 }>
- { <AccountDropdown
- items={ accountHistory.slice().reverse() }
- onSelect={ this._onSelectAccountFromHistory }
- onRemove={ this.props.onRemoveAccountTokenFromHistory } /> }
- </Accordion>
</View>
- </View>;
+ );
}
_createFooter() {
- return <View>
- <Text style={ styles.login_footer__prompt}>{ 'Don\'t have an account number?' }</Text>
- <BlueButton onPress={ this._onCreateAccount }>
- <Label>Create account</Label>
- <Img source='icon-extLink' height={16} width={16} />
- </BlueButton>
- </View>;
+ return (
+ <View>
+ <Text style={styles.login_footer__prompt}>{"Don't have an account number?"}</Text>
+ <BlueButton onPress={this._onCreateAccount}>
+ <Label>Create account</Label>
+ <Img source="icon-extLink" height={16} width={16} />
+ </BlueButton>
+ </View>
+ );
}
}
@@ -353,13 +387,15 @@ class AccountDropdown extends React.Component<AccountDropdownProps> {
const uniqueItems = [...new Set(this.props.items)];
return (
<View>
- { uniqueItems.map(token => (
- <AccountDropdownItem key={ token }
- value={ token }
- label={ formatAccount(token) }
- onSelect={ this.props.onSelect }
- onRemove={ this.props.onRemove } />
- )) }
+ {uniqueItems.map((token) => (
+ <AccountDropdownItem
+ key={token}
+ value={token}
+ label={formatAccount(token)}
+ onSelect={this.props.onSelect}
+ onRemove={this.props.onRemove}
+ />
+ ))}
</View>
);
}
@@ -374,19 +410,29 @@ type AccountDropdownItemProps = {
class AccountDropdownItem extends React.Component<AccountDropdownItemProps> {
render() {
- return (<View>
- <View style={ styles.account_dropdown__spacer }/>
- <CellButton style={ styles.account_dropdown__item } cellHoverStyle={ styles.account_dropdown__item_hover }>
- <Label style={styles.account_dropdown__label} cellHoverStyle={ styles.account_dropdown__label_hover } onPress={ () => this.props.onSelect(this.props.value) }>
- { this.props.label }
- </Label>
- <Img style={styles.account_dropdown__remove}
- cellHoverStyle={ styles.account_dropdown__remove_cell_hover }
- hoverStyle={ styles.account_dropdown__remove_hover }
- source='icon-close-sml'
- height={16} width={16}
- onPress={ () => this.props.onRemove(this.props.value) }/>
- </CellButton>
- </View>);
+ return (
+ <View>
+ <View style={styles.account_dropdown__spacer} />
+ <CellButton
+ style={styles.account_dropdown__item}
+ cellHoverStyle={styles.account_dropdown__item_hover}>
+ <Label
+ style={styles.account_dropdown__label}
+ cellHoverStyle={styles.account_dropdown__label_hover}
+ onPress={() => this.props.onSelect(this.props.value)}>
+ {this.props.label}
+ </Label>
+ <Img
+ style={styles.account_dropdown__remove}
+ cellHoverStyle={styles.account_dropdown__remove_cell_hover}
+ hoverStyle={styles.account_dropdown__remove_hover}
+ source="icon-close-sml"
+ height={16}
+ width={16}
+ onPress={() => this.props.onRemove(this.props.value)}
+ />
+ </CellButton>
+ </View>
+ );
}
}
diff --git a/app/components/LoginStyles.js b/app/components/LoginStyles.js
index 21c3aa4429..5e64e8b1eb 100644
--- a/app/components/LoginStyles.js
+++ b/app/components/LoginStyles.js
@@ -7,7 +7,7 @@ export default {
login_footer: {
backgroundColor: colors.darkBlue,
paddingTop: 18,
- paddingBottom:16,
+ paddingBottom: 16,
flex: 0,
},
status_icon: {
@@ -16,18 +16,18 @@ export default {
marginBottom: 30,
justifyContent: 'center',
},
- login_form:{
- flex:1,
+ login_form: {
+ flex: 1,
flexDirection: 'column',
- overflow:'visible',
+ overflow: 'visible',
paddingTop: 0,
paddingBottom: 0,
paddingLeft: 24,
paddingRight: 24,
marginTop: 83,
- marginBottom:0,
+ marginBottom: 0,
marginRight: 0,
- marginLeft:0,
+ marginLeft: 0,
},
account_input_group: {
borderWidth: 2,
@@ -131,7 +131,7 @@ export default {
letterSpacing: -0.7,
color: colors.white,
marginBottom: 7,
- flex:0,
+ flex: 0,
},
subtitle: {
fontFamily: 'Open Sans',
diff --git a/app/components/Map.js b/app/components/Map.js
index 3865e8975a..72298fd2ee 100644
--- a/app/components/Map.js
+++ b/app/components/Map.js
@@ -17,8 +17,8 @@ export type MapProps = {
type MapState = {
bounds: {
width: number,
- height: number
- }
+ height: number,
+ },
};
export default class Map extends Component<MapProps, MapState> {
@@ -31,18 +31,20 @@ export default class Map extends Component<MapProps, MapState> {
render() {
const { width, height } = this.state.bounds;
- const readyToRenderTheMap = (width > 0 && height > 0);
+ const readyToRenderTheMap = width > 0 && height > 0;
return (
- <View style={ this.props.style } onLayout={ this._onLayout }>
- { readyToRenderTheMap && (
- <SvgMap width={ width }
- height={ height }
- center={ this.props.center }
- offset={ this.props.offset }
- zoomLevel={ this._zoomLevel(this.props.zoomLevel) }
- showMarker={ this.props.showMarker }
- markerImagePath={ this._markerImage(this.props.markerStyle) } />
- ) }
+ <View style={this.props.style} onLayout={this._onLayout}>
+ {readyToRenderTheMap && (
+ <SvgMap
+ width={width}
+ height={height}
+ center={this.props.center}
+ offset={this.props.offset}
+ zoomLevel={this._zoomLevel(this.props.zoomLevel)}
+ showMarker={this.props.showMarker}
+ markerImagePath={this._markerImage(this.props.markerStyle)}
+ />
+ )}
</View>
);
}
@@ -53,14 +55,11 @@ export default class Map extends Component<MapProps, MapState> {
return (
oldProps.center[0] !== nextProps.center[0] ||
oldProps.center[1] !== nextProps.center[1] ||
-
oldProps.offset[0] !== nextProps.offset[0] ||
oldProps.offset[1] !== nextProps.offset[1] ||
-
oldProps.zoomLevel !== nextProps.zoomLevel ||
oldProps.showMarker !== nextProps.showMarker ||
oldProps.markerStyle !== nextProps.markerStyle ||
-
oldState.bounds.width !== nextState.bounds.width ||
oldState.bounds.height !== nextState.bounds.height
);
@@ -71,30 +70,32 @@ export default class Map extends Component<MapProps, MapState> {
bounds: {
width: layoutInfo.width,
height: layoutInfo.height,
- }
+ },
});
- }
+ };
// TODO: Remove zoom level in favor of center + coordinate span
_zoomLevel(variant: $PropertyType<MapProps, 'zoomLevel'>) {
- switch(variant) {
- case 'high': return 1;
- case 'medium': return 20;
- case 'low': return 40;
- default:
- throw new Error(`Invalid enumeration type: ${variant}`);
+ switch (variant) {
+ case 'high':
+ return 1;
+ case 'medium':
+ return 20;
+ case 'low':
+ return 40;
+ default:
+ throw new Error(`Invalid enumeration type: ${variant}`);
}
}
_markerImage(style: $PropertyType<MapProps, 'markerStyle'>) {
- switch(style) {
- case 'secure':
- return './assets/images/location-marker-secure.svg';
- case 'unsecure':
- return './assets/images/location-marker-unsecure.svg';
- default:
- throw new Error(`Invalid enumeration type: ${style}`);
+ switch (style) {
+ case 'secure':
+ return './assets/images/location-marker-secure.svg';
+ case 'unsecure':
+ return './assets/images/location-marker-unsecure.svg';
+ default:
+ throw new Error(`Invalid enumeration type: ${style}`);
}
}
-
}
diff --git a/app/components/PlatformWindow.android.js b/app/components/PlatformWindow.android.js
index b2a13e86c9..9d15466f56 100644
--- a/app/components/PlatformWindow.android.js
+++ b/app/components/PlatformWindow.android.js
@@ -4,14 +4,10 @@ import { KeyboardAvoidingView } from 'react-native';
export default class PlatformWindow extends React.Component {
props: {
- children: Array<React.Node> | React.Node
+ children: Array<React.Node> | React.Node,
};
render() {
- return (
- <KeyboardAvoidingView behavior={'position'}>
- { this.props.children }
- </KeyboardAvoidingView>
- );
+ return <KeyboardAvoidingView behavior={'position'}>{this.props.children}</KeyboardAvoidingView>;
}
-} \ No newline at end of file
+}
diff --git a/app/components/PlatformWindow.js b/app/components/PlatformWindow.js
index b727cdd7b1..60f26dd6de 100644
--- a/app/components/PlatformWindow.js
+++ b/app/components/PlatformWindow.js
@@ -2,16 +2,12 @@
import * as React from 'react';
type Props = {
- children?: React.Node
+ children?: React.Node,
};
export default class PlatformWindow extends React.Component<Props> {
render() {
const chromeClass = ['window-chrome', 'window-chrome--' + process.platform];
- return (
- <div className={ chromeClass.join(' ') }>
- { this.props.children }
- </div>
- );
+ return <div className={chromeClass.join(' ')}>{this.props.children}</div>;
}
-} \ No newline at end of file
+}
diff --git a/app/components/Preferences.js b/app/components/Preferences.js
index d24d99c042..afe802d958 100644
--- a/app/components/Preferences.js
+++ b/app/components/Preferences.js
@@ -7,9 +7,9 @@ import Switch from './Switch';
import styles from './PreferencesStyles';
export type PreferencesProps = {
- allowLan: boolean;
- onChangeAllowLan: (boolean) => void;
- onClose: () => void;
+ allowLan: boolean,
+ onChangeAllowLan: (boolean) => void,
+ onClose: () => void,
};
export default class Preferences extends Component {
@@ -18,33 +18,37 @@ export default class Preferences extends Component {
render() {
return (
<Layout>
- <Header hidden={ true } style={ 'defaultDark' } />
+ <Header hidden={true} style={'defaultDark'} />
<Container>
- <View style={ styles.preferences }>
- <Button style={ styles.preferences__close } onPress={ this.props.onClose } testName='closeButton'>
- <View style={ styles.preferences__close_content }>
- <Img style={ styles.preferences__close_icon } source="icon-back" />
- <Text style={ styles.preferences__close_title }>Settings</Text>
+ <View style={styles.preferences}>
+ <Button
+ style={styles.preferences__close}
+ onPress={this.props.onClose}
+ testName="closeButton">
+ <View style={styles.preferences__close_content}>
+ <Img style={styles.preferences__close_icon} source="icon-back" />
+ <Text style={styles.preferences__close_title}>Settings</Text>
</View>
</Button>
- <View style={ styles.preferences__container }>
-
- <View style={ styles.preferences__header }>
- <Text style={ styles.preferences__title }>Preferences</Text>
+ <View style={styles.preferences__container}>
+ <View style={styles.preferences__header}>
+ <Text style={styles.preferences__title}>Preferences</Text>
</View>
- <View style={ styles.preferences__content }>
- <View style={ styles.preferences__cell }>
- <View style={ styles.preferences__cell_label_container }>
- <Text style={ styles.preferences__cell_label }>Local network sharing</Text>
+ <View style={styles.preferences__content}>
+ <View style={styles.preferences__cell}>
+ <View style={styles.preferences__cell_label_container}>
+ <Text style={styles.preferences__cell_label}>Local network sharing</Text>
</View>
- <View style={ styles.preferences__cell_accessory }>
- <Switch isOn={ this.props.allowLan } onChange={ this.props.onChangeAllowLan } />
+ <View style={styles.preferences__cell_accessory}>
+ <Switch isOn={this.props.allowLan} onChange={this.props.onChangeAllowLan} />
</View>
</View>
- <View style={ styles.preferences__cell_footer }>
- <Text style={ styles.preferences__cell_footer_label }>
- { 'Allows access to other devices on the same network for sharing, printing etc.' }
+ <View style={styles.preferences__cell_footer}>
+ <Text style={styles.preferences__cell_footer_label}>
+ {
+ 'Allows access to other devices on the same network for sharing, printing etc.'
+ }
</Text>
</View>
</View>
diff --git a/app/components/PreferencesStyles.js b/app/components/PreferencesStyles.js
index f751653622..c2d41c4ecb 100644
--- a/app/components/PreferencesStyles.js
+++ b/app/components/PreferencesStyles.js
@@ -29,7 +29,7 @@ export default {
borderWidth: 0,
padding: 0,
margin: 0,
- zIndex: 1, /* part of .preferences__container covers the button */
+ zIndex: 1 /* part of .preferences__container covers the button */,
cursor: 'default',
},
preferences__close_content: {
@@ -80,7 +80,7 @@ export default {
fontSize: 32,
fontWeight: '900',
lineHeight: 40,
- color: colors.white
+ color: colors.white,
},
preferences__cell_label: {
fontFamily: 'DINPro',
@@ -96,7 +96,7 @@ export default {
fontWeight: '600',
lineHeight: 20,
letterSpacing: -0.2,
- color: colors.white80
- }
- })
-}; \ No newline at end of file
+ color: colors.white80,
+ },
+ }),
+};
diff --git a/app/components/SelectLocation.js b/app/components/SelectLocation.js
index 5a0b8c1101..d706e7fcc2 100644
--- a/app/components/SelectLocation.js
+++ b/app/components/SelectLocation.js
@@ -9,17 +9,21 @@ import Img from './Img';
import Accordion from './Accordion';
-import type { SettingsReduxState, RelayLocationRedux, RelayLocationCityRedux } from '../redux/settings/reducers';
+import type {
+ SettingsReduxState,
+ RelayLocationRedux,
+ RelayLocationCityRedux,
+} from '../redux/settings/reducers';
import type { RelayLocation } from '../lib/ipc-facade';
export type SelectLocationProps = {
settings: SettingsReduxState,
- onClose: () => void;
- onSelect: (location: RelayLocation) => void;
+ onClose: () => void,
+ onSelect: (location: RelayLocation) => void,
};
type State = {
- expanded: Array<string>
+ expanded: Array<string>,
};
export default class SelectLocation extends React.Component<SelectLocationProps, State> {
@@ -35,13 +39,13 @@ export default class SelectLocation extends React.Component<SelectLocationProps,
// set initially expanded country based on relaySettings
const relaySettings = this.props.settings.relaySettings;
- if(relaySettings.normal) {
+ if (relaySettings.normal) {
const { location } = relaySettings.normal;
- if(location === 'any') {
+ if (location === 'any') {
// no-op
- } else if(location.country) {
+ } else if (location.country) {
this.state.expanded.push(location.country);
- } else if(location.city) {
+ } else if (location.city) {
this.state.expanded.push(location.city[0]);
}
}
@@ -52,7 +56,7 @@ export default class SelectLocation extends React.Component<SelectLocationProps,
const cell = this._selectedCell;
const scrollView = this._scrollView;
- if(scrollView && cell) {
+ if (scrollView && cell) {
//TODO: fix this when repairing the auto-scroll in customscrollbars.
//scrollView.scrollToElement(cell, 'middle');
}
@@ -63,24 +67,24 @@ export default class SelectLocation extends React.Component<SelectLocationProps,
<Layout>
<Container>
<View style={styles.select_location}>
- <Button style={styles.close} onPress={ this.props.onClose } testName='close'>
- <Img style={styles.close_icon} source='icon-close'/>
+ <Button style={styles.close} onPress={this.props.onClose} testName="close">
+ <Img style={styles.close_icon} source="icon-close" />
</Button>
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.title}>Select location</Text>
</View>
- <CustomScrollbars autoHide={ true } ref={ (ref) => this._scrollView = ref }>
+ <CustomScrollbars autoHide={true} ref={(ref) => (this._scrollView = ref)}>
<View>
<Text style={styles.subtitle}>
- While connected, your real location is masked with a private and secure location in the selected region
+ While connected, your real location is masked with a private and secure location
+ in the selected region
</Text>
- { this.props.settings.relayLocations.map((relayCountry) => {
+ {this.props.settings.relayLocations.map((relayCountry) => {
return this._renderCountry(relayCountry);
- }) }
-
+ })}
</View>
</CustomScrollbars>
</View>
@@ -92,20 +96,25 @@ export default class SelectLocation extends React.Component<SelectLocationProps,
_isSelected(selectedLocation: RelayLocation) {
const { relaySettings } = this.props.settings;
- if(relaySettings.normal) {
+ if (relaySettings.normal) {
const otherLocation = relaySettings.normal.location;
- if(selectedLocation.country && otherLocation.country &&
- selectedLocation.country === otherLocation.country) {
+ if (
+ selectedLocation.country &&
+ otherLocation.country &&
+ selectedLocation.country === otherLocation.country
+ ) {
return true;
}
- if(Array.isArray(selectedLocation.city) && Array.isArray(otherLocation.city)) {
+ if (Array.isArray(selectedLocation.city) && Array.isArray(otherLocation.city)) {
const selectedCity = selectedLocation.city;
const otherCity = otherLocation.city;
- return selectedCity.length === otherCity.length &&
- selectedCity.every((v, i) => v === otherCity[i]);
+ return (
+ selectedCity.length === otherCity.length &&
+ selectedCity.every((v, i) => v === otherCity[i])
+ );
}
}
return false;
@@ -115,21 +124,23 @@ export default class SelectLocation extends React.Component<SelectLocationProps,
this.setState((state) => {
const expanded = state.expanded.slice();
const index = expanded.indexOf(countryCode);
- if(index === -1) {
+ if (index === -1) {
expanded.push(countryCode);
} else {
expanded.splice(index, 1);
}
return { expanded };
});
- }
+ };
_relayStatusIndicator(active: boolean, isSelected: boolean) {
const statusClass = active ? styles.relay_status__active : styles.relay_status__inactive;
- return ( isSelected ?
- <Img style={ styles.tick_icon } source='icon-tick' height={24} width={24} /> :
- <View style={[ styles.relay_status, statusClass ]}></View>);
+ return isSelected ? (
+ <Img style={styles.tick_icon} source="icon-tick" height={24} width={24} />
+ ) : (
+ <View style={[styles.relay_status, statusClass]} />
+ );
}
_renderCountry(relayCountry: RelayLocationRedux) {
@@ -138,9 +149,12 @@ export default class SelectLocation extends React.Component<SelectLocationProps,
// either expanded by user or when the city selected within the country
const isExpanded = this.state.expanded.includes(relayCountry.code);
- const handleSelect = (relayCountry.hasActiveRelays && !isSelected) ? () => {
- this.props.onSelect({ country: relayCountry.code });
- } : undefined;
+ const handleSelect =
+ relayCountry.hasActiveRelays && !isSelected
+ ? () => {
+ this.props.onSelect({ country: relayCountry.code });
+ }
+ : undefined;
const handleCollapse = (e) => {
this._toggleCollapse(relayCountry.code);
@@ -148,35 +162,34 @@ export default class SelectLocation extends React.Component<SelectLocationProps,
};
return (
- <View key={ relayCountry.code } style={styles.country}>
+ <View key={relayCountry.code} style={styles.country}>
<CellButton
- cellHoverStyle={ isSelected ? styles.cell_selected : null }
- style={ isSelected ? styles.cell_selected : styles.cell }
- onPress={ handleSelect }
+ cellHoverStyle={isSelected ? styles.cell_selected : null}
+ style={isSelected ? styles.cell_selected : styles.cell}
+ onPress={handleSelect}
disabled={!relayCountry.hasActiveRelays}
- testName='country'>
+ testName="country">
+ {this._relayStatusIndicator(relayCountry.hasActiveRelays, isSelected)}
- { this._relayStatusIndicator(relayCountry.hasActiveRelays, isSelected) }
+ <Label>{relayCountry.name}</Label>
- <Label>
- { relayCountry.name }
- </Label>
-
- { relayCountry.cities.length > 1 ?
- <Img style={styles.collapse_button}
+ {relayCountry.cities.length > 1 ? (
+ <Img
+ style={styles.collapse_button}
hoverStyle={styles.expand_chevron_hover}
- onPress={ handleCollapse }
+ onPress={handleCollapse}
source={isExpanded ? 'icon-chevron-up' : 'icon-chevron-down'}
height={24}
- width={24} />
- : null }
+ width={24}
+ />
+ ) : null}
</CellButton>
- { relayCountry.cities.length > 1 &&
- (<Accordion height={ isExpanded ? 'auto' : 0 }>
- { relayCountry.cities.map((relayCity) => this._renderCity(relayCountry.code, relayCity)) }
- </Accordion>)
- }
+ {relayCountry.cities.length > 1 && (
+ <Accordion height={isExpanded ? 'auto' : 0}>
+ {relayCountry.cities.map((relayCity) => this._renderCity(relayCountry.code, relayCity))}
+ </Accordion>
+ )}
</View>
);
}
@@ -186,28 +199,31 @@ export default class SelectLocation extends React.Component<SelectLocationProps,
const isSelected = this._isSelected(relayLocation);
- const onRef = isSelected ? (element) => {
- this._selectedCell = element;
- } : undefined;
+ const onRef = isSelected
+ ? (element) => {
+ this._selectedCell = element;
+ }
+ : undefined;
- const handleSelect = (relayCity.hasActiveRelays && !isSelected) ? () => {
- this.props.onSelect(relayLocation);
- } : undefined;
+ const handleSelect =
+ relayCity.hasActiveRelays && !isSelected
+ ? () => {
+ this.props.onSelect(relayLocation);
+ }
+ : undefined;
return (
- <CellButton key={ `${countryCode}_${relayCity.code}` }
- onPress={ handleSelect }
+ <CellButton
+ key={`${countryCode}_${relayCity.code}`}
+ onPress={handleSelect}
disabled={!relayCity.hasActiveRelays}
cellHoverStyle={isSelected ? styles.sub_cell__selected : null}
style={isSelected ? styles.sub_cell__selected : styles.sub_cell}
- testName='city'
+ testName="city"
ref={onRef}>
+ {this._relayStatusIndicator(relayCity.hasActiveRelays, isSelected)}
- { this._relayStatusIndicator(relayCity.hasActiveRelays, isSelected) }
-
- <Label>
- { relayCity.name }
- </Label>
+ <Label>{relayCity.name}</Label>
</CellButton>
);
}
diff --git a/app/components/SelectLocationStyles.js b/app/components/SelectLocationStyles.js
index 721ad64eec..a0aec306d4 100644
--- a/app/components/SelectLocationStyles.js
+++ b/app/components/SelectLocationStyles.js
@@ -12,7 +12,7 @@ export default {
flexDirection: 'column',
flex: 1,
},
- header:{
+ header: {
flex: 0,
marginBottom: 16,
},
@@ -21,7 +21,7 @@ export default {
marginTop: 24,
cursor: 'default',
},
- close_icon:{
+ close_icon: {
width: 24,
height: 24,
flex: 0,
@@ -116,4 +116,4 @@ export default {
flex: 0,
},
}),
-}; \ No newline at end of file
+};
diff --git a/app/components/Settings.js b/app/components/Settings.js
index 0f87da2c11..33fc371faa 100644
--- a/app/components/Settings.js
+++ b/app/components/Settings.js
@@ -2,7 +2,7 @@
import moment from 'moment';
import * as React from 'react';
import { Component, Text, View } from 'reactxp';
-import { Button, CellButton, RedButton, Label, SubText} from './styled';
+import { Button, CellButton, RedButton, Label, SubText } from './styled';
import { Layout, Container } from './Layout';
import CustomScrollbars from './CustomScrollbars';
import styles from './SettingsStyles';
@@ -30,8 +30,11 @@ export default class Settings extends Component<SettingsProps> {
<Layout>
<Container>
<View style={styles.settings}>
- <Button style={styles.settings__close} onPress={ this.props.onClose } testName='settings__close'>
- <Img height={24} width={24} style={styles.settings__close_icon} source='icon-close'/>
+ <Button
+ style={styles.settings__close}
+ onPress={this.props.onClose}
+ testName="settings__close">
+ <Img height={24} width={24} style={styles.settings__close_icon} source="icon-close" />
</Button>
<View style={styles.settings__container}>
@@ -39,17 +42,15 @@ export default class Settings extends Component<SettingsProps> {
<Text style={styles.settings__title}>Settings</Text>
</View>
- <CustomScrollbars style={styles.settings__scrollview} autoHide={ true }>
-
+ <CustomScrollbars style={styles.settings__scrollview} autoHide={true}>
<View style={styles.settings__content}>
<View>
- { this._renderTopButtons() }
- { this._renderMiddleButtons() }
- { this._renderBottomButtons() }
+ {this._renderTopButtons()}
+ {this._renderMiddleButtons()}
+ {this._renderBottomButtons()}
</View>
- { this._renderQuitButton() }
+ {this._renderQuitButton()}
</View>
-
</CustomScrollbars>
</View>
</View>
@@ -64,59 +65,69 @@ export default class Settings extends Component<SettingsProps> {
return null;
}
- let isOutOfTime = false, formattedExpiry = '';
+ let isOutOfTime = false,
+ formattedExpiry = '';
let expiryIso = this.props.account.expiry;
- if(isLoggedIn && expiryIso) {
+ if (isLoggedIn && expiryIso) {
let expiry = moment(this.props.account.expiry);
isOutOfTime = expiry.isSameOrBefore(moment());
formattedExpiry = (expiry.fromNow(true) + ' left').toUpperCase();
}
- return <View>
- <View style={styles.settings_account} testName='settings__account'>
- {isOutOfTime ? (
- <CellButton onPress={ this.props.onViewAccount }
- testName='settings__account_paid_until_button'>
- <Label>Account</Label>
- <SubText testName='settings__account_paid_until_subtext' style={styles.settings__account_paid_until_Label__error}>OUT OF TIME</SubText>
- <Img height={12} width={7} source='icon-chevron' />
- </CellButton>
- ) : (
- <CellButton onPress={ this.props.onViewAccount }
- testName='settings__account_paid_until_button'>
- <Label>Account</Label>
- <SubText testName='settings__account_paid_until_subtext'>{ formattedExpiry }</SubText>
- <Img height={12} width={7} source='icon-chevron' />
- </CellButton>
- )}
- </View>
+ return (
+ <View>
+ <View style={styles.settings_account} testName="settings__account">
+ {isOutOfTime ? (
+ <CellButton
+ onPress={this.props.onViewAccount}
+ testName="settings__account_paid_until_button">
+ <Label>Account</Label>
+ <SubText
+ testName="settings__account_paid_until_subtext"
+ style={styles.settings__account_paid_until_Label__error}>
+ OUT OF TIME
+ </SubText>
+ <Img height={12} width={7} source="icon-chevron" />
+ </CellButton>
+ ) : (
+ <CellButton
+ onPress={this.props.onViewAccount}
+ testName="settings__account_paid_until_button">
+ <Label>Account</Label>
+ <SubText testName="settings__account_paid_until_subtext">{formattedExpiry}</SubText>
+ <Img height={12} width={7} source="icon-chevron" />
+ </CellButton>
+ )}
+ </View>
- <CellButton onPress={ this.props.onViewPreferences }
- testName='settings__preferences'>
- <Label>Preferences</Label>
- <Img height={12} width={7} source='icon-chevron' />
- </CellButton>
+ <CellButton onPress={this.props.onViewPreferences} testName="settings__preferences">
+ <Label>Preferences</Label>
+ <Img height={12} width={7} source="icon-chevron" />
+ </CellButton>
- <CellButton onPress={ this.props.onViewAdvancedSettings }
- testName='settings__advanced'>
- <Label>Advanced</Label>
- <Img height={12} width={7} source='icon-chevron' />
- </CellButton>
- <View style={styles.settings__cell_spacer}/>
- </View>;
+ <CellButton onPress={this.props.onViewAdvancedSettings} testName="settings__advanced">
+ <Label>Advanced</Label>
+ <Img height={12} width={7} source="icon-chevron" />
+ </CellButton>
+ <View style={styles.settings__cell_spacer} />
+ </View>
+ );
}
_renderMiddleButtons() {
- return <View>
- <CellButton onPress={ this.props.onExternalLink.bind(this, 'download') }
- testName='settings__version'>
- <Label>App version</Label>
- <SubText>{this._formattedVersion()}</SubText>
- <Img height={16} width={16} source='icon-extLink' />
- </CellButton>
- <View style={styles.settings__cell_spacer}/>
- </View>;
+ return (
+ <View>
+ <CellButton
+ onPress={this.props.onExternalLink.bind(this, 'download')}
+ testName="settings__version">
+ <Label>App version</Label>
+ <SubText>{this._formattedVersion()}</SubText>
+ <Img height={16} width={16} source="icon-extLink" />
+ </CellButton>
+ <View style={styles.settings__cell_spacer} />
+ </View>
+ );
}
_formattedVersion() {
@@ -124,39 +135,42 @@ export default class Settings extends Component<SettingsProps> {
// version scheme. in package.json we thus have to write YEAR.release.X-channel and
// this function is responsible for removing .X part.
return this.props.version
- .replace('.0-', '-') // remove the .0 in 2018.1.0-beta9
+ .replace('.0-', '-') // remove the .0 in 2018.1.0-beta9
.replace(/\.0$/, ''); // remove the .0 in 2018.1.0
}
_renderBottomButtons() {
- return <View>
- <CellButton onPress={ this.props.onExternalLink.bind(this, 'faq') }
- testName='settings__external_link'>
- <Label>FAQs</Label>
- <Img height={16} width={16} source='icon-extLink' />
- </CellButton>
+ return (
+ <View>
+ <CellButton
+ onPress={this.props.onExternalLink.bind(this, 'faq')}
+ testName="settings__external_link">
+ <Label>FAQs</Label>
+ <Img height={16} width={16} source="icon-extLink" />
+ </CellButton>
- <CellButton onPress={ this.props.onExternalLink.bind(this, 'guides') }
- testName='settings__external_link'>
- <Label>Guides</Label>
- <Img height={16} width={16} source='icon-extLink' />
- </CellButton>
+ <CellButton
+ onPress={this.props.onExternalLink.bind(this, 'guides')}
+ testName="settings__external_link">
+ <Label>Guides</Label>
+ <Img height={16} width={16} source="icon-extLink" />
+ </CellButton>
- <CellButton onPress={ this.props.onViewSupport }
- testName='settings__view_support'>
- <Label>Report a problem</Label>
- <Img height={12} width={7} source='icon-chevron' />
- </CellButton>
- </View>;
+ <CellButton onPress={this.props.onViewSupport} testName="settings__view_support">
+ <Label>Report a problem</Label>
+ <Img height={12} width={7} source="icon-chevron" />
+ </CellButton>
+ </View>
+ );
}
_renderQuitButton() {
- return <View style={styles.settings__footer}>
- <RedButton
- onPress={this.props.onQuit}
- testName='settings__quit'>
- <Label>Quit app</Label>
- </RedButton>
- </View>;
+ return (
+ <View style={styles.settings__footer}>
+ <RedButton onPress={this.props.onQuit} testName="settings__quit">
+ <Label>Quit app</Label>
+ </RedButton>
+ </View>
+ );
}
-} \ No newline at end of file
+}
diff --git a/app/components/SettingsStyles.js b/app/components/SettingsStyles.js
index d84673253e..82616f7e4a 100644
--- a/app/components/SettingsStyles.js
+++ b/app/components/SettingsStyles.js
@@ -1,62 +1,65 @@
import { createViewStyles, createTextStyles } from '../lib/styles';
import { colors } from '../config';
-export default Object.assign(createViewStyles({
- settings: {
- backgroundColor: colors.darkBlue,
- flex: 1,
- },
- settings__container:{
- flexDirection: 'column',
- flex: 1
- },
- settings__header:{
- flexGrow: 0,
- flexShrink: 0,
- flexBasis: 'auto',
- paddingTop: 16,
- paddingRight: 24,
- paddingLeft: 24,
- paddingBottom: 16,
- },
- settings__content: {
- flexDirection: 'column',
- flex: 1,
- justifyContent: 'space-between',
- },
- settings__scrollview: {
- flexGrow: 1,
- flexShrink: 1,
- flexBasis: '100%',
- },
- settings__close: {
- marginLeft: 12,
- marginTop: 24,
- cursor: 'default',
- },
- settings__close_icon:{
- width: 24,
- height: 24,
- flex: 0,
- opacity: 0.6,
- },
- settings__cell_spacer:{
- height: 24,
- flex: 0
- },
- settings__footer: {
- paddingTop: 16,
- paddingBottom: 16,
- },
-}), createTextStyles({
- settings__title:{
- fontFamily: 'DINPro',
- fontSize: 32,
- fontWeight: '900',
- lineHeight: 40,
- color: colors.white
- },
- settings__account_paid_until_label__error:{
- color: colors.red,
- },
-}));
+export default Object.assign(
+ createViewStyles({
+ settings: {
+ backgroundColor: colors.darkBlue,
+ flex: 1,
+ },
+ settings__container: {
+ flexDirection: 'column',
+ flex: 1,
+ },
+ settings__header: {
+ flexGrow: 0,
+ flexShrink: 0,
+ flexBasis: 'auto',
+ paddingTop: 16,
+ paddingRight: 24,
+ paddingLeft: 24,
+ paddingBottom: 16,
+ },
+ settings__content: {
+ flexDirection: 'column',
+ flex: 1,
+ justifyContent: 'space-between',
+ },
+ settings__scrollview: {
+ flexGrow: 1,
+ flexShrink: 1,
+ flexBasis: '100%',
+ },
+ settings__close: {
+ marginLeft: 12,
+ marginTop: 24,
+ cursor: 'default',
+ },
+ settings__close_icon: {
+ width: 24,
+ height: 24,
+ flex: 0,
+ opacity: 0.6,
+ },
+ settings__cell_spacer: {
+ height: 24,
+ flex: 0,
+ },
+ settings__footer: {
+ paddingTop: 16,
+ paddingBottom: 16,
+ },
+ }),
+ createTextStyles({
+ settings__title: {
+ fontFamily: 'DINPro',
+ fontSize: 32,
+ fontWeight: '900',
+ lineHeight: 40,
+ color: colors.white,
+ },
+ settings__account_paid_until_label__error: {
+ color: colors.red,
+ },
+ }),
+);
diff --git a/app/components/Support.js b/app/components/Support.js
index 0b3e88676a..fa4e6cf62d 100644
--- a/app/components/Support.js
+++ b/app/components/Support.js
@@ -23,10 +23,10 @@ type SupportState = {
export type SupportProps = {
account: AccountReduxState,
- onClose: () => void;
- onViewLog: (string) => void;
- onCollectLog: (Array<string>) => Promise<string>;
- onSend: (email: string, message: string, savedReport: string) => void;
+ onClose: () => void,
+ onViewLog: (string) => void,
+ onCollectLog: (Array<string>) => Promise<string>,
+ onSend: (email: string, message: string, savedReport: string) => void,
};
export default class Support extends Component<SupportProps, SupportState> {
@@ -43,28 +43,27 @@ export default class Support extends Component<SupportProps, SupportState> {
onChangeEmail = (email: string) => {
this.setState({ email: email });
- }
+ };
onChangeDescription = (description: string) => {
this.setState({ message: description });
- }
+ };
onViewLog = () => {
-
- this._getLog()
- .then((path) => {
- this.props.onViewLog(path);
- });
- }
+ this._getLog().then((path) => {
+ this.props.onViewLog(path);
+ });
+ };
_getLog(): Promise<string> {
const accountsToRedact = this.props.account.accountHistory;
const { savedReport } = this.state;
- return savedReport ?
- Promise.resolve(savedReport) :
- this.props.onCollectLog(accountsToRedact)
- .then( path => {
- return new Promise(resolve => this.setState({ savedReport: path }, () => resolve(path)));
+ return savedReport
+ ? Promise.resolve(savedReport)
+ : this.props.onCollectLog(accountsToRedact).then((path) => {
+ return new Promise((resolve) =>
+ this.setState({ savedReport: path }, () => resolve(path)),
+ );
});
}
@@ -76,39 +75,46 @@ export default class Support extends Component<SupportProps, SupportState> {
} else {
this._sendProblemReport();
}
- }
+ };
_sendProblemReport() {
- this.setState({
- sendState: 'LOADING',
- }, () => {
- this._getLog()
- .then((path) => {
- return this.props.onSend(this.state.email, this.state.message, path);
- })
- .then( () => {
- this.setState({
- sendState: 'SUCCESS',
- });
- })
- .catch( () => {
- this.setState({
- sendState: 'FAILED',
+ this.setState(
+ {
+ sendState: 'LOADING',
+ },
+ () => {
+ this._getLog()
+ .then((path) => {
+ return this.props.onSend(this.state.email, this.state.message, path);
+ })
+ .then(() => {
+ this.setState({
+ sendState: 'SUCCESS',
+ });
+ })
+ .catch(() => {
+ this.setState({
+ sendState: 'FAILED',
+ });
});
- });
- });
+ },
+ );
}
render() {
-
const { sendState } = this.state;
- const header = <View style={styles.support__header}>
- <Text style={styles.support__title}>Report a problem</Text>
- { (sendState === 'INITIAL' || sendState === 'CONFIRM_NO_EMAIL') && <Text style={styles.support__subtitle}>
- { 'To help you more effectively, your app\'s log file will be attached to this message. Your data will remain secure and private, as it is anonymised before being sent over an encrypted channel.' }
- </Text>
- }
- </View>;
+ const header = (
+ <View style={styles.support__header}>
+ <Text style={styles.support__title}>Report a problem</Text>
+ {(sendState === 'INITIAL' || sendState === 'CONFIRM_NO_EMAIL') && (
+ <Text style={styles.support__subtitle}>
+ {
+ "To help you more effectively, your app's log file will be attached to this message. Your data will remain secure and private, as it is anonymised before being sent over an encrypted channel."
+ }
+ </Text>
+ )}
+ </View>
+ );
const content = this._renderContent();
@@ -116,16 +122,17 @@ export default class Support extends Component<SupportProps, SupportState> {
<Layout>
<Container>
<View style={styles.support}>
- <Button style={styles.support__close} onPress={ this.props.onClose } testName="support__close">
+ <Button
+ style={styles.support__close}
+ onPress={this.props.onClose}
+ testName="support__close">
<Img height={24} width={24} style={styles.support__close_icon} source="icon-back" />
<Text style={styles.support__close_title}>Settings</Text>
</Button>
<View style={styles.support__container}>
+ {header}
- { header }
-
- { content }
-
+ {content}
</View>
</View>
</Container>
@@ -134,154 +141,150 @@ export default class Support extends Component<SupportProps, SupportState> {
}
_renderContent() {
- switch(this.state.sendState) {
- case 'INITIAL':
- case 'CONFIRM_NO_EMAIL':
- return this._renderForm();
- case 'LOADING':
- return this._renderLoading();
- case 'SUCCESS':
- return this._renderSent();
- case 'FAILED':
- return this._renderFailed();
- default:
- return null;
+ switch (this.state.sendState) {
+ case 'INITIAL':
+ case 'CONFIRM_NO_EMAIL':
+ return this._renderForm();
+ case 'LOADING':
+ return this._renderLoading();
+ case 'SUCCESS':
+ return this._renderSent();
+ case 'FAILED':
+ return this._renderFailed();
+ default:
+ return null;
}
}
_renderForm() {
-
- return <View style={styles.support__content}>
- <View style={styles.support__form}>
- <View style={styles.support__form_row}>
- <TextInput style={styles.support__form_email}
- placeholder="Your email"
- defaultValue={ this.state.email }
- onChangeText={ this.onChangeEmail }
- keyboardType="email-address" />
- </View>
- <View style={styles.support__form_row_message}>
- <View style={styles.support__form_message_scroll_wrap}>
- <TextInput style={styles.support__form_message}
- placeholder="Describe your problem"
- defaultValue={ this.state.message }
- multiline={ true }
- onChangeText={ this.onChangeDescription }
- testName="support__form_message"/>
+ return (
+ <View style={styles.support__content}>
+ <View style={styles.support__form}>
+ <View style={styles.support__form_row}>
+ <TextInput
+ style={styles.support__form_email}
+ placeholder="Your email"
+ defaultValue={this.state.email}
+ onChangeText={this.onChangeEmail}
+ keyboardType="email-address"
+ />
</View>
- </View>
- <View style={styles.support__footer}>
- {
- this.state.sendState === 'CONFIRM_NO_EMAIL'
+ <View style={styles.support__form_row_message}>
+ <View style={styles.support__form_message_scroll_wrap}>
+ <TextInput
+ style={styles.support__form_message}
+ placeholder="Describe your problem"
+ defaultValue={this.state.message}
+ multiline={true}
+ onChangeText={this.onChangeDescription}
+ testName="support__form_message"
+ />
+ </View>
+ </View>
+ <View style={styles.support__footer}>
+ {this.state.sendState === 'CONFIRM_NO_EMAIL'
? this._renderNoEmailWarning()
- : this._renderActionButtons()
- }
+ : this._renderActionButtons()}
+ </View>
</View>
</View>
- </View>;
+ );
}
_renderNoEmailWarning() {
- return <View>
- <Text style={styles.support__no_email_warning}>
- You are about to send the problem report without a way for us to get back to you. If you want an answer to your report you will have to enter an email address.
- </Text>
- <GreenButton
- disabled={ !this.validate() }
- onPress={ this.onSend }
- testName='support__send_logs'>
- Send anyway
- </GreenButton>
- </View>;
+ return (
+ <View>
+ <Text style={styles.support__no_email_warning}>
+ You are about to send the problem report without a way for us to get back to you. If you
+ want an answer to your report you will have to enter an email address.
+ </Text>
+ <GreenButton
+ disabled={!this.validate()}
+ onPress={this.onSend}
+ testName="support__send_logs">
+ Send anyway
+ </GreenButton>
+ </View>
+ );
}
_renderActionButtons() {
return [
- <BlueButton key={1}
- onPress={ this.onViewLog }
- testName='support__view_logs'>
+ <BlueButton key={1} onPress={this.onViewLog} testName="support__view_logs">
<Label>View app logs</Label>
- <Img source='icon-extLink' height={16} width={16} />
+ <Img source="icon-extLink" height={16} width={16} />
</BlueButton>,
- <GreenButton key={2}
- disabled={ !this.validate() }
- onPress={ this.onSend }
- testName='support__send_logs'>
+ <GreenButton
+ key={2}
+ disabled={!this.validate()}
+ onPress={this.onSend}
+ testName="support__send_logs">
Send
- </GreenButton>
+ </GreenButton>,
];
}
_renderLoading() {
- return <View style={styles.support__content}>
- <View style={styles.support__form}>
- <View style={styles.support__form_row}>
- <View style={styles.support__status_icon}>
- <Img source="icon-spinner" height={60} width={60} alt="" />
- </View>
- <View style={styles.support__status_security__secure}>
- Secure Connection
+ return (
+ <View style={styles.support__content}>
+ <View style={styles.support__form}>
+ <View style={styles.support__form_row}>
+ <View style={styles.support__status_icon}>
+ <Img source="icon-spinner" height={60} width={60} alt="" />
+ </View>
+ <View style={styles.support__status_security__secure}>Secure Connection</View>
+ <Text style={styles.support__send_status}>Sending...</Text>
</View>
- <Text style={styles.support__send_status}>
- Sending...
- </Text>
</View>
</View>
- </View>;
+ );
}
_renderSent() {
- return <View style={styles.support__content}>
- <View style={styles.support__form}>
- <View style={styles.support__form_row}>
- <View style={styles.support__status_icon}>
- <Img source="icon-success" height={60} width={60} alt="" />
- </View>
- <Text style={styles.support__status_security__secure}>
- Secure Connection
- </Text>
- <Text style={styles.support__send_status}>
- Sent
- </Text>
+ return (
+ <View style={styles.support__content}>
+ <View style={styles.support__form}>
+ <View style={styles.support__form_row}>
+ <View style={styles.support__status_icon}>
+ <Img source="icon-success" height={60} width={60} alt="" />
+ </View>
+ <Text style={styles.support__status_security__secure}>Secure Connection</Text>
+ <Text style={styles.support__send_status}>Sent</Text>
- <Text style={styles.support__subtitle}>
- Thanks! We will look into this.
- </Text>
- { this.state.email.trim().length > 0 ?
- <Text style={styles.support__subtitle}>If needed we will contact you on {'\u00A0'}
- <Text style={styles.support__sent_email}>{ this.state.email }</Text>
- </Text>
- : null }
+ <Text style={styles.support__subtitle}>Thanks! We will look into this.</Text>
+ {this.state.email.trim().length > 0 ? (
+ <Text style={styles.support__subtitle}>
+ If needed we will contact you on {'\u00A0'}
+ <Text style={styles.support__sent_email}>{this.state.email}</Text>
+ </Text>
+ ) : null}
+ </View>
</View>
</View>
- </View>;
+ );
}
_renderFailed() {
- return <View style={styles.support__content}>
- <View style={styles.support__form}>
- <View style={styles.support__form_row}>
- <View style={styles.support__status_icon}>
- <Img source="icon-fail" height={60} width={60} alt="" />
+ return (
+ <View style={styles.support__content}>
+ <View style={styles.support__form}>
+ <View style={styles.support__form_row}>
+ <View style={styles.support__status_icon}>
+ <Img source="icon-fail" height={60} width={60} alt="" />
+ </View>
+ <Text style={styles.support__status_security__secure}>Secure Connection</Text>
+ <Text style={styles.support__send_status}>Failed to send</Text>
</View>
- <Text style={styles.support__status_security__secure}>
- Secure Connection
- </Text>
- <Text style={styles.support__send_status}>
- Failed to send
- </Text>
+ </View>
+ <View style={styles.support__footer}>
+ <BlueButton onPress={() => this.setState({ sendState: 'INITIAL' })}>
+ Edit message
+ </BlueButton>
+ <GreenButton onPress={this.onSend} testName="support__send_logs">
+ Try again
+ </GreenButton>
</View>
</View>
- <View style={styles.support__footer}>
- <BlueButton onPress={ () => this.setState({ sendState: 'INITIAL' }) }>
- Edit message
- </BlueButton>
- <GreenButton
- onPress={ this.onSend }
- testName='support__send_logs'>
- Try again
- </GreenButton>
- </View>
- </View>;
+ );
}
}
diff --git a/app/components/SupportStyles.js b/app/components/SupportStyles.js
index cc6cca788c..ea1f26651d 100644
--- a/app/components/SupportStyles.js
+++ b/app/components/SupportStyles.js
@@ -1,157 +1,160 @@
import { createViewStyles, createTextStyles } from '../lib/styles';
import { colors } from '../config';
-export default Object.assign(createViewStyles({
- support:{
- backgroundColor: colors.darkBlue,
- flex: 1,
- },
- support__container:{
- display: 'flex',
- flexDirection: 'column',
- flex: 1
- },
- support__header:{
- flex: 0,
- paddingTop: 12,
- paddingBottom: 12,
- paddingLeft: 24,
- paddingRight: 24,
- },
- support__close:{
- paddingLeft: 12,
- paddingTop: 24,
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'flex-start',
- },
- support__close_icon:{
- flex: 0,
- opacity: 0.6,
- marginRight: 8,
- },
- support__content:{
- flex: 1,
- display: 'flex',
- flexDirection: 'column',
- justifyContent: 'space-between',
- },
- support__form:{
- display: 'flex',
- flex: 1,
- flexDirection: 'column',
- },
- support__form_row:{
- paddingTop: 0,
- paddingBottom: 8,
- paddingLeft: 22,
- paddingRight: 22,
- },
- support__form_row_message:{
- flex: 1,
- paddingTop: 0,
- paddingBottom: 8,
- paddingLeft: 22,
- paddingRight: 22,
- },
- support__form_message_scroll_wrap:{
- flex: 1,
- display: 'flex',
- borderRadius: 4,
- overflow: 'hidden',
- },
- support__footer:{
- paddingTop: 0,
- paddingBottom: 16,
- display: 'flex',
- flexDirection: 'column',
- flex: 0,
- },
- support__status_icon:{
- textAlign: 'center',
- marginBottom: 32,
- },
-}), createTextStyles({
- support__close_title:{
- fontFamily: 'Open Sans',
- fontSize: 13,
- fontWeight: '600',
- color: colors.white60,
- },
- support__title:{
- fontFamily: 'DINPro',
- fontSize: 32,
- fontWeight: '900',
- lineHeight: 40,
- color: colors.white,
- marginBottom: 16,
- },
- support__subtitle:{
- fontFamily: 'Open Sans',
- fontSize: 13,
- fontWeight: '600',
- overflow: 'visible',
- color: colors.white80,
- lineHeight: 20,
- letterSpacing: -0.2,
- },
- support__form_email:{
- flex: 1,
- borderRadius: 4,
- overflow: 'hidden',
- paddingTop: 14,
- paddingLeft: 14,
- paddingRight: 14,
- paddingBottom: 14,
- fontFamily: 'Open Sans',
- fontSize: 13,
- fontWeight: '600',
- lineHeight: 26,
- color: colors.blue,
- backgroundColor: colors.white,
- },
- support__form_message:{
- paddingTop: 14,
- paddingLeft: 14,
- paddingRight: 14,
- paddingBottom: 14,
- fontFamily: 'Open Sans',
- fontSize: 13,
- fontWeight: '600',
- color: colors.blue,
- backgroundColor: colors.white,
- flex: 1,
- },
- support__sent_email:{
- fontWeight: '900',
- color: colors.white,
- },
- support__status_security__secure:{
- fontFamily: 'Open Sans',
- fontSize: 16,
- fontWeight: '800',
- lineHeight: 22,
- marginBottom: 4,
- color: colors.green,
- },
- support__send_status:{
- fontFamily: 'DINPro',
- fontSize: 38,
- fontWeight: '900',
- maxHeight: 'calc(1.16em * 2)',
- overflow: 'visible',
- letterSpacing: -0.9,
- color: colors.white,
- marginBottom: 4,
- },
- support__no_email_warning: {
- fontFamily: 'Open Sans',
- fontSize: 13,
- lineHeight: 16,
- color: colors.white80,
- paddingTop: 8,
- paddingLeft: 24,
- paddingRight: 24,
- paddingBottom: 8,
- },
-}));
+export default Object.assign(
+ createViewStyles({
+ support: {
+ backgroundColor: colors.darkBlue,
+ flex: 1,
+ },
+ support__container: {
+ display: 'flex',
+ flexDirection: 'column',
+ flex: 1,
+ },
+ support__header: {
+ flex: 0,
+ paddingTop: 12,
+ paddingBottom: 12,
+ paddingLeft: 24,
+ paddingRight: 24,
+ },
+ support__close: {
+ paddingLeft: 12,
+ paddingTop: 24,
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'flex-start',
+ },
+ support__close_icon: {
+ flex: 0,
+ opacity: 0.6,
+ marginRight: 8,
+ },
+ support__content: {
+ flex: 1,
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'space-between',
+ },
+ support__form: {
+ display: 'flex',
+ flex: 1,
+ flexDirection: 'column',
+ },
+ support__form_row: {
+ paddingTop: 0,
+ paddingBottom: 8,
+ paddingLeft: 22,
+ paddingRight: 22,
+ },
+ support__form_row_message: {
+ flex: 1,
+ paddingTop: 0,
+ paddingBottom: 8,
+ paddingLeft: 22,
+ paddingRight: 22,
+ },
+ support__form_message_scroll_wrap: {
+ flex: 1,
+ display: 'flex',
+ borderRadius: 4,
+ overflow: 'hidden',
+ },
+ support__footer: {
+ paddingTop: 0,
+ paddingBottom: 16,
+ display: 'flex',
+ flexDirection: 'column',
+ flex: 0,
+ },
+ support__status_icon: {
+ textAlign: 'center',
+ marginBottom: 32,
+ },
+ }),
+ createTextStyles({
+ support__close_title: {
+ fontFamily: 'Open Sans',
+ fontSize: 13,
+ fontWeight: '600',
+ color: colors.white60,
+ },
+ support__title: {
+ fontFamily: 'DINPro',
+ fontSize: 32,
+ fontWeight: '900',
+ lineHeight: 40,
+ color: colors.white,
+ marginBottom: 16,
+ },
+ support__subtitle: {
+ fontFamily: 'Open Sans',
+ fontSize: 13,
+ fontWeight: '600',
+ overflow: 'visible',
+ color: colors.white80,
+ lineHeight: 20,
+ letterSpacing: -0.2,
+ },
+ support__form_email: {
+ flex: 1,
+ borderRadius: 4,
+ overflow: 'hidden',
+ paddingTop: 14,
+ paddingLeft: 14,
+ paddingRight: 14,
+ paddingBottom: 14,
+ fontFamily: 'Open Sans',
+ fontSize: 13,
+ fontWeight: '600',
+ lineHeight: 26,
+ color: colors.blue,
+ backgroundColor: colors.white,
+ },
+ support__form_message: {
+ paddingTop: 14,
+ paddingLeft: 14,
+ paddingRight: 14,
+ paddingBottom: 14,
+ fontFamily: 'Open Sans',
+ fontSize: 13,
+ fontWeight: '600',
+ color: colors.blue,
+ backgroundColor: colors.white,
+ flex: 1,
+ },
+ support__sent_email: {
+ fontWeight: '900',
+ color: colors.white,
+ },
+ support__status_security__secure: {
+ fontFamily: 'Open Sans',
+ fontSize: 16,
+ fontWeight: '800',
+ lineHeight: 22,
+ marginBottom: 4,
+ color: colors.green,
+ },
+ support__send_status: {
+ fontFamily: 'DINPro',
+ fontSize: 38,
+ fontWeight: '900',
+ maxHeight: 'calc(1.16em * 2)',
+ overflow: 'visible',
+ letterSpacing: -0.9,
+ color: colors.white,
+ marginBottom: 4,
+ },
+ support__no_email_warning: {
+ fontFamily: 'Open Sans',
+ fontSize: 13,
+ lineHeight: 16,
+ color: colors.white80,
+ paddingTop: 8,
+ paddingLeft: 24,
+ paddingRight: 24,
+ paddingBottom: 8,
+ },
+ }),
+);
diff --git a/app/components/SvgMap.js b/app/components/SvgMap.js
index 48288f9a8a..43f1e2ef71 100644
--- a/app/components/SvgMap.js
+++ b/app/components/SvgMap.js
@@ -1,7 +1,14 @@
// @flow
import * as React from 'react';
-import { ComposableMap, ZoomableGroup, Geographies, Geography, Markers, Marker } from 'react-simple-maps';
+import {
+ ComposableMap,
+ ZoomableGroup,
+ Geographies,
+ Geography,
+ Markers,
+ Marker,
+} from 'react-simple-maps';
import { geoTimes } from 'd3-geo-projection';
import rbush from 'rbush';
@@ -56,7 +63,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
};
_projectionConfig = {
- scale: 160
+ scale: 160,
};
constructor(props: SvgMapProps) {
@@ -66,8 +73,8 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
}
componentWillReceiveProps(nextProps: SvgMapProps) {
- if(this._shouldInvalidateState(nextProps)) {
- this.setState(prevState => this._getNextState(prevState, nextProps));
+ if (this._shouldInvalidateState(nextProps)) {
+ this.setState((prevState) => this._getNextState(prevState, nextProps));
}
}
@@ -75,18 +82,13 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
return (
this.props.width !== nextProps.width ||
this.props.height !== nextProps.height ||
-
this.props.center[0] !== nextProps.center[0] ||
this.props.center[1] !== nextProps.center[1] ||
-
this.props.offset[0] !== nextProps.offset[0] ||
this.props.offset[1] !== nextProps.offset[1] ||
-
this.props.zoomLevel !== nextProps.zoomLevel ||
-
this.props.showMarker !== nextProps.showMarker ||
this.props.markerImagePath !== nextProps.markerImagePath ||
-
this.state.zoomCenter !== nextState.zoomCenter ||
this.state.zoomLevel !== nextState.zoomLevel
);
@@ -100,7 +102,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
};
const zoomableGroupStyle = {
- transition: `transform ${MOVE_SPEED}ms ease-in-out`
+ transition: `transform ${MOVE_SPEED}ms ease-in-out`,
};
const geographyStyle = this._mergeRsmStyle({
@@ -108,7 +110,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
fill: '#294d73',
stroke: '#192e45',
strokeWidth: `${1 / this.state.zoomLevel}`,
- }
+ },
});
const stateProvinceLineStyle = this._mergeRsmStyle({
@@ -116,7 +118,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
fill: 'transparent',
stroke: '#192e45',
strokeWidth: `${1 / this.state.zoomLevel}`,
- }
+ },
});
const markerStyle = this._mergeRsmStyle({
@@ -128,71 +130,74 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
// disable CSS transition when moving between locations
// by using the different "key"
const userMarker = this.props.showMarker && (
- <Marker key={ `user-location-${ this.props.center.join('-') }` }
+ <Marker
+ key={`user-location-${this.props.center.join('-')}`}
marker={{ coordinates: this.props.center }}
- style={ markerStyle }>
- <image x="-30" y="-30" href={ this.props.markerImagePath } />
+ style={markerStyle}>
+ <image x="-30" y="-30" href={this.props.markerImagePath} />
</Marker>
);
- const countryMarkers = this.state.visibleCountries.map(item => (
- <Marker key={ `country-${item.id}` }
+ const countryMarkers = this.state.visibleCountries.map((item) => (
+ <Marker
+ key={`country-${item.id}`}
marker={{ coordinates: item.geometry.coordinates }}
- style={ markerStyle }>
+ style={markerStyle}>
<text fill="rgba(255,255,255,.6)" fontSize="22" textAnchor="middle">
- { item.properties.name }
+ {item.properties.name}
</text>
</Marker>
));
- const cityMarkers = this.state.visibleCities.map(item => (
- <Marker key={ `city-${item.id}` }
+ const cityMarkers = this.state.visibleCities.map((item) => (
+ <Marker
+ key={`city-${item.id}`}
marker={{ coordinates: item.geometry.coordinates }}
- style={ markerStyle }>
+ style={markerStyle}>
<circle r="2" fill="rgba(255,255,255,.6)" />
<text x="0" y="-10" fill="rgba(255,255,255,.6)" fontSize="16" textAnchor="middle">
- { item.properties.name }
+ {item.properties.name}
</text>
</Marker>
));
return (
<ComposableMap
- width={ this.props.width }
- height={ this.props.height }
- style={ mapStyle }
- projection={ this._getProjection }
- projectionConfig={ this._projectionConfig }>
+ width={this.props.width}
+ height={this.props.height}
+ style={mapStyle}
+ projection={this._getProjection}
+ projectionConfig={this._projectionConfig}>
<ZoomableGroup
- center={ this.state.zoomCenter }
- zoom={ this.state.zoomLevel }
- disablePanning={ false }
- style={ zoomableGroupStyle }>
- <Geographies geography={ geographyData } disableOptimization={ true }>
+ center={this.state.zoomCenter}
+ zoom={this.state.zoomLevel}
+ disablePanning={false}
+ style={zoomableGroupStyle}>
+ <Geographies geography={geographyData} disableOptimization={true}>
{(geographies, projection) => {
return this.state.visibleGeometry.map(({ id }) => (
<Geography
- key={ id }
- geography={ geographies[id] }
- projection={ projection }
- style={ geographyStyle } />
+ key={id}
+ geography={geographies[id]}
+ projection={projection}
+ style={geographyStyle}
+ />
));
}}
</Geographies>
- <Geographies geography={ statesProvincesLinesData } disableOptimization={ true }>
+ <Geographies geography={statesProvincesLinesData} disableOptimization={true}>
{(geographies, projection) => {
return this.state.visibleStatesProvincesLines.map(({ id }) => (
<Geography
- key={ id }
- geography={ geographies[id] }
- projection={ projection }
- style={ stateProvinceLineStyle } />
+ key={id}
+ geography={geographies[id]}
+ projection={projection}
+ style={stateProvinceLineStyle}
+ />
));
}}
</Geographies>
- <Markers>
- { [...countryMarkers, ...cityMarkers, userMarker] }
- </Markers>
+ <Markers>{[...countryMarkers, ...cityMarkers, userMarker]}</Markers>
</ZoomableGroup>
</ComposableMap>
);
@@ -203,17 +208,21 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
return {
default: defaultStyle,
hover: style.hover || defaultStyle,
- pressed: style.pressed || defaultStyle
+ pressed: style.pressed || defaultStyle,
};
}
- _getProjection(width: number, height: number, config: {
- scale?: number,
- xOffset?: number,
- yOffset?: number,
- rotation?: [number, number, number],
- precision?: number,
- }) {
+ _getProjection(
+ width: number,
+ height: number,
+ config: {
+ scale?: number,
+ xOffset?: number,
+ yOffset?: number,
+ rotation?: [number, number, number],
+ precision?: number,
+ },
+ ) {
const scale = config.scale || 160;
const xOffset = config.xOffset || 0;
const yOffset = config.yOffset || 0;
@@ -222,7 +231,7 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
return geoTimes()
.scale(scale)
- .translate([ xOffset + width / 2, yOffset + height / 2 ])
+ .translate([xOffset + width / 2, yOffset + height / 2])
.rotate(rotation)
.precision(precision);
}
@@ -231,24 +240,22 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
center: [number, number],
offset: [number, number],
projection: Function,
- zoom: number
+ zoom: number,
) {
const pos = projection(center);
- return projection.invert([
- pos[0] + offset[0] / zoom,
- pos[1] + offset[1] / zoom
- ]);
+ return projection.invert([pos[0] + offset[0] / zoom, pos[1] + offset[1] / zoom]);
}
_getViewportGeoBoundingBox(
centerCoordinate: [number, number],
- width: number, height: number,
+ width: number,
+ height: number,
projection: Function,
- zoom: number
+ zoom: number,
) {
const center = projection(centerCoordinate);
- const halfWidth = width * 0.5 / zoom;
- const halfHeight = height * 0.5 / zoom;
+ const halfWidth = (width * 0.5) / zoom;
+ const halfHeight = (height * 0.5) / zoom;
const northWest = projection.invert([center[0] - halfWidth, center[1] - halfHeight]);
const southEast = projection.invert([center[0] + halfWidth, center[1] + halfHeight]);
@@ -267,13 +274,10 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
return (
oldProps.width !== nextProps.width ||
oldProps.height !== nextProps.height ||
-
oldProps.center[0] !== nextProps.center[0] ||
oldProps.center[1] !== nextProps.center[1] ||
-
oldProps.offset[0] !== nextProps.offset[0] ||
oldProps.offset[1] !== nextProps.offset[1] ||
-
oldProps.zoomLevel !== nextProps.zoomLevel
);
}
@@ -283,27 +287,38 @@ export default class SvgMap extends React.Component<SvgMapProps, SvgMapState> {
const projection = this._getProjection(width, height, this._projectionConfig);
const zoomCenter = this._getZoomCenter(center, offset, projection, zoomLevel);
- const viewportBbox = this._getViewportGeoBoundingBox(zoomCenter, width, height, projection, zoomLevel);
+ const viewportBbox = this._getViewportGeoBoundingBox(
+ zoomCenter,
+ width,
+ height,
+ projection,
+ zoomLevel,
+ );
const viewportBboxMatch = {
- minX: viewportBbox[0], minY: viewportBbox[1],
- maxX: viewportBbox[2], maxY: viewportBbox[3],
- };
-
- // combine previous and current viewports to get the rough area of transition
- const combinedViewportBboxMatch = prevState ? {
- minX: Math.min(viewportBbox[0], prevState.viewportBbox[0]),
- minY: Math.min(viewportBbox[1], prevState.viewportBbox[1]),
- maxX: Math.max(viewportBbox[2], prevState.viewportBbox[2]),
- maxY: Math.max(viewportBbox[3], prevState.viewportBbox[3]),
- } : {
minX: viewportBbox[0],
minY: viewportBbox[1],
maxX: viewportBbox[2],
maxY: viewportBbox[3],
};
- const visibleCountries = zoomLevel < 5 || zoomLevel > 20 ? [] : countryTree.search(viewportBboxMatch);
+ // combine previous and current viewports to get the rough area of transition
+ const combinedViewportBboxMatch = prevState
+ ? {
+ minX: Math.min(viewportBbox[0], prevState.viewportBbox[0]),
+ minY: Math.min(viewportBbox[1], prevState.viewportBbox[1]),
+ maxX: Math.max(viewportBbox[2], prevState.viewportBbox[2]),
+ maxY: Math.max(viewportBbox[3], prevState.viewportBbox[3]),
+ }
+ : {
+ minX: viewportBbox[0],
+ minY: viewportBbox[1],
+ maxX: viewportBbox[2],
+ maxY: viewportBbox[3],
+ };
+
+ const visibleCountries =
+ zoomLevel < 5 || zoomLevel > 20 ? [] : countryTree.search(viewportBboxMatch);
const visibleCities = zoomLevel >= 40 ? cityTree.search(viewportBboxMatch) : [];
const visibleGeometry = geometryTree.search(combinedViewportBboxMatch);
const visibleStatesProvincesLines = provincesStatesLinesTree.search(combinedViewportBboxMatch);
diff --git a/app/components/Switch.android.js b/app/components/Switch.android.js
index 17bb976186..4689107868 100644
--- a/app/components/Switch.android.js
+++ b/app/components/Switch.android.js
@@ -3,28 +3,22 @@ import * as React from 'react';
import { Switch as _Switch } from 'react-native';
export type SwitchProps = {
- isOn: boolean;
- onChange?: (isOn: boolean) => void;
+ isOn: boolean,
+ onChange?: (isOn: boolean) => void,
};
-type State = {
-};
+type State = {};
export default class Switch extends React.Component<SwitchProps, State> {
static defaultProps: SwitchProps = {
isOn: false,
- onChange: ()=>{},
+ onChange: () => {},
};
- state = {
- };
+ state = {};
render() {
const { isOn, ...otherProps } = this.props;
- return (
- <_Switch { ...otherProps }
- value={ isOn }
- onValueChange={ this.props.onChange(isOn) } />
- );
+ return <_Switch {...otherProps} value={isOn} onValueChange={this.props.onChange(isOn)} />;
}
}
diff --git a/app/components/Switch.js b/app/components/Switch.js
index 6bd4b8e4d0..257b2c6587 100644
--- a/app/components/Switch.js
+++ b/app/components/Switch.js
@@ -5,41 +5,41 @@ const CLICK_TIMEOUT = 1000;
const MOVE_THRESHOLD = 10;
export type SwitchProps = {
- className?: string;
- isOn: boolean;
- onChange: ?((isOn: boolean) => void);
+ className?: string,
+ isOn: boolean,
+ onChange: ?(isOn: boolean) => void,
};
type State = {
ignoreChange: boolean,
- initialPos: {x: number, y: number},
+ initialPos: { x: number, y: number },
startTime: ?number,
};
export default class Switch extends React.Component<SwitchProps, State> {
static defaultProps: SwitchProps = {
isOn: false,
- onChange: null
+ onChange: null,
};
state = {
ignoreChange: false,
- initialPos: {x: 0, y: 0},
- startTime: (null: ?number)
+ initialPos: { x: 0, y: 0 },
+ startTime: (null: ?number),
};
isCapturingMouseEvents = false;
ref: ?HTMLInputElement;
- onRef = (e: ?HTMLInputElement) => this.ref = e;
+ onRef = (e: ?HTMLInputElement) => (this.ref = e);
handleMouseDown = (e: MouseEvent) => {
const { clientX: x, clientY: y } = e;
this.startCapturingMouseEvents();
this.setState({
initialPos: { x, y },
- startTime: e.timeStamp
+ startTime: e.timeStamp,
});
- }
+ };
handleMouseMove = (e: MouseEvent) => {
const inputElement = this.ref;
@@ -47,66 +47,66 @@ export default class Switch extends React.Component<SwitchProps, State> {
const { clientX: x, clientY: y } = e;
const dx = Math.abs(x0 - x);
- if(dx < MOVE_THRESHOLD) {
+ if (dx < MOVE_THRESHOLD) {
return;
}
const isOn = !!this.props.isOn;
let nextOn = isOn;
- if(x < x0 && isOn) {
+ if (x < x0 && isOn) {
nextOn = false;
- } else if(x > x0 && !isOn) {
+ } else if (x > x0 && !isOn) {
nextOn = true;
}
- if(isOn !== nextOn) {
+ if (isOn !== nextOn) {
this.setState({
initialPos: { x, y },
- ignoreChange: true
+ ignoreChange: true,
});
- if(inputElement) {
+ if (inputElement) {
inputElement.checked = nextOn;
}
this.notify(nextOn);
}
- }
+ };
handleMouseUp = () => {
this.stopCapturingMouseEvents();
- }
+ };
handleChange = (e: Event) => {
const startTime = this.state.startTime;
const eventTarget: Object = e.target;
- if(typeof(startTime) !== 'number') {
+ if (typeof startTime !== 'number') {
throw new Error('startTime must be a number.');
}
const dt = e.timeStamp - startTime;
- if(this.state.ignoreChange) {
+ if (this.state.ignoreChange) {
this.setState({ ignoreChange: false });
e.preventDefault();
- } else if(dt > CLICK_TIMEOUT) {
+ } else if (dt > CLICK_TIMEOUT) {
e.preventDefault();
} else {
this.notify(eventTarget.checked);
}
- }
+ };
notify(isOn: boolean) {
const onChange = this.props.onChange;
- if(onChange) {
+ if (onChange) {
onChange(isOn);
}
}
startCapturingMouseEvents() {
- if(this.isCapturingMouseEvents) {
+ if (this.isCapturingMouseEvents) {
throw new Error('startCapturingMouseEvents() is called out of order.');
}
document.addEventListener('mousemove', this.handleMouseMove);
@@ -115,7 +115,7 @@ export default class Switch extends React.Component<SwitchProps, State> {
}
stopCapturingMouseEvents() {
- if(!this.isCapturingMouseEvents) {
+ if (!this.isCapturingMouseEvents) {
throw new Error('stopCapturingMouseEvents() is called out of order.');
}
document.removeEventListener('mousemove', this.handleMouseMove);
@@ -125,7 +125,7 @@ export default class Switch extends React.Component<SwitchProps, State> {
componentWillUnmount() {
// guard from abrupt programmatic unmount
- if(this.isCapturingMouseEvents) {
+ if (this.isCapturingMouseEvents) {
this.stopCapturingMouseEvents();
}
}
@@ -135,13 +135,15 @@ export default class Switch extends React.Component<SwitchProps, State> {
const { isOn, onChange, ...otherProps } = this.props;
const className = ('switch ' + (otherProps.className || '')).trim();
return (
- <input { ...otherProps }
+ <input
+ {...otherProps}
type="checkbox"
- ref={ this.onRef }
- className={ className }
- checked={ isOn }
- onMouseDown={ this.handleMouseDown }
- onChange={ this.handleChange } />
+ ref={this.onRef}
+ className={className}
+ checked={isOn}
+ onMouseDown={this.handleMouseDown}
+ onChange={this.handleChange}
+ />
);
}
}
diff --git a/app/components/TransitionContainer.js b/app/components/TransitionContainer.js
index 687a9ae9e0..1b6e8aee8f 100644
--- a/app/components/TransitionContainer.js
+++ b/app/components/TransitionContainer.js
@@ -6,19 +6,18 @@ import getStyles from './TransitionContainerStyles';
type TransitionContainerProps = {
children: React.Node,
- ...TransitionGroupProps
+ ...TransitionGroupProps,
};
type State = {
- previousChildren: ?React.Node,
- childrenAnimation: Types.AnimatedViewStyleRuleSet,
- previousChildrenAnimation: Types.AnimatedViewStyleRuleSet,
- animationStyles: Types.AnimatedViewStyleRuleSet,
- dimensions: Types.Dimensions,
+ previousChildren: ?React.Node,
+ childrenAnimation: Types.AnimatedViewStyleRuleSet,
+ previousChildrenAnimation: Types.AnimatedViewStyleRuleSet,
+ animationStyles: Types.AnimatedViewStyleRuleSet,
+ dimensions: Types.Dimensions,
};
export default class TransitionContainer extends Component<TransitionContainerProps, State> {
-
constructor(props: TransitionContainerProps) {
super(props);
@@ -30,157 +29,172 @@ export default class TransitionContainer extends Component<TransitionContainerPr
}
componentWillReceiveProps(nextProps: TransitionContainerProps) {
- switch (nextProps.name){
- case 'slide-up':
- this.slideUpTransition(nextProps);
- break;
- case 'slide-down':
- this.slideDownTransition(nextProps);
- break;
- case 'push':
- this.pushTransition(nextProps);
- break;
- case 'pop':
- this.popTransition(nextProps);
- break;
- default:
- break;
+ switch (nextProps.name) {
+ case 'slide-up':
+ this.slideUpTransition(nextProps);
+ break;
+ case 'slide-down':
+ this.slideDownTransition(nextProps);
+ break;
+ case 'push':
+ this.pushTransition(nextProps);
+ break;
+ case 'pop':
+ this.popTransition(nextProps);
+ break;
+ default:
+ break;
}
}
onFinishedAnimation() {
this.setState({
childrenAnimation: getStyles().allowPointerEventsStyle,
- previousChildren: null
+ previousChildren: null,
});
}
slideUpTransition(nextProps: TransitionContainerProps) {
const currentTranslationValue = Animated.createValue(this.state.dimensions.height);
- this.setState({
- previousChildren: this.props.children,
- childrenAnimation: Styles.createAnimatedViewStyle({
- pointerEvents: 'none',
- zIndex: 1,
- transform: [{ translateY: currentTranslationValue }]
- }),
- previousChildrenAnimation: Styles.createAnimatedViewStyle({
- pointerEvents: 'none',
- zIndex: 0,
- transform: [{ translateY: 0 }]
- }),
- }, () => {
- Animated.timing(currentTranslationValue, {
- toValue: 0,
- easing: Animated.Easing.InOut(),
- duration: nextProps.duration,
- }).start(() => this.onFinishedAnimation());
- });
+ this.setState(
+ {
+ previousChildren: this.props.children,
+ childrenAnimation: Styles.createAnimatedViewStyle({
+ pointerEvents: 'none',
+ zIndex: 1,
+ transform: [{ translateY: currentTranslationValue }],
+ }),
+ previousChildrenAnimation: Styles.createAnimatedViewStyle({
+ pointerEvents: 'none',
+ zIndex: 0,
+ transform: [{ translateY: 0 }],
+ }),
+ },
+ () => {
+ Animated.timing(currentTranslationValue, {
+ toValue: 0,
+ easing: Animated.Easing.InOut(),
+ duration: nextProps.duration,
+ }).start(() => this.onFinishedAnimation());
+ },
+ );
}
slideDownTransition(nextProps: TransitionContainerProps) {
const previousTranslationValue = Animated.createValue(0);
- this.setState({
- previousChildren: this.props.children,
- childrenAnimation: Styles.createAnimatedViewStyle({
- pointerEvents: 'none',
- zIndex: 0,
- transform: [{ translateY: 0 }]
- }),
- previousChildrenAnimation: Styles.createAnimatedViewStyle({
- pointerEvents: 'none',
- zIndex: 1,
- transform: [{ translateY: previousTranslationValue }]
- }),
- }, () => {
- Animated.timing(previousTranslationValue, {
- toValue: this.state.dimensions.height,
- easing: Animated.Easing.InOut(),
- duration: nextProps.duration,
- }).start(() => this.onFinishedAnimation());
- });
+ this.setState(
+ {
+ previousChildren: this.props.children,
+ childrenAnimation: Styles.createAnimatedViewStyle({
+ pointerEvents: 'none',
+ zIndex: 0,
+ transform: [{ translateY: 0 }],
+ }),
+ previousChildrenAnimation: Styles.createAnimatedViewStyle({
+ pointerEvents: 'none',
+ zIndex: 1,
+ transform: [{ translateY: previousTranslationValue }],
+ }),
+ },
+ () => {
+ Animated.timing(previousTranslationValue, {
+ toValue: this.state.dimensions.height,
+ easing: Animated.Easing.InOut(),
+ duration: nextProps.duration,
+ }).start(() => this.onFinishedAnimation());
+ },
+ );
}
pushTransition(nextProps: TransitionContainerProps) {
const currentTranslationValue = Animated.createValue(this.state.dimensions.width);
const previousTranslationValue = Animated.createValue(0);
- this.setState({
- previousChildren: this.props.children,
- childrenAnimation: Styles.createAnimatedViewStyle({
- pointerEvents: 'none',
- zIndex: 1,
- transform: [{ translateX: currentTranslationValue }]
- }),
- previousChildrenAnimation: Styles.createAnimatedViewStyle({
- pointerEvents: 'none',
- zIndex: 0,
- transform: [{ translateX: previousTranslationValue }]
- }),
- }, () => {
- const compositeAnimation = Animated.parallel([
- Animated.timing(currentTranslationValue, {
- toValue: 0,
- easing: Animated.Easing.InOut(),
- duration: nextProps.duration,
+ this.setState(
+ {
+ previousChildren: this.props.children,
+ childrenAnimation: Styles.createAnimatedViewStyle({
+ pointerEvents: 'none',
+ zIndex: 1,
+ transform: [{ translateX: currentTranslationValue }],
}),
- Animated.timing(previousTranslationValue, {
- toValue: - this.state.dimensions.width / 2,
- easing: Animated.Easing.InOut(),
- duration: nextProps.duration,
- })
- ]);
- compositeAnimation.start(() => this.onFinishedAnimation());
- });
+ previousChildrenAnimation: Styles.createAnimatedViewStyle({
+ pointerEvents: 'none',
+ zIndex: 0,
+ transform: [{ translateX: previousTranslationValue }],
+ }),
+ },
+ () => {
+ const compositeAnimation = Animated.parallel([
+ Animated.timing(currentTranslationValue, {
+ toValue: 0,
+ easing: Animated.Easing.InOut(),
+ duration: nextProps.duration,
+ }),
+ Animated.timing(previousTranslationValue, {
+ toValue: -this.state.dimensions.width / 2,
+ easing: Animated.Easing.InOut(),
+ duration: nextProps.duration,
+ }),
+ ]);
+ compositeAnimation.start(() => this.onFinishedAnimation());
+ },
+ );
}
popTransition(nextProps: TransitionContainerProps) {
- const currentTranslationValue = Animated.createValue(- this.state.dimensions.width / 2 );
+ const currentTranslationValue = Animated.createValue(-this.state.dimensions.width / 2);
const previousTranslationValue = Animated.createValue(0);
- this.setState({
- previousChildren: this.props.children,
- childrenAnimation: Styles.createAnimatedViewStyle({
- pointerEvents: 'none',
- zIndex: 0,
- transform: [{ translateX: currentTranslationValue }]
- }),
- previousChildrenAnimation: Styles.createAnimatedViewStyle({
- pointerEvents: 'none',
- zIndex: 1,
- transform: [{ translateX: previousTranslationValue }]
- }),
- }, () => {
- const compositeAnimation = Animated.parallel([
- Animated.timing(currentTranslationValue, {
- toValue: 0,
- easing: Animated.Easing.InOut(),
- duration: nextProps.duration,
+ this.setState(
+ {
+ previousChildren: this.props.children,
+ childrenAnimation: Styles.createAnimatedViewStyle({
+ pointerEvents: 'none',
+ zIndex: 0,
+ transform: [{ translateX: currentTranslationValue }],
}),
- Animated.timing(previousTranslationValue, {
- toValue: this.state.dimensions.width,
- easing: Animated.Easing.InOut(),
- duration: nextProps.duration,
- })
- ]);
- compositeAnimation.start(() => this.onFinishedAnimation());
- });
+ previousChildrenAnimation: Styles.createAnimatedViewStyle({
+ pointerEvents: 'none',
+ zIndex: 1,
+ transform: [{ translateX: previousTranslationValue }],
+ }),
+ },
+ () => {
+ const compositeAnimation = Animated.parallel([
+ Animated.timing(currentTranslationValue, {
+ toValue: 0,
+ easing: Animated.Easing.InOut(),
+ duration: nextProps.duration,
+ }),
+ Animated.timing(previousTranslationValue, {
+ toValue: this.state.dimensions.width,
+ easing: Animated.Easing.InOut(),
+ duration: nextProps.duration,
+ }),
+ ]);
+ compositeAnimation.start(() => this.onFinishedAnimation());
+ },
+ );
}
render() {
const { children } = this.props;
const { previousChildren, childrenAnimation, previousChildrenAnimation } = this.state;
return (
- <View style={ getStyles().transitionContainerStyle }>
- { previousChildren &&
- (<Animated.View key={ previousChildren && previousChildren.key }
+ <View style={getStyles().transitionContainerStyle}>
+ {previousChildren && (
+ <Animated.View
+ key={previousChildren && previousChildren.key}
style={[getStyles().animationDefaultStyle, previousChildrenAnimation]}>
- { previousChildren }
- </Animated.View>) }
+ {previousChildren}
+ </Animated.View>
+ )}
- <Animated.View key={ children.key } style={[getStyles().animationDefaultStyle, childrenAnimation]}>
- { children }
+ <Animated.View
+ key={children.key}
+ style={[getStyles().animationDefaultStyle, childrenAnimation]}>
+ {children}
</Animated.View>
-
</View>
);
}
-} \ No newline at end of file
+}
diff --git a/app/components/TransitionContainerStyles.android.js b/app/components/TransitionContainerStyles.android.js
index d335eea680..b234ff4be0 100644
--- a/app/components/TransitionContainerStyles.android.js
+++ b/app/components/TransitionContainerStyles.android.js
@@ -6,21 +6,31 @@ import { log } from '../lib/platform';
const dimensions = UserInterface.measureWindow();
let menuBarHeight;
-MobileAppBridge.getMenuBarHeight().then(_response => {menuBarHeight = _response;}).catch(e => {
- log.error('Failed getting menuBarHeight:', e);
-});
+MobileAppBridge.getMenuBarHeight()
+ .then((_response) => {
+ menuBarHeight = _response;
+ })
+ .catch((e) => {
+ log.error('Failed getting menuBarHeight:', e);
+ });
export default () => {
return {
- animationDefaultStyle: Styles.createAnimatedViewStyle({
- position: 'absolute',
- width: dimensions.width,
- height: dimensions.height - menuBarHeight + 24,
- }, false),
+ animationDefaultStyle: Styles.createAnimatedViewStyle(
+ {
+ position: 'absolute',
+ width: dimensions.width,
+ height: dimensions.height - menuBarHeight + 24,
+ },
+ false,
+ ),
allowPointerEventsStyle: null,
- transitionContainerStyle: Styles.createViewStyle({
- width: dimensions.width,
- height: dimensions.height - menuBarHeight + 24, //TODO: Remove ugly hack since it seems that at least my LG is seems hard to find the real display area ... Probably needs to be fixed for some versions or models
- }, false)
+ transitionContainerStyle: Styles.createViewStyle(
+ {
+ width: dimensions.width,
+ height: dimensions.height - menuBarHeight + 24, //TODO: Remove ugly hack since it seems that at least my LG is seems hard to find the real display area ... Probably needs to be fixed for some versions or models
+ },
+ false,
+ ),
};
-}; \ No newline at end of file
+};
diff --git a/app/components/TransitionContainerStyles.js b/app/components/TransitionContainerStyles.js
index eb03570d46..c6510c0600 100644
--- a/app/components/TransitionContainerStyles.js
+++ b/app/components/TransitionContainerStyles.js
@@ -14,9 +14,9 @@ const styles = {
transitionContainerStyle: Styles.createViewStyle({
width: dimensions.width,
height: dimensions.height,
- })
+ }),
};
export default () => {
return styles;
-}; \ No newline at end of file
+};
diff --git a/app/components/styled/AppButton.js b/app/components/styled/AppButton.js
index 59cba4eefb..f54bd18024 100644
--- a/app/components/styled/AppButton.js
+++ b/app/components/styled/AppButton.js
@@ -15,59 +15,60 @@ class BaseButton extends Component {
state = { hovered: false };
- textStyle = () => this.state.hovered ? styles.white80 : styles.white;
- iconStyle = () => this.state.hovered ? styles.white80 : styles.white;
- backgroundStyle = () => this.state.hovered ? styles.white80 : styles.white;
+ textStyle = () => (this.state.hovered ? styles.white80 : styles.white);
+ iconStyle = () => (this.state.hovered ? styles.white80 : styles.white);
+ backgroundStyle = () => (this.state.hovered ? styles.white80 : styles.white);
- onHoverStart = () => !this.props.disabled ? this.setState({ hovered: true }) : null;
- onHoverEnd = () => !this.props.disabled ? this.setState({ hovered: false }) : null;
+ onHoverStart = () => (!this.props.disabled ? this.setState({ hovered: true }) : null);
+ onHoverEnd = () => (!this.props.disabled ? this.setState({ hovered: false }) : null);
render() {
const { children, ...otherProps } = this.props;
return (
- <Button style={[ styles.common, this.backgroundStyle() ]}
+ <Button
+ style={[styles.common, this.backgroundStyle()]}
onHoverStart={this.onHoverStart}
onHoverEnd={this.onHoverEnd}
{...otherProps}>
- {
- React.Children.map(children, (node) => {
- if (React.isValidElement(node)) {
- let updatedProps = {};
+ {React.Children.map(children, (node) => {
+ if (React.isValidElement(node)) {
+ let updatedProps = {};
- if(node.type.name === 'Label') {
- updatedProps = { style: [styles.label, this.textStyle()]};
- }
-
- if(node.type.name === 'Img') {
- updatedProps = { tintColor:'currentColor', style: [styles.icon, this.iconStyle()]};
- }
+ if (node.type.name === 'Label') {
+ updatedProps = { style: [styles.label, this.textStyle()] };
+ }
- return React.cloneElement(node, updatedProps);
- } else {
- return <Label style={[styles.label, this.textStyle()]}>{children}</Label>;
+ if (node.type.name === 'Img') {
+ updatedProps = { tintColor: 'currentColor', style: [styles.icon, this.iconStyle()] };
}
- })
- }
+
+ return React.cloneElement(node, updatedProps);
+ } else {
+ return <Label style={[styles.label, this.textStyle()]}>{children}</Label>;
+ }
+ })}
</Button>
);
}
}
export class RedButton extends BaseButton {
- backgroundStyle = () => this.state.hovered ? styles.redHover : styles.red;
+ backgroundStyle = () => (this.state.hovered ? styles.redHover : styles.red);
}
export class GreenButton extends BaseButton {
- backgroundStyle = () => this.state.hovered ? styles.greenHover : styles.green;
+ backgroundStyle = () => (this.state.hovered ? styles.greenHover : styles.green);
}
export class BlueButton extends BaseButton {
- backgroundStyle = () => this.state.hovered ? styles.blueHover : styles.blue;
+ backgroundStyle = () => (this.state.hovered ? styles.blueHover : styles.blue);
}
export class TransparentButton extends BaseButton {
- backgroundStyle = () => this.state.hovered ? blurStyles.transparentHover : blurStyles.transparent;
+ backgroundStyle = () =>
+ this.state.hovered ? blurStyles.transparentHover : blurStyles.transparent;
}
export class RedTransparentButton extends BaseButton {
- backgroundStyle = () => this.state.hovered ? blurStyles.redTransparentHover : blurStyles.redTransparent;
-} \ No newline at end of file
+ backgroundStyle = () =>
+ this.state.hovered ? blurStyles.redTransparentHover : blurStyles.redTransparent;
+}
diff --git a/app/components/styled/AppButtonStyles.js b/app/components/styled/AppButtonStyles.js
index 477a0cc54a..6049f227d5 100644
--- a/app/components/styled/AppButtonStyles.js
+++ b/app/components/styled/AppButtonStyles.js
@@ -4,42 +4,42 @@ import { createViewStyles, createTextStyles } from '../../lib/styles';
export default {
...createViewStyles({
- red:{
+ red: {
backgroundColor: colors.red95,
},
redHover: {
backgroundColor: colors.red,
},
- green:{
+ green: {
backgroundColor: colors.green,
},
- greenHover:{
+ greenHover: {
backgroundColor: colors.green90,
},
- blue:{
+ blue: {
backgroundColor: colors.blue80,
},
- blueHover:{
+ blueHover: {
backgroundColor: colors.blue60,
},
- white80:{
+ white80: {
color: colors.white80,
},
white: {
color: colors.white,
},
- icon:{
+ icon: {
position: 'absolute',
alignSelf: 'flex-end',
right: 8,
marginLeft: 8,
},
- iconTransparent:{
+ iconTransparent: {
position: 'absolute',
alignSelf: 'flex-end',
right: 42,
},
- common:{
+ common: {
paddingTop: 9,
paddingLeft: 9,
paddingRight: 9,
@@ -56,7 +56,7 @@ export default {
},
}),
...createTextStyles({
- label:{
+ label: {
alignSelf: 'center',
fontFamily: 'DINPro',
fontSize: 20,
@@ -65,4 +65,4 @@ export default {
flex: 1,
},
}),
-}; \ No newline at end of file
+};
diff --git a/app/components/styled/BlurAppButtonStyles.android.js b/app/components/styled/BlurAppButtonStyles.android.js
index 9243a28729..c39e44cdd5 100644
--- a/app/components/styled/BlurAppButtonStyles.android.js
+++ b/app/components/styled/BlurAppButtonStyles.android.js
@@ -4,17 +4,17 @@ import { createViewStyles } from '../../lib/styles';
export default {
...createViewStyles({
- transparent:{
+ transparent: {
backgroundColor: colors.white20,
},
- transparentHover:{
+ transparentHover: {
backgroundColor: colors.white40,
},
- redTransparent:{
+ redTransparent: {
backgroundColor: colors.red40,
},
- redTransparentHover:{
+ redTransparentHover: {
backgroundColor: colors.red45,
},
- })
-}; \ No newline at end of file
+ }),
+};
diff --git a/app/components/styled/BlurAppButtonStyles.js b/app/components/styled/BlurAppButtonStyles.js
index 9e7b213754..72d5398ea8 100644
--- a/app/components/styled/BlurAppButtonStyles.js
+++ b/app/components/styled/BlurAppButtonStyles.js
@@ -4,21 +4,21 @@ import { createViewStyles } from '../../lib/styles';
export default {
...createViewStyles({
- transparent:{
+ transparent: {
backgroundColor: colors.white20,
backdropFilter: 'blur(4px)',
},
- transparentHover:{
+ transparentHover: {
backgroundColor: colors.white40,
backdropFilter: 'blur(4px)',
},
- redTransparent:{
+ redTransparent: {
backgroundColor: colors.red40,
backdropFilter: 'blur(4px)',
},
- redTransparentHover:{
+ redTransparentHover: {
backgroundColor: colors.red45,
backdropFilter: 'blur(4px)',
},
- })
-}; \ No newline at end of file
+ }),
+};
diff --git a/app/components/styled/CellButton.js b/app/components/styled/CellButton.js
index 1a0e055b01..f0251c942e 100644
--- a/app/components/styled/CellButton.js
+++ b/app/components/styled/CellButton.js
@@ -9,7 +9,7 @@ import { createViewStyles, createTextStyles } from '../../lib/styles';
const styles = {
...createViewStyles({
- cell:{
+ cell: {
backgroundColor: colors.blue80,
paddingTop: 14,
paddingBottom: 14,
@@ -21,19 +21,19 @@ const styles = {
alignItems: 'center',
alignContent: 'center',
},
- blue:{
+ blue: {
backgroundColor: colors.blue80,
},
- blueHover:{
+ blueHover: {
backgroundColor: colors.blue60,
},
- white40:{
+ white40: {
color: colors.white40,
},
- white60:{
+ white60: {
color: colors.white60,
},
- white80:{
+ white80: {
color: colors.white80,
},
white: {
@@ -45,7 +45,7 @@ const styles = {
},
}),
...createTextStyles({
- label:{
+ label: {
color: colors.white,
alignSelf: 'center',
fontFamily: 'DINPro',
@@ -55,7 +55,7 @@ const styles = {
flex: 1,
marginLeft: 8,
},
- subtext:{
+ subtext: {
color: colors.white60,
fontFamily: 'Open Sans',
fontSize: 13,
@@ -69,12 +69,11 @@ const styles = {
export class SubText extends Text {}
export class Label extends Text {}
-
type CellButtonProps = {
children?: React.Node,
disabled?: boolean,
cellHoverStyle?: Types.ViewStyle,
- style?: Types.ViewStyle
+ style?: Types.ViewStyle,
};
type State = { hovered: boolean };
@@ -82,44 +81,55 @@ type State = { hovered: boolean };
export default class CellButton extends Component<CellButtonProps, State> {
state = { hovered: false };
- textStyle = (cellHoverStyle?: Types.ViewStyle) => this.state.hovered ? cellHoverStyle : null;
- iconStyle = (cellHoverStyle?: Types.ViewStyle) => this.state.hovered ? cellHoverStyle : null;
- subtextStyle = (cellHoverStyle?: Types.ViewStyle) => this.state.hovered ? cellHoverStyle : null;
- backgroundStyle = (cellHoverStyle?: Types.ViewStyle) => this.state.hovered ? cellHoverStyle || styles.blueHover : null;
+ textStyle = (cellHoverStyle?: Types.ViewStyle) => (this.state.hovered ? cellHoverStyle : null);
+ iconStyle = (cellHoverStyle?: Types.ViewStyle) => (this.state.hovered ? cellHoverStyle : null);
+ subtextStyle = (cellHoverStyle?: Types.ViewStyle) => (this.state.hovered ? cellHoverStyle : null);
+ backgroundStyle = (cellHoverStyle?: Types.ViewStyle) =>
+ this.state.hovered ? cellHoverStyle || styles.blueHover : null;
- onHoverStart = () => !this.props.disabled ? this.setState({ hovered: true }) : null;
- onHoverEnd = () => !this.props.disabled ? this.setState({ hovered: false }) : null;
+ onHoverStart = () => (!this.props.disabled ? this.setState({ hovered: true }) : null);
+ onHoverEnd = () => (!this.props.disabled ? this.setState({ hovered: false }) : null);
render() {
const { children, style, cellHoverStyle, ...otherProps } = this.props;
return (
- <Button style={[ styles.cell, style, this.backgroundStyle(cellHoverStyle) ]}
+ <Button
+ style={[styles.cell, style, this.backgroundStyle(cellHoverStyle)]}
onHoverStart={this.onHoverStart}
onHoverEnd={this.onHoverEnd}
{...otherProps}>
- {
- React.Children.map(children, (node) => {
- if (React.isValidElement(node)) {
- let updatedProps = {};
-
- if(node.type.name === 'Label') {
- updatedProps = { style: [styles.label, node.props.style, this.textStyle(node.props.cellHoverStyle)]};
- }
+ {React.Children.map(children, (node) => {
+ if (React.isValidElement(node)) {
+ let updatedProps = {};
- if(node.type.name === 'Img') {
- updatedProps = { tintColor:'currentColor', style: [styles.icon, node.props.style, this.iconStyle(node.props.cellHoverStyle)]};
- }
+ if (node.type.name === 'Label') {
+ updatedProps = {
+ style: [styles.label, node.props.style, this.textStyle(node.props.cellHoverStyle)],
+ };
+ }
- if(node.type.name === 'SubText') {
- updatedProps = { style: [styles.subtext, node.props.style, this.subtextStyle(node.props.cellHoverStyle)]};
- }
+ if (node.type.name === 'Img') {
+ updatedProps = {
+ tintColor: 'currentColor',
+ style: [styles.icon, node.props.style, this.iconStyle(node.props.cellHoverStyle)],
+ };
+ }
- return React.cloneElement(node, updatedProps);
- } else if (node){
- return <Label style={[styles.label, this.textStyle()]}>{children}</Label>;
+ if (node.type.name === 'SubText') {
+ updatedProps = {
+ style: [
+ styles.subtext,
+ node.props.style,
+ this.subtextStyle(node.props.cellHoverStyle),
+ ],
+ };
}
- })
- }
+
+ return React.cloneElement(node, updatedProps);
+ } else if (node) {
+ return <Label style={[styles.label, this.textStyle()]}>{children}</Label>;
+ }
+ })}
</Button>
);
}
diff --git a/app/components/styled/index.js b/app/components/styled/index.js
index 7efeb28389..6582da5e77 100644
--- a/app/components/styled/index.js
+++ b/app/components/styled/index.js
@@ -2,7 +2,13 @@
import { Button } from './Button';
import CellButton, { Label, SubText } from './CellButton';
-import { RedButton, GreenButton, BlueButton, TransparentButton, RedTransparentButton } from './AppButton';
+import {
+ RedButton,
+ GreenButton,
+ BlueButton,
+ TransparentButton,
+ RedTransparentButton,
+} from './AppButton';
export {
Button,