summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2021-07-21 19:15:07 +0200
committerOskar Nyberg <oskar@mullvad.net>2021-08-17 08:40:52 +0200
commitbd7e76d25f48bd5436144fc767c975a6791e7fd2 (patch)
tree4c4e04753041d94290ecbe2076403692164d2475
parent81e3513d276246e39e42416824374518c6f7b97c (diff)
downloadmullvadvpn-bd7e76d25f48bd5436144fc767c975a6791e7fd2.tar.xz
mullvadvpn-bd7e76d25f48bd5436144fc767c975a6791e7fd2.zip
Add filter by provider button in select location view
-rw-r--r--gui/src/renderer/components/SelectLocation.tsx53
-rw-r--r--gui/src/renderer/components/SelectLocationStyles.tsx37
-rw-r--r--gui/src/renderer/containers/SelectLocationPage.tsx2
3 files changed, 90 insertions, 2 deletions
diff --git a/gui/src/renderer/components/SelectLocation.tsx b/gui/src/renderer/components/SelectLocation.tsx
index a8375a178c..b3226821a0 100644
--- a/gui/src/renderer/components/SelectLocation.tsx
+++ b/gui/src/renderer/components/SelectLocation.tsx
@@ -1,4 +1,5 @@
import React from 'react';
+import { colors } from '../../config.json';
import { LiftedConstraint, RelayLocation } from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
import { IRelayLocationRedux } from '../redux/settings/reducers';
@@ -6,6 +7,7 @@ import { LocationScope } from '../redux/userinterface/reducers';
import BridgeLocations, { SpecialBridgeLocationType } from './BridgeLocations';
import CustomScrollbars from './CustomScrollbars';
import ExitLocations from './ExitLocations';
+import ImageView from './ImageView';
import { Layout } from './Layout';
import LocationList, { LocationSelection, LocationSelectionType } from './LocationList';
import {
@@ -20,8 +22,12 @@ import { ScopeBarItem } from './ScopeBar';
import {
StyledContainer,
StyledContent,
+ StyledFilterIconButton,
+ StyledFilterContainer,
+ StyledFilterMenu,
StyledNavigationBarAttachment,
StyledScopeBar,
+ StyledFilterByProviderButton,
} from './SelectLocationStyles';
import { HeaderSubTitle } from './SettingsHeader';
@@ -33,18 +39,25 @@ interface IProps {
bridgeLocations: IRelayLocationRedux[];
allowBridgeSelection: boolean;
onClose: () => void;
+ onViewFilterByProvider: () => void;
onChangeLocationScope: (location: LocationScope) => void;
onSelectExitLocation: (location: RelayLocation) => void;
onSelectBridgeLocation: (location: RelayLocation) => void;
onSelectClosestToExit: () => void;
}
+interface IState {
+ showFilterMenu: boolean;
+}
+
interface ISelectLocationSnapshot {
scrollPosition: [number, number];
expandedLocations: RelayLocation[];
}
-export default class SelectLocation extends React.Component<IProps> {
+export default class SelectLocation extends React.Component<IProps, IState> {
+ public state = { showFilterMenu: false };
+
private scrollView = React.createRef<CustomScrollbars>();
private spacePreAllocationViewRef = React.createRef<SpacePreAllocationView>();
private selectedExitLocationRef = React.createRef<React.ReactInstance>();
@@ -55,6 +68,8 @@ export default class SelectLocation extends React.Component<IProps> {
private snapshotByScope: { [index: number]: ISelectLocationSnapshot } = {};
+ private filterButtonRef = React.createRef<HTMLDivElement>();
+
public componentDidMount() {
this.scrollToSelectedCell();
}
@@ -92,7 +107,7 @@ export default class SelectLocation extends React.Component<IProps> {
public render() {
return (
- <Layout>
+ <Layout onClick={this.onClickAnywhere}>
<StyledContainer>
<NavigationContainer>
<NavigationBar alwaysDisplayBarTitle={true}>
@@ -104,6 +119,25 @@ export default class SelectLocation extends React.Component<IProps> {
messages.pgettext('select-location-nav', 'Select location')
}
</TitleBarItem>
+
+ <StyledFilterContainer ref={this.filterButtonRef}>
+ <StyledFilterIconButton onClick={this.toggleFilterMenu}>
+ <ImageView
+ source="icon-filter-round"
+ tintColor={colors.white60}
+ tintHoverColor={colors.white80}
+ height={24}
+ width={24}
+ />
+ </StyledFilterIconButton>
+ {this.state.showFilterMenu && (
+ <StyledFilterMenu>
+ <StyledFilterByProviderButton onClick={this.props.onViewFilterByProvider}>
+ {messages.pgettext('select-location-view', 'Filter by provider')}
+ </StyledFilterByProviderButton>
+ </StyledFilterMenu>
+ )}
+ </StyledFilterContainer>
</NavigationItems>
<StyledNavigationBarAttachment>
<HeaderSubTitle>
@@ -232,6 +266,21 @@ export default class SelectLocation extends React.Component<IProps> {
this.spacePreAllocationViewRef.current?.allocate(expandedContentHeight);
this.scrollView.current?.scrollIntoView(locationRect);
};
+
+ private toggleFilterMenu = () => {
+ this.setState((state) => ({
+ showFilterMenu: !state.showFilterMenu,
+ }));
+ };
+
+ private onClickAnywhere = (event: React.MouseEvent<HTMLDivElement>) => {
+ if (
+ this.state.showFilterMenu &&
+ !this.filterButtonRef.current?.contains(event.target as HTMLElement)
+ ) {
+ this.setState({ showFilterMenu: false });
+ }
+ };
}
interface ISpacePreAllocationView {
diff --git a/gui/src/renderer/components/SelectLocationStyles.tsx b/gui/src/renderer/components/SelectLocationStyles.tsx
index 6a3685ffb4..2c317ddddc 100644
--- a/gui/src/renderer/components/SelectLocationStyles.tsx
+++ b/gui/src/renderer/components/SelectLocationStyles.tsx
@@ -1,5 +1,6 @@
import styled from 'styled-components';
import { colors } from '../../config.json';
+import { smallText } from './common-styles';
import { Container } from './Layout';
import { ScopeBar } from './ScopeBar';
@@ -22,3 +23,39 @@ export const StyledNavigationBarAttachment = styled.div({
marginTop: '8px',
paddingHorizontal: '4px',
});
+
+export const StyledFilterContainer = styled.div({
+ position: 'relative',
+});
+
+export const StyledFilterIconButton = styled.button({
+ borderWidth: 0,
+ padding: 0,
+ margin: 0,
+ cursor: 'default',
+ backgroundColor: 'transparent',
+});
+
+export const StyledFilterMenu = styled.div({
+ position: 'absolute',
+ top: 'calc(100% + 4px)',
+ right: '0',
+ borderRadius: '4px',
+ backgroundColor: colors.darkBlue,
+ overflow: 'hidden',
+});
+
+export const StyledFilterByProviderButton = styled.button({
+ ...smallText,
+ borderWidth: 0,
+ margin: 0,
+ cursor: 'default',
+ color: colors.white,
+ padding: '7px 15px',
+ whiteSpace: 'nowrap',
+ borderRadius: 0,
+ backgroundColor: colors.blue,
+ ':hover': {
+ backgroundColor: colors.blue80,
+ },
+});
diff --git a/gui/src/renderer/containers/SelectLocationPage.tsx b/gui/src/renderer/containers/SelectLocationPage.tsx
index b3aab7eb69..7511a75fe1 100644
--- a/gui/src/renderer/containers/SelectLocationPage.tsx
+++ b/gui/src/renderer/containers/SelectLocationPage.tsx
@@ -7,6 +7,7 @@ import RelaySettingsBuilder from '../../shared/relay-settings-builder';
import SelectLocation from '../components/SelectLocation';
import withAppContext, { IAppContext } from '../context';
import { IHistoryProps, withHistory } from '../lib/history';
+import { RoutePath } from '../lib/routes';
import { IReduxState, ReduxDispatch } from '../redux/store';
import userInterfaceActions from '../redux/userinterface/actions';
import { LocationScope } from '../redux/userinterface/reducers';
@@ -45,6 +46,7 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: IHistoryProps & IApp
return {
onClose: () => props.history.dismiss(),
+ onViewFilterByProvider: () => props.history.push(RoutePath.filterByProvider),
onChangeLocationScope: (scope: LocationScope) => {
userInterface.setLocationScope(scope);
},