summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/renderer/components/SelectLocation.tsx99
-rw-r--r--gui/src/renderer/components/SelectLocationStyles.tsx6
-rw-r--r--gui/src/renderer/containers/SelectLocationPage.tsx7
3 files changed, 79 insertions, 33 deletions
diff --git a/gui/src/renderer/components/SelectLocation.tsx b/gui/src/renderer/components/SelectLocation.tsx
index cb73eeb2f0..34059f3e85 100644
--- a/gui/src/renderer/components/SelectLocation.tsx
+++ b/gui/src/renderer/components/SelectLocation.tsx
@@ -2,7 +2,12 @@ import React from 'react';
import { sprintf } from 'sprintf-js';
import { colors } from '../../config.json';
-import { LiftedConstraint, RelayLocation, TunnelProtocol } from '../../shared/daemon-rpc-types';
+import {
+ LiftedConstraint,
+ Ownership,
+ RelayLocation,
+ TunnelProtocol,
+} from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
import { IRelayLocationRedux } from '../redux/settings/reducers';
import BridgeLocations, { SpecialBridgeLocationType } from './BridgeLocations';
@@ -25,13 +30,13 @@ import {
} from './NavigationBar';
import { ScopeBarItem } from './ScopeBar';
import {
- StyledClearProvidersButton,
+ StyledClearFilterButton,
StyledContainer,
StyledContent,
+ StyledFilter,
StyledFilterIconButton,
+ StyledFilterRow,
StyledNavigationBarAttachment,
- StyledProviderCountRow,
- StyledProvidersCount,
StyledScopeBar,
StyledSettingsHeader,
} from './SelectLocationStyles';
@@ -47,6 +52,7 @@ interface IProps {
allowEntrySelection: boolean;
tunnelProtocol: LiftedConstraint<TunnelProtocol>;
providers: string[];
+ ownership: Ownership;
onClose: () => void;
onViewFilter: () => void;
onSelectExitLocation: (location: RelayLocation) => void;
@@ -54,6 +60,7 @@ interface IProps {
onSelectBridgeLocation: (location: RelayLocation) => void;
onSelectClosestToExit: () => void;
onClearProviders: () => void;
+ onClearOwnership: () => void;
}
enum LocationScope {
@@ -127,6 +134,9 @@ export default class SelectLocation extends React.Component<IProps, IState> {
}
public render() {
+ const showOwnershipFilter = this.props.ownership !== Ownership.any;
+ const showProvidersFilter = this.props.providers.length > 0;
+ const showFilters = showOwnershipFilter || showProvidersFilter;
return (
<BackAction icon="close" action={this.props.onClose}>
<Layout>
@@ -167,32 +177,52 @@ export default class SelectLocation extends React.Component<IProps, IState> {
{this.renderHeaderSubtitle()}
</StyledSettingsHeader>
- {this.props.providers.length > 0 && (
- <StyledProviderCountRow>
+ {showFilters && (
+ <StyledFilterRow>
{messages.pgettext('select-location-view', 'Filtered:')}
- <StyledProvidersCount>
- {sprintf(
- messages.pgettext(
- 'select-location-view',
- 'Providers: %(numberOfProviders)d',
- ),
- {
- numberOfProviders: this.props.providers.length,
- },
- )}
- <StyledClearProvidersButton
- aria-label={messages.gettext('Clear')}
- onClick={this.props.onClearProviders}>
- <ImageView
- height={16}
- width={16}
- source="icon-close"
- tintColor={colors.white60}
- tintHoverColor={colors.white80}
- />
- </StyledClearProvidersButton>
- </StyledProvidersCount>
- </StyledProviderCountRow>
+
+ {showOwnershipFilter && (
+ <StyledFilter>
+ {this.ownershipFilterLabel()}
+ <StyledClearFilterButton
+ aria-label={messages.gettext('Clear')}
+ onClick={this.props.onClearOwnership}>
+ <ImageView
+ height={16}
+ width={16}
+ source="icon-close"
+ tintColor={colors.white60}
+ tintHoverColor={colors.white80}
+ />
+ </StyledClearFilterButton>
+ </StyledFilter>
+ )}
+
+ {showProvidersFilter && (
+ <StyledFilter>
+ {sprintf(
+ messages.pgettext(
+ 'select-location-view',
+ 'Providers: %(numberOfProviders)d',
+ ),
+ {
+ numberOfProviders: this.props.providers.length,
+ },
+ )}
+ <StyledClearFilterButton
+ aria-label={messages.gettext('Clear')}
+ onClick={this.props.onClearProviders}>
+ <ImageView
+ height={16}
+ width={16}
+ source="icon-close"
+ tintColor={colors.white60}
+ tintHoverColor={colors.white80}
+ />
+ </StyledClearFilterButton>
+ </StyledFilter>
+ )}
+ </StyledFilterRow>
)}
{this.props.allowEntrySelection && (
<StyledScopeBar
@@ -228,6 +258,17 @@ export default class SelectLocation extends React.Component<IProps, IState> {
}
}
+ private ownershipFilterLabel(): string {
+ switch (this.props.ownership) {
+ case Ownership.mullvadOwned:
+ return messages.pgettext('filter-view', 'Owned');
+ case Ownership.rented:
+ return messages.pgettext('filter-view', 'Rented');
+ default:
+ throw new Error('Only owned and rented should make label visible');
+ }
+ }
+
private getLocationListRef(prevProps: IProps, prevState: IState) {
if (prevState.locationScope === LocationScope.exit) {
return this.exitLocationList.current;
diff --git a/gui/src/renderer/components/SelectLocationStyles.tsx b/gui/src/renderer/components/SelectLocationStyles.tsx
index ac7f684ff8..15211389f6 100644
--- a/gui/src/renderer/components/SelectLocationStyles.tsx
+++ b/gui/src/renderer/components/SelectLocationStyles.tsx
@@ -43,14 +43,14 @@ export const StyledSettingsHeader = styled(SettingsHeader)({
paddingBottom: '11px',
});
-export const StyledProviderCountRow = styled.div({
+export const StyledFilterRow = styled.div({
...tinyText,
color: colors.white,
marginLeft: '6px',
marginBottom: '8px',
});
-export const StyledProvidersCount = styled.div({
+export const StyledFilter = styled.div({
...tinyText,
display: 'inline-flex',
alignItems: 'center',
@@ -61,7 +61,7 @@ export const StyledProvidersCount = styled.div({
color: colors.white,
});
-export const StyledClearProvidersButton = styled.div({
+export const StyledClearFilterButton = styled.div({
display: 'inline-block',
borderWidth: 0,
padding: 0,
diff --git a/gui/src/renderer/containers/SelectLocationPage.tsx b/gui/src/renderer/containers/SelectLocationPage.tsx
index f26e805d83..8fa036f245 100644
--- a/gui/src/renderer/containers/SelectLocationPage.tsx
+++ b/gui/src/renderer/containers/SelectLocationPage.tsx
@@ -1,7 +1,7 @@
import { connect } from 'react-redux';
import BridgeSettingsBuilder from '../../shared/bridge-settings-builder';
-import { LiftedConstraint, RelayLocation } from '../../shared/daemon-rpc-types';
+import { LiftedConstraint, Ownership, RelayLocation } from '../../shared/daemon-rpc-types';
import log from '../../shared/logging';
import RelaySettingsBuilder from '../../shared/relay-settings-builder';
import SelectLocation from '../components/SelectLocation';
@@ -44,6 +44,7 @@ const mapStateToProps = (state: IReduxState, props: IHistoryProps & IAppContext)
((tunnelProtocol === 'any' || tunnelProtocol === 'wireguard') && multihopEnabled);
const providers = 'normal' in relaySettings ? relaySettings.normal.providers : [];
+ const ownership = 'normal' in relaySettings ? relaySettings.normal.ownership : Ownership.any;
return {
locale: state.userInterface.locale,
@@ -55,6 +56,7 @@ const mapStateToProps = (state: IReduxState, props: IHistoryProps & IAppContext)
allowEntrySelection,
tunnelProtocol,
providers,
+ ownership,
onSelectEntryLocation: async (entryLocation: RelayLocation) => {
// dismiss the view first
@@ -118,6 +120,9 @@ const mapDispatchToProps = (_dispatch: ReduxDispatch, props: IHistoryProps & IAp
onClearProviders: async () => {
await props.app.updateRelaySettings({ normal: { providers: [] } });
},
+ onClearOwnership: async () => {
+ await props.app.updateRelaySettings({ normal: { ownership: Ownership.any } });
+ },
};
};