diff options
| -rw-r--r-- | app/components/SelectLocation.css | 146 | ||||
| -rw-r--r-- | app/components/SelectLocation.js | 134 | ||||
| -rw-r--r-- | app/components/SelectLocationStyles.js | 88 | ||||
| -rw-r--r-- | test/components/SelectLocation.spec.js | 27 |
4 files changed, 164 insertions, 231 deletions
diff --git a/app/components/SelectLocation.css b/app/components/SelectLocation.css deleted file mode 100644 index 7e107f237f..0000000000 --- a/app/components/SelectLocation.css +++ /dev/null @@ -1,146 +0,0 @@ -.select-location { - background: #192E45; - height: 100%; -} - -.select-location__container { - display: flex; - flex-direction: column; - height: 100%; -} - -.select-location__header { - flex: 0 0 auto; - padding: 40px 24px 16px; - position: relative; /* anchor for close button */ -} - -.select-location__close { - position: absolute; - display: block; - border: 0; - padding: 0; - margin: 0; - width: 24px; - height: 24px; - top: 24px; - left: 12px; - background-color: transparent; - background-image: url(../assets/images/icon-close.svg); - opacity: 0.6; - z-index: 1; /* part of .select-location__container covers the button */ -} - -.select-location__title { - font-family: DINPro; - font-size: 32px; - font-weight: 900; - line-height: 1.25em; - color: #FFFFFF; -} - -.select-location__subtitle { - font-family: "Open Sans"; - font-size: 13px; - font-weight: 600; - line-height: normal; - color: rgba(255,255,255,0.8); - padding: 0 24px 24px; -} - -.select-location__cell { - background-color: rgba(41,71,115,1); - display: flex; - flex-direction: row; - align-items: stretch; -} - -.select-location__cell-content { - padding: 15px 24px; - display: flex; - flex: 1 1 auto; - flex-direction: row; - align-items: center; -} - -.select-location__cell--selectable:hover { - background-color:rgba(41,71,115,0.9); -} - -.select-location__cell--selected, -.select-location__cell--selected:hover { - background-color: #44AD4D; -} - -.select-location__country + .select-location__country { - margin-top: 1px; -} - -.select-location__cell-label { - font-family: DINPro; - font-size: 20px; - font-weight: 900; - line-height: 26px; - color: #FFFFFF; -} - -.select-location__cell-label--inactive { - color: rgba(255, 255, 255, 0.2); -} - -.select-location__cell-icon { - width: 24px; - height: 24px; - flex: 0 0 auto; - margin-right: 8px; - align-items: center; - justify-content: center; - display: flex; - color: #fff; -} - -.select-location__collapse-button { - border: 0; - background: transparent; - padding: 0; - margin: 0 0 0 auto; - display: flex; - align-items: stretch; - padding: 12px; -} - -.select-location__collapse-icon { - color: #fff; -} - -.select-location__sub-cell { - background-color: rgb(36, 57, 84); - padding: 15px 24px 15px 40px; - display: flex; - flex-direction: row; - align-items: center; - margin-top: 1px; -} - -.select-location__sub-cell--selectable:hover { - background-color: rgba(41,71,115,0.9); -} - -.select-location__sub-cell--selected, -.select-location__sub-cell--selected:hover { - background-color: #44AD4D; -} - -.select-location-relay-status { - width: 16px; - height: 16px; - border-radius: 8px; -} - -.select-location-relay-status--inactive { - background: rgba(208, 2, 27, 0.95); -} - -.select-location-relay-status--active { - background: rgba(68, 173, 77, 0.9); -}
\ No newline at end of file diff --git a/app/components/SelectLocation.js b/app/components/SelectLocation.js index 88f1415b01..2f040763ef 100644 --- a/app/components/SelectLocation.js +++ b/app/components/SelectLocation.js @@ -1,12 +1,13 @@ // @flow import * as React from 'react'; -import { Layout, Container, Header } from './Layout'; +import { Layout, Container } from './Layout'; import CustomScrollbars from './CustomScrollbars'; +import { Text, View } from 'reactxp'; +import { Button, CellButton, Label } from './styled'; +import styles from './SelectLocationStyles'; +import Img from './Img'; import Accordion from './Accordion'; -import ChevronDownSVG from '../assets/images/icon-chevron-down.svg'; -import ChevronUpSVG from '../assets/images/icon-chevron-up.svg'; -import TickSVG from '../assets/images/icon-tick.svg'; import type { SettingsReduxState, RelayLocationRedux, RelayLocationCityRedux } from '../redux/settings/reducers'; import type { RelayLocation } from '../lib/ipc-facade'; @@ -22,7 +23,7 @@ type State = { }; export default class SelectLocation extends React.Component<SelectLocationProps, State> { - _selectedCell: ?HTMLElement; + _selectedCell: ?CellButton; _scrollView: ?CustomScrollbars; state = { @@ -50,6 +51,8 @@ export default class SelectLocation extends React.Component<SelectLocationProps, // restore scroll to selected cell const cell = this._selectedCell; const scrollView = this._scrollView; + console.log(scrollView); + console.log(cell); if(scrollView && cell) { scrollView.scrollToElement(cell, 'middle'); @@ -59,29 +62,30 @@ export default class SelectLocation extends React.Component<SelectLocationProps, render() { return ( <Layout> - <Header hidden={ true } style={ 'defaultDark' } /> <Container> - <div className="select-location"> - <button className="select-location__close" onClick={ this.props.onClose } /> - <div className="select-location__container"> - <div className="select-location__header"> - <h2 className="select-location__title">Select location</h2> - </div> + <View style={styles.select_location}> + <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 }> - <div> - <div className="select-location__subtitle"> + <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 - </div> + </Text> { this.props.settings.relayLocations.map((relayCountry) => { return this._renderCountry(relayCountry); }) } - </div> + </View> </CustomScrollbars> - </div> - </div> + </View> + </View> </Container> </Layout> ); @@ -122,9 +126,9 @@ export default class SelectLocation extends React.Component<SelectLocationProps, } _relayStatusIndicator(active: boolean) { - const statusClass = active ? 'select-location-relay-status--active' : 'select-location-relay-status--inactive'; + const statusClass = active ? styles.relay_status__active : styles.relay_status__inactive; - return (<div className={ 'select-location-relay-status ' + statusClass }></div>); + return (<View style={[ styles.relay_status, statusClass ]}></View>); } _renderCountry(relayCountry: RelayLocationRedux) { @@ -142,47 +146,35 @@ export default class SelectLocation extends React.Component<SelectLocationProps, e.stopPropagation(); }; - const countryClass = 'select-location__cell' + - (isSelected ? ' select-location__cell--selected' : '') + - (relayCountry.hasActiveRelays ? ' select-location__cell--selectable' : ''); - - const onRef = isSelected ? (element) => { - this._selectedCell = element; - } : undefined; - return ( - <div key={ relayCountry.code } className="select-location__country"> - <div className={ countryClass } - onClick={ handleSelect } - ref={ onRef }> - <div className="select-location__cell-content"> - - <div className="select-location__cell-icon"> - { isSelected ? - <TickSVG /> : - this._relayStatusIndicator(relayCountry.hasActiveRelays) } - </div> + <View key={ relayCountry.code } style={styles.country}> + <CellButton + style={ isSelected ? styles.cell_selected : null } + onPress={ handleSelect } + disabled={!relayCountry.hasActiveRelays} + testName='country'> - <div className={ 'select-location__cell-label' + - (relayCountry.hasActiveRelays ? '' : ' select-location__cell-label--inactive') }> - { relayCountry.name } - </div> - </div> + { isSelected ? + <Img source='icon-tick' height='24' width='24' /> : + this._relayStatusIndicator(relayCountry.hasActiveRelays) } - { relayCountry.cities.length > 1 && <button type="button" className="select-location__collapse-button" onClick={ handleCollapse }> - { isExpanded ? - <ChevronUpSVG className="select-location__collapse-icon" /> : - <ChevronDownSVG className="select-location__collapse-icon" /> } - </button> } + <Label> + { relayCountry.name } + </Label> - </div> + { relayCountry.cities.length > 1 ? + isExpanded ? + <Img style={styles.collapse_button} onPress={ handleCollapse } source='icon-chevron-up' height='24' width='24' /> : + <Img style={styles.collapse_button} onPress={ handleCollapse } source='icon-chevron-down' height='24' width='24' /> + : null } + </CellButton> { relayCountry.cities.length > 1 && - (<Accordion className="select-location__cities" height={ isExpanded ? 'auto' : 0 }> + (<Accordion height={ isExpanded ? 'auto' : 0 }> { relayCountry.cities.map((relayCity) => this._renderCity(relayCountry.code, relayCity)) } </Accordion>) } - </div> + </View> ); } @@ -191,36 +183,30 @@ export default class SelectLocation extends React.Component<SelectLocationProps, const isSelected = this._isSelected(relayLocation); - const cityClass = 'select-location__sub-cell' + - (isSelected ? ' select-location__sub-cell--selected' : '') + - (relayCity.hasActiveRelays ? ' select-location__sub-cell--selectable' : ''); + const onRef = isSelected ? (element) => { + this._selectedCell = element; + } : undefined; const handleSelect = (relayCity.hasActiveRelays && !isSelected) ? () => { this.props.onSelect(relayLocation); } : undefined; - const onRef = isSelected ? (element) => { - this._selectedCell = element; - } : undefined; - return ( - <div key={ `${countryCode}_${relayCity.code}` } - className={ cityClass } - onClick={ handleSelect } - ref={ onRef }> + <CellButton key={ `${countryCode}_${relayCity.code}` } + onPress={ handleSelect } + disabled={!relayCity.hasActiveRelays} + style={isSelected ? styles.sub_cell__selected : styles.sub_cell} + testName='city' + ref={onRef}> - <div className="select-location__cell-icon"> - { isSelected ? - <TickSVG /> : - this._relayStatusIndicator(relayCity.hasActiveRelays) } - </div> + { isSelected ? + <Img source='icon-tick' height='24' width='24' /> : + this._relayStatusIndicator(relayCity.hasActiveRelays) } - <div className={ 'select-location__cell-label' + - (relayCity.hasActiveRelays ? '' : ' select-location__cell-label--inactive') }> + <Label> { relayCity.name } - </div> - </div> + </Label> + </CellButton> ); } - } diff --git a/app/components/SelectLocationStyles.js b/app/components/SelectLocationStyles.js new file mode 100644 index 0000000000..52f17a58c1 --- /dev/null +++ b/app/components/SelectLocationStyles.js @@ -0,0 +1,88 @@ +// @flow +import { createViewStyles, createTextStyles } from '../lib/styles'; +import { colors } from '../config'; + +export default { + ...createViewStyles({ + select_location: { + backgroundColor: colors.darkBlue, + height: '100%', + }, + container: { + flexDirection: 'column', + flex: 1, + }, + header:{ + flex: 0, + marginBottom: 16, + }, + close: { + marginLeft: 12, + marginTop: 12, + cursor: 'default', + }, + close_icon:{ + width: 24, + height: 24, + flex: 0, + opacity: 0.6, + }, + relay_status: { + width: 16, + height: 16, + borderRadius: 8, + marginLeft: 8, + marginRight: 8, + }, + relay_status__inactive: { + backgroundColor: colors.red95, + }, + relay_status__active: { + backgroundColor: colors.green90, + }, + country: { + flexDirection: 'column', + flex: 0, + }, + collapse_button: { + height: 24, + width: 24, + alignSelf: 'flex-end', + }, + sub_cell: { + paddingLeft: 40, + backgroundColor: colors.blue40, + }, + sub_cell__selected: { + paddingLeft: 40, + backgroundColor: colors.green, + }, + cell_selected: { + backgroundColor: colors.green, + }, + }), + ...createTextStyles({ + title: { + fontFamily: 'DINPro', + fontSize: 32, + fontWeight: '900', + lineHeight: 40, + color: colors.white, + paddingTop: 16, + paddingLeft: 24, + paddingRight: 24, + }, + subtitle: { + fontFamily: 'Open Sans', + fontSize: 13, + fontWeight: '600', + color: colors.white60, + letterSpacing: -0.2, + paddingTop: 0, + paddingLeft: 24, + paddingRight: 24, + paddingBottom: 24, + flex: 0, + }, + }), +};
\ No newline at end of file diff --git a/test/components/SelectLocation.spec.js b/test/components/SelectLocation.spec.js index 59a8dc9770..4e2265c6dd 100644 --- a/test/components/SelectLocation.spec.js +++ b/test/components/SelectLocation.spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import * as React from 'react'; -import ReactTestUtils, { Simulate } from 'react-dom/test-utils'; +import { shallow } from 'enzyme'; import SelectLocation from '../../app/components/SelectLocation'; import type { SettingsReduxState } from '../../app/redux/settings/reducers'; @@ -48,7 +48,7 @@ describe('components/SelectLocation', () => { }; const render = (props: SelectLocationProps) => { - return ReactTestUtils.renderIntoDocument( + return shallow( <SelectLocation { ...props } /> ); }; @@ -57,11 +57,8 @@ describe('components/SelectLocation', () => { const props = makeProps(state, { onClose: () => done() }); - const domNode = ReactTestUtils.findRenderedDOMComponentWithClass(render(props), 'select-location__close'); - // See: https://github.com/facebook/flow/pull/5841 - if(domNode) { - Simulate.click(domNode); - } + const node = getComponent(render(props), 'close'); + click(node); }); it('should call select callback for country', (done) => { @@ -77,9 +74,9 @@ describe('components/SelectLocation', () => { } } }); - const elements = ReactTestUtils.scryRenderedDOMComponentsWithClass(render(props), 'select-location__cell'); + const elements = getComponent(render(props), 'country'); expect(elements).to.have.length(1); - Simulate.click(elements[0]); + click(elements.at(0)); }); it('should call select callback for city', (done) => { @@ -95,9 +92,17 @@ describe('components/SelectLocation', () => { } } }); - const elements = ReactTestUtils.scryRenderedDOMComponentsWithClass(render(props), 'select-location__sub-cell'); + const elements = getComponent(render(props), 'city'); expect(elements).to.have.length(2); - Simulate.click(elements[0]); + click(elements.at(0)); }); }); + +function getComponent(container, testName) { + return container.findWhere( n => n.prop('testName') === testName); +} + +function click(component) { + component.prop('onPress')(); +} |
