diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/components/Connect.css | 190 | ||||
| -rw-r--r-- | app/components/Connect.js | 200 | ||||
| -rw-r--r-- | app/components/ConnectStyles.js | 147 |
3 files changed, 246 insertions, 291 deletions
diff --git a/app/components/Connect.css b/app/components/Connect.css deleted file mode 100644 index 592e824ea2..0000000000 --- a/app/components/Connect.css +++ /dev/null @@ -1,190 +0,0 @@ -.connect { - height: 100%; - position: relative; -} - -.connect__map { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 0; -} - -.connect__container { - display: flex; - flex-direction: column; - height: 100%; - position: relative; /* need this for z-index to work to cover map */ - z-index: 1; -} - -.connect__footer { - display: flex; - flex-direction: column; - padding: 42px 24px 24px; -} - -.connect__row + .connect__row{ - margin-top: 16px; -} - -.connect__blocking-container { - color: rgba(255,255,255,0.8); - max-height: 0px; - height: 100%; - width: 100%; - overflow: hidden; - - text-transform: uppercase; - - position: absolute; - border-bottom: 1px solid rgba(255,255,255,0.8); - transition: max-height 0.5s; -} -.connect__blocking-container.show { - max-height: 36px; -} -.connect__blocking-container.hide { - max-height: 0px; - border-bottom: 0px solid rgb(208, 2, 27); - transition: max-height 0.5s, border-bottom 0.1s 0.4s; -} - -.connect__blocking-message { - display: flex; - flex-direction: row; - margin: 8px 20px; - font-family: "Open Sans"; - font-size: 12px; - font-weight: 800; - line-height: 17px; -} - -.connect__blocking-icon { - width: 10px; - height: 10px; - border-radius: 5px; - margin-top: 4px; - margin-right: 8px; - - background-color: rgb(208, 2, 27); -} - -.connect__server { - padding: 7px 12px 9px; - background-color: rgba(255,255,255,0.2); - border-radius: 4px; - display: flex; - flex-direction: row; - align-items: center; - backdrop-filter: blur(4px); -} - -.connect__server-label { - flex: 1 1 auto; - text-align: center; -} - -.connect__server-chevron { - flex: 0 0 auto; - width: 7px; - margin-left: -7px; /* let .connect__server-label extend to occupy the entire space */ -} - -.connect__footer-button { - display: block; - width:100%; - border: 0; - padding: 7px 12px 9px; - border-radius: 4px; - font-family: DINPro; - font-size: 20px; - font-weight: 900; - text-align: center; - line-height: 26px; - color: #FFFFFF; -} - -.connect__status { - padding: 0 24px; - margin-top: 94px; - margin-bottom: auto; -} - -.connect__error-title { - font-family: DINPro; - font-size: 32px; - font-weight: 900; - line-height: 1.25; - color: #fff; - margin-bottom: 8px; -} - -.connect__error-message { - font-family: "Open Sans"; - font-size: 13px; - font-weight: 600; - line-height: normal; - color: #fff; - margin-bottom: 24px; -} - -.connect__status-security { - font-family: "Open Sans"; - font-size: 16px; - font-weight: 800; - line-height: 22px; - margin-bottom: 4px; - color: #FFFFFF; - text-transform: uppercase; -} - -.connect__status-security--unsecured { - color: #D0021B; -} - -.connect__status-security--secure { - color: #44AD4D; -} - -.connect__status-location { - font-family: DINPro; - font-size: 38px; - font-weight: 900; - line-height: 1.16em; - max-height: calc(1.16em * 2); - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - letter-spacing: -0.9px; - color: #FFFFFF; - margin-bottom: 4px; -} - -.connect__status-location-icon { - display: inline-block; - margin-right: 8px; -} - -.connect__status-ipaddress { - font-family: "Open Sans"; - font-size: 16px; - font-weight: 800; - line-height: normal; - color: #FFFFFF; -} - -.connect__status-ipaddress--invisible { - visibility: hidden; -} - -.connect__status-icon { - text-align: center; - margin-bottom: 32px; -} - -.connect__status-icon--hidden { - visibility: hidden; -} diff --git a/app/components/Connect.js b/app/components/Connect.js index 3408e40b8d..632b04ea21 100644 --- a/app/components/Connect.js +++ b/app/components/Connect.js @@ -3,12 +3,15 @@ import moment from 'moment'; import * as React from 'react'; import { Layout, Container, Header } from './Layout'; +import { Text, View, Animated, Styles, Types } from 'reactxp'; +import Img from './Img'; +import { TransparentButton, GreenButton, RedButton, Label } from './styled'; +import styles from './ConnectStyles'; +import { colors } from '../config'; + import { BackendError } from '../lib/backend'; import Map from './Map'; -import ExternalLinkSVG from '../assets/images/icon-extLink.svg'; -import ChevronRightSVG from '../assets/images/icon-chevron.svg'; - import type { HeaderBarStyle } from './HeaderBar'; import type { ConnectionReduxState } from '../redux/connection/reducers'; @@ -66,7 +69,7 @@ export default class Connect extends React.Component<ConnectProps, ConnectState> return ( <Layout> - <Header style={ this.headerStyle() } showSettings={ true } onSettings={ this.props.onSettings } /> + <Header style={ this.headerStyle() } showSettings={ true } onSettings={ this.props.onSettings } testName='header'/> <Container> { child } </Container> @@ -76,28 +79,28 @@ export default class Connect extends React.Component<ConnectProps, ConnectState> renderError(error: BackendError) { return ( - <div className="connect"> - <div className="connect__status"> - <div className="connect__status-icon"> - <img src="./assets/images/icon-fail.svg" alt="" /> - </div> - <div className="connect__error-title"> + <View style={styles.connect}> + <View style={styles.status}> + <View style={styles.status_icon}> + <Img source="icon-fail" height="60" width="60" alt="" /> + </View> + <View style={styles.error_title}> { error.title } - </div> - <div className="connect__error-message"> + </View> + <View style={styles.error_message}> { error.message } - </div> + </View> { error.type === 'NO_CREDIT' ? - <div> - <button className="button button--positive" onClick={ this.onExternalLink.bind(this, 'purchase') }> - <span className="button-label">Buy more time</span> - <ExternalLinkSVG className="button-icon button-icon--16" /> - </button> - </div> + <View> + <GreenButton onPress={ this.onExternalLink.bind(this, 'purchase') }> + <Label>Buy more time</Label> + <Img source='icon-extLink' height='16' width='16' /> + </GreenButton> + </View> : null } - </div> - </div> + </View> + </View> ); } @@ -150,20 +153,23 @@ export default class Connect extends React.Component<ConnectProps, ConnectState> } return ( - <div className="connect"> - <div className="connect__map"> + <View style={styles.connect}> + <View style={styles.map}> <Map style={{ width: '100%', height: '100%' }} { ...this._getMapProps() } /> - </div> - <div className="connect__container"> + </View> + <View style={styles.container}> { this._renderIsBlockingInternetMessage() } - <div className="connect__status"> + <View style={styles.status}> { /* show spinner when connecting */ } - <div className={ this.spinnerClass() }> - <img src="./assets/images/icon-spinner.svg" alt="" ref={ this._updateMapOffset } /> - </div> + { isConnecting ? + <View style={ styles.status_icon }> + <Img source="icon-spinner" height="60" width="60" alt="" ref={ this._updateMapOffset } /> + </View> + : null + } - <div className={ this.networkSecurityClass() }>{ this.networkSecurityMessage() }</div> + <View style={ this.networkSecurityStyle() } testName='networkSecurityMessage'>{ this.networkSecurityMessage() }</View> { /* ********************************** @@ -173,19 +179,19 @@ export default class Connect extends React.Component<ConnectProps, ConnectState> { /* location when connecting or disconnected */ } { isConnecting || isDisconnected ? - <div className="connect__status-location"> - <span>{ this.props.connection.country }</span> - </div> + <Text style={styles.status_location} testName='location'> + { this.props.connection.country } + </Text> : null } { /* location when connected */ } { isConnected ? - <div className="connect__status-location"> + <Text style={styles.status_location} testName='location'> { this.props.connection.city } { this.props.connection.city && <br/> } { this.props.connection.country } - </div> + </Text> :null } @@ -195,15 +201,15 @@ export default class Connect extends React.Component<ConnectProps, ConnectState> ********************************** */ } - <div className={ this.ipAddressClass() } onClick={ this.onIPAddressClick.bind(this) }> + <Text style={ this.ipAddressStyle() } onPress={ this.onIPAddressClick.bind(this) }> { (isConnected || isDisconnected) ? ( - <span>{ + <Text testName='ipAddress'>{ this.state.showCopyIPMessage ? 'IP copied to clipboard!' : this.props.connection.ip - }</span>) : null } - </div> - </div> + }</Text>) : null } + </Text> + </View> { /* @@ -214,46 +220,31 @@ export default class Connect extends React.Component<ConnectProps, ConnectState> { /* footer when disconnected */ } { isDisconnected ? - <div className="connect__footer"> - <div className="connect__row"> - <button className="connect__server button button--neutral button--blur" onClick={ this.props.onSelectLocation }> - <div className="connect__server-label">{ this.props.selectedRelayName }</div> - <div className="connect__server-chevron"><ChevronRightSVG /></div> - </button> - </div> - - <div className="connect__row"> - <button className="button button--positive" onClick={ this.props.onConnect }>Secure my connection</button> - </div> - </div> + <View style={styles.footer}> + <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> + </View> : null } { /* footer when connecting */ } { isConnecting ? - <div className="connect__footer"> - <div className="connect__row"> - <button className="button button--neutral button--blur" onClick={ this.props.onSelectLocation }>Switch location</button> - </div> - - <div className="connect__row"> - <button className="button button--negative-light button--blur" onClick={ this.props.onDisconnect }>Cancel</button> - </div> - </div> + <View style={styles.footer}> + <TransparentButton onPress={ this.props.onSelectLocation }>Switch location</TransparentButton> + <RedButton onPress={ this.props.onDisconnect }>Cancel</RedButton> + </View> : null } { /* footer when connected */ } { isConnected ? - <div className="connect__footer"> - <div className="connect__row"> - <button className="button button--neutral button--blur" onClick={ this.props.onSelectLocation }>Switch location</button> - </div> - - <div className="connect__row"> - <button className="button button--negative-light button--blur" onClick={ this.props.onDisconnect }>Disconnect</button> - </div> - </div> + <View style={styles.footer}> + <TransparentButton onPress={ this.props.onSelectLocation }>Switch location</TransparentButton> + <RedButton onPress={ this.props.onDisconnect } testName='disconnect'>Disconnect</RedButton> + </View> : null } @@ -263,23 +254,39 @@ export default class Connect extends React.Component<ConnectProps, ConnectState> ********************************** */ } - </div> - </div> + </View> + </View> ); } + _getBlockingMessageAnimation(animationValue: Animated.Value, toValue: number){ + return Animated.timing(animationValue, { + toValue: toValue, + easing: Animated.Easing.InOut(), + duration: 250, + useNativeDriver: true, + }); + } + + _renderIsBlockingInternetMessage() { - let animationClass = 'hide'; + let messageHeight = 0; + let messageHeightValue = Animated.createValue(0); if (this.props.connection.status === 'connecting') { - animationClass = 'show'; + messageHeight = styles.blockingMessageHeight; } - return <div className={`connect__blocking-container ${animationClass}`}> - <div className="connect__blocking-message"> - <div className="connect__blocking-icon"> </div> - blocking internet - </div> - </div>; + this._getBlockingMessageAnimation(messageHeightValue, messageHeight).start(); + + return <Animated.View style={ + Styles.createAnimatedViewStyle({ + height: messageHeight, + backgroundColor: colors.blue})} > + <Text style={styles.blocking_message}> + <Text style={styles.blocking_icon}> </Text> + <Text>BLOCKING INTERNET</Text> + </Text> + </Animated.View>; } // Handlers @@ -308,39 +315,30 @@ export default class Connect extends React.Component<ConnectProps, ConnectState> throw new Error('Invalid ConnectionState'); } - networkSecurityClass(): string { - let classes = ['connect__status-security']; + networkSecurityStyle(): Types.Style { + let classes = [styles.status_security]; if(this.props.connection.status === 'connected') { - classes.push('connect__status-security--secure'); + classes.push(styles.status_security__secure); } else if(this.props.connection.status === 'disconnected') { - classes.push('connect__status-security--unsecured'); + classes.push(styles.status_security__unsecured); } - - return classes.join(' '); + return classes; } networkSecurityMessage(): string { switch(this.props.connection.status) { - case 'connected': return 'Secure connection'; - case 'connecting': return 'Creating secure connection'; - default: return 'Unsecured connection'; - } - } - - spinnerClass(): string { - var classes = ['connect__status-icon']; - if(this.props.connection.status !== 'connecting') { - classes.push('connect__status-icon--hidden'); + case 'connected': return 'SECURE CONNECTION'; + case 'connecting': return 'CREATING SECURE CONNECTION'; + default: return 'UNSECURED CONNECTION'; } - return classes.join(' '); } - ipAddressClass(): string { - var classes = ['connect__status-ipaddress']; + ipAddressStyle(): Types.Style { + var classes = [styles.status_ipaddress]; if(this.props.connection.status === 'connecting') { - classes.push('connect__status-ipaddress--invisible'); + classes.push(styles.status_ipaddress__invisible); } - return classes.join(' '); + return classes; } displayError(): ?BackendError { diff --git a/app/components/ConnectStyles.js b/app/components/ConnectStyles.js new file mode 100644 index 0000000000..030d33b07c --- /dev/null +++ b/app/components/ConnectStyles.js @@ -0,0 +1,147 @@ +// @flow +import { createViewStyles, createTextStyles } from '../lib/styles'; +import { colors } from '../config'; + +export default { + ...createViewStyles({ + connect: { + height: '100%', + flex: 1, + }, + map: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + zIndex: 0, + height: '100%', + width: '100%', + }, + container: { + flexDirection: 'column', + flex: 1, + position: 'relative', /* need this for z-index to work to cover map */ + zIndex: 1, + }, + footer:{ + flex: 0, + marginBottom: 16, + }, + blocking_container: { + color: colors.white80, + overflow: 'hidden', + position: 'absolute', + }, + blocking_icon: { + width: 10, + height: 10, + flex: 0, + display: 'flex', + borderRadius: 5, + marginTop: 4, + marginRight: 8, + backgroundColor: colors.red, + }, + server: { + paddingTop: 7, + paddingLeft: 12, + paddingRight: 12, + paddingBottom: 9, + backgroundColor: colors.white20, + borderRadius: 4, + flexDirection: 'row', + alignItems: 'center', + }, + status: { + justifyContent: 'center', + paddingTop: 0, + paddingLeft: 24, + paddingRight: 24, + paddingBottom: 0, + marginTop: 94, + flex: 1, + }, + status_icon: { + alignSelf: 'center', + width: 60, + height: 60, + marginBottom: 32, + }, + }), + ...createTextStyles({ + blocking_message: { + display: 'flex', + flexDirection: 'row', + fontFamily: 'Open Sans', + fontSize: 12, + fontWeight: '800', + lineHeight: 17, + marginTop: 8, + marginLeft: 20, + marginRight: 20, + marginBottom: 8, + color: colors.white60, + backgroundColor: colors.blue, + }, + server_label: { + fontFamily: 'DINPro', + fontSize: 32, + fontWeight: '900', + lineHeight: 44, + letterSpacing: -0.7, + color: colors.white, + marginBottom: 7, + flex:0, + }, + error_title: { + fontFamily: 'DINPro', + fontSize: 32, + fontWeight: '900', + lineHeight: 40, + color: colors.white, + marginBottom: 8, + }, + error_message: { + fontFamily: 'Open Sans', + fontSize: 13, + fontWeight: '600', + color: colors.white, + marginBottom: 24, + }, + status_security: { + fontFamily: 'Open Sans', + fontSize: 16, + fontWeight: '800', + lineHeight: 22, + marginBottom: 4, + color: colors.white, + }, + status_security__secure: { + color: colors.green, + }, + status_security__unsecured: { + color: colors.red, + }, + status_ipaddress: { + fontFamily: 'Open Sans', + fontSize: 16, + fontWeight: '800', + color: colors.white, + }, + status_ipaddress__invisible: { + opacity: 0, + }, + status_location: { + fontFamily: 'DINPro', + fontSize: 38, + fontWeight: '900', + lineHeight: 40, + overflow: 'hidden', + letterSpacing: -0.9, + color: colors.white, + marginBottom: 4, + }, + }), + blockingMessageHeight: 36, +};
\ No newline at end of file |
