diff --git a/res/css/_components.scss b/res/css/_components.scss
index 4ae93f0727..65ce8742b8 100644
--- a/res/css/_components.scss
+++ b/res/css/_components.scss
@@ -5,6 +5,7 @@
@import "./_font-weights.scss";
@import "./_spacing.scss";
@import "./components/views/location/_LocationShareMenu.scss";
+@import "./components/views/location/_ShareDialogButtons.scss";
@import "./components/views/location/_ShareType.scss";
@import "./components/views/spaces/_QuickThemeSwitcher.scss";
@import "./structures/_AutoHideScrollbar.scss";
diff --git a/res/css/components/views/location/_ShareDialogButtons.scss b/res/css/components/views/location/_ShareDialogButtons.scss
new file mode 100644
index 0000000000..c6d77d2da8
--- /dev/null
+++ b/res/css/components/views/location/_ShareDialogButtons.scss
@@ -0,0 +1,52 @@
+/*
+Copyright 2022 The Matrix.org Foundation C.I.C
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_ShareDialogButtons {
+ position: absolute;
+ width: 100%;
+ height: 0;
+ top: 0;
+}
+
+.mx_ShareDialogButtons_button {
+ @mixin ButtonResetDefault;
+ height: 24px;
+ width: 24px;
+ border-radius: 50%;
+ background-color: $quinary-content;
+ opacity: 0.8;
+ text-align: center;
+ color: $secondary-content;
+ position: absolute;
+ top: $spacing-16;
+
+ &:hover, &:focus {
+ opacity: 1;
+ }
+
+ &.left {
+ left: $spacing-16;
+ }
+
+ &.right {
+ right: $spacing-16;
+ }
+}
+
+.mx_ShareDialogButtons_button-icon {
+ height: 10px;
+ margin-top: 3px;
+}
diff --git a/res/css/views/location/_LocationPicker.scss b/res/css/views/location/_LocationPicker.scss
index 082912c92d..76e56eedd9 100644
--- a/res/css/views/location/_LocationPicker.scss
+++ b/res/css/views/location/_LocationPicker.scss
@@ -25,11 +25,15 @@ limitations under the License.
border-radius: 8px;
.maplibregl-ctrl.maplibregl-ctrl-group {
+ // place below the close button
+ // padding-16 + 24px close button + padding-10
margin-top: 50px;
+ margin-right: $spacing-16;
}
.maplibregl-ctrl-bottom-right {
bottom: 68px;
+ margin-right: $spacing-16;
}
.maplibregl-user-location-accuracy-circle {
@@ -91,34 +95,6 @@ limitations under the License.
min-width: 328px;
min-height: 48px;
}
-
- button.mx_LocationPicker_cancelButton {
- border: none;
- border-radius: 12px;
- position: absolute;
- top: -360px;
- right: 5px;
- background-color: $quinary-content;
- width: 24px;
- height: 24px;
- padding: 0px;
- color: rgba(0, 0, 0, 0);
- }
-
- button.mx_LocationPicker_cancelButton::before {
- content: '';
- background-color: $primary-content;
- min-width: 8px;
- min-height: 8px;
- width: 8px;
- height: 8px;
- position: absolute;
- margin: 4px 8px;
- mask-repeat: no-repeat;
- mask-size: contain;
- mask-position: center;
- mask-image: url('$(res)/img/cancel-small.svg');
- }
}
}
diff --git a/res/img/element-icons/cancel-rounded.svg b/res/img/element-icons/cancel-rounded.svg
new file mode 100644
index 0000000000..7439aaeaba
--- /dev/null
+++ b/res/img/element-icons/cancel-rounded.svg
@@ -0,0 +1,4 @@
+
diff --git a/res/img/element-icons/caret-left.svg b/res/img/element-icons/caret-left.svg
new file mode 100644
index 0000000000..14c28dc3b1
--- /dev/null
+++ b/res/img/element-icons/caret-left.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/components/views/location/LocationPicker.tsx b/src/components/views/location/LocationPicker.tsx
index 2300ba7ac6..150b8355e8 100644
--- a/src/components/views/location/LocationPicker.tsx
+++ b/src/components/views/location/LocationPicker.tsx
@@ -177,10 +177,9 @@ class LocationPicker extends React.Component {
diff --git a/src/components/views/location/LocationShareMenu.tsx b/src/components/views/location/LocationShareMenu.tsx
index 1f29b48291..ab33251794 100644
--- a/src/components/views/location/LocationShareMenu.tsx
+++ b/src/components/views/location/LocationShareMenu.tsx
@@ -24,6 +24,7 @@ import LocationPicker, { ILocationPickerProps } from "./LocationPicker";
import { shareLocation } from './shareLocation';
import SettingsStore from '../../../settings/SettingsStore';
import ShareType, { LocationShareType } from './ShareType';
+import ShareDialogButtons from './ShareDialogButtons';
type Props = Omit & {
onFinished: (ev?: SyntheticEvent) => void;
@@ -55,8 +56,10 @@ const LocationShareMenu: React.FC = ({
const matrixClient = useContext(MatrixClientContext);
const enabledShareTypes = getEnabledShareTypes();
- const [shareType, setShareType] = useState(
- enabledShareTypes.length === 1 ? LocationShareType.Own : undefined,
+ const multipleShareTypesEnabled = enabledShareTypes.length > 1;
+
+ const [shareType, setShareType] = useState(
+ multipleShareTypesEnabled ? undefined : LocationShareType.Own,
);
return = ({
/>
:
}
+ setShareType(undefined)} onCancel={onFinished} />
;
};
diff --git a/src/components/views/location/ShareDialogButtons.tsx b/src/components/views/location/ShareDialogButtons.tsx
new file mode 100644
index 0000000000..fac113d169
--- /dev/null
+++ b/src/components/views/location/ShareDialogButtons.tsx
@@ -0,0 +1,52 @@
+/*
+Copyright 2022 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the 'License');
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an 'AS IS' BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from 'react';
+
+import AccessibleButton from '../elements/AccessibleButton';
+import { Icon as BackIcon } from '../../../../res/img/element-icons/caret-left.svg';
+import { Icon as CloseIcon } from '../../../../res/img/element-icons/cancel-rounded.svg';
+
+interface Props {
+ onCancel: () => void;
+ onBack: () => void;
+ displayBack?: boolean;
+}
+
+const ShareDialogButtons: React.FC = ({ onBack, onCancel, displayBack }) => {
+ return
+ { displayBack &&
+
+
+
+ }
+
+
+
+
;
+};
+
+export default ShareDialogButtons;
diff --git a/test/components/views/location/LocationShareMenu-test.tsx b/test/components/views/location/LocationShareMenu-test.tsx
index 7607f6ef55..8ffd80bf29 100644
--- a/test/components/views/location/LocationShareMenu-test.tsx
+++ b/test/components/views/location/LocationShareMenu-test.tsx
@@ -52,6 +52,7 @@ describe('', () => {
const userId = '@ernie:server.org';
const mockClient = {
on: jest.fn(),
+ off: jest.fn(),
removeListener: jest.fn(),
getUserId: jest.fn().mockReturnValue(userId),
getClientWellKnown: jest.fn().mockResolvedValue({
@@ -85,33 +86,96 @@ describe('', () => {
const getShareTypeOption = (component, shareType: LocationShareType) =>
findByTestId(component, `share-location-option-${shareType}`);
+ const getBackButton = component => findByTestId(component, 'share-dialog-buttons-back');
+ const getCancelButton = component => findByTestId(component, 'share-dialog-buttons-cancel');
- it('renders location picker when only Own share type is enabled', () => {
- mocked(SettingsStore).getValue.mockReturnValue(false);
- const component = getComponent();
- expect(component.find('ShareType').length).toBeFalsy();
- expect(component.find('LocationPicker').length).toBeTruthy();
- });
-
- it('renders share type switch with own and pin drop options when enabled', () => {
- // feature_location_share_pin_drop is set to enabled by default mocking
- const component = getComponent();
- expect(component.find('LocationPicker').length).toBeFalsy();
-
- expect(getShareTypeOption(component, LocationShareType.Own).length).toBeTruthy();
- expect(getShareTypeOption(component, LocationShareType.Pin).length).toBeTruthy();
- });
-
- it('selecting own location share type advances to location picker', () => {
- // feature_location_share_pin_drop is set to enabled by default mocking
- const component = getComponent();
-
- act(() => {
- getShareTypeOption(component, LocationShareType.Own).at(0).simulate('click');
+ describe('when only Own share type is enabled', () => {
+ beforeEach(() => {
+ mocked(SettingsStore).getValue.mockReturnValue(false);
});
- component.setProps({});
+ it('renders location picker when only Own share type is enabled', () => {
+ const component = getComponent();
+ expect(component.find('ShareType').length).toBeFalsy();
+ expect(component.find('LocationPicker').length).toBeTruthy();
+ });
- expect(component.find('LocationPicker').length).toBeTruthy();
+ it('does not render back button when only Own share type is enabled', () => {
+ const component = getComponent();
+ expect(getBackButton(component).length).toBeFalsy();
+ });
+
+ it('clicking cancel button from location picker closes dialog', () => {
+ const onFinished = jest.fn();
+ const component = getComponent({ onFinished });
+
+ act(() => {
+ getCancelButton(component).at(0).simulate('click');
+ });
+
+ expect(onFinished).toHaveBeenCalled();
+ });
+ });
+
+ describe('with pin drop share type enabled', () => {
+ // feature_location_share_pin_drop is set to enabled by default mocking
+
+ it('renders share type switch with own and pin drop options', () => {
+ const component = getComponent();
+ expect(component.find('LocationPicker').length).toBeFalsy();
+
+ expect(getShareTypeOption(component, LocationShareType.Own).length).toBeTruthy();
+ expect(getShareTypeOption(component, LocationShareType.Pin).length).toBeTruthy();
+ });
+
+ it('does not render back button on share type screen', () => {
+ const component = getComponent();
+ expect(getBackButton(component).length).toBeFalsy();
+ });
+
+ it('clicking cancel button from share type screen closes dialog', () => {
+ const onFinished = jest.fn();
+ const component = getComponent({ onFinished });
+
+ act(() => {
+ getCancelButton(component).at(0).simulate('click');
+ });
+
+ expect(onFinished).toHaveBeenCalled();
+ });
+
+ it('selecting own location share type advances to location picker', () => {
+ const component = getComponent();
+
+ act(() => {
+ getShareTypeOption(component, LocationShareType.Own).at(0).simulate('click');
+ });
+
+ component.setProps({});
+
+ expect(component.find('LocationPicker').length).toBeTruthy();
+ });
+
+ it('clicking back button from location picker screen goes back to share screen', () => {
+ // feature_location_share_pin_drop is set to enabled by default mocking
+ const onFinished = jest.fn();
+ const component = getComponent({ onFinished });
+
+ // advance to location picker
+ act(() => {
+ getShareTypeOption(component, LocationShareType.Own).at(0).simulate('click');
+ component.setProps({});
+ });
+
+ expect(component.find('LocationPicker').length).toBeTruthy();
+
+ act(() => {
+ getBackButton(component).at(0).simulate('click');
+ component.setProps({});
+ });
+
+ // back to share type
+ expect(component.find('ShareType').length).toBeTruthy();
+ });
});
});