// @flow import * as React from 'react'; 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 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; }; type State = { expanded: Array }; export default class SelectLocation extends React.Component { _selectedCell: ?CellButton; _scrollView: ?CustomScrollbars; state = { expanded: [], }; constructor(props: SelectLocationProps, context?: any) { super(props, context); // set initially expanded country based on relaySettings const relaySettings = this.props.settings.relaySettings; if(relaySettings.normal) { const { location } = relaySettings.normal; if(location === 'any') { // no-op } else if(location.country) { this.state.expanded.push(location.country); } else if(location.city) { this.state.expanded.push(location.city[0]); } } } componentDidMount() { // restore scroll to selected cell const cell = this._selectedCell; const scrollView = this._scrollView; if(scrollView && cell) { //TODO: fix this when repairing the auto-scroll in customscrollbars. //scrollView.scrollToElement(cell, 'middle'); } } render() { return ( Select location this._scrollView = ref }> While connected, your real location is masked with a private and secure location in the selected region { this.props.settings.relayLocations.map((relayCountry) => { return this._renderCountry(relayCountry); }) } ); } _isSelected(selectedLocation: RelayLocation) { const { relaySettings } = this.props.settings; if(relaySettings.normal) { const otherLocation = relaySettings.normal.location; if(selectedLocation.country && otherLocation.country && selectedLocation.country === otherLocation.country) { return true; } 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 false; } _toggleCollapse = (countryCode: string) => { this.setState((state) => { const expanded = state.expanded.slice(); const index = expanded.indexOf(countryCode); 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 ? : ); } _renderCountry(relayCountry: RelayLocationRedux) { const isSelected = this._isSelected({ country: relayCountry.code }); // 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 handleCollapse = (e) => { this._toggleCollapse(relayCountry.code); e.stopPropagation(); }; return ( { this._relayStatusIndicator(relayCountry.hasActiveRelays, isSelected) } { relayCountry.cities.length > 1 ? : null } { relayCountry.cities.length > 1 && ( { relayCountry.cities.map((relayCity) => this._renderCity(relayCountry.code, relayCity)) } ) } ); } _renderCity(countryCode: string, relayCity: RelayLocationCityRedux) { const relayLocation: RelayLocation = { city: [countryCode, relayCity.code] }; const isSelected = this._isSelected(relayLocation); const onRef = isSelected ? (element) => { this._selectedCell = element; } : undefined; const handleSelect = (relayCity.hasActiveRelays && !isSelected) ? () => { this.props.onSelect(relayLocation); } : undefined; return ( { this._relayStatusIndicator(relayCity.hasActiveRelays, isSelected) } ); } }