From ebc2267e5282b925b1169b6519844a198dd986d5 Mon Sep 17 00:00:00 2001 From: Kerry Date: Thu, 3 Mar 2022 11:30:46 +0100 Subject: [PATCH] Location sharing > back button (#7958) * add back/cancel buttons to share dialog Signed-off-by: Kerry Archibald * test buttons Signed-off-by: Kerry Archibald * improve weird indentation Signed-off-by: Kerry Archibald * relint Signed-off-by: Kerry Archibald * PR tweaks Signed-off-by: Kerry Archibald * quotes Signed-off-by: Kerry Archibald --- res/css/_components.scss | 1 + .../views/location/_ShareDialogButtons.scss | 52 +++++++++ res/css/views/location/_LocationPicker.scss | 32 +----- res/img/element-icons/cancel-rounded.svg | 4 + res/img/element-icons/caret-left.svg | 3 + .../views/location/LocationPicker.tsx | 3 +- .../views/location/LocationShareMenu.tsx | 8 +- .../views/location/ShareDialogButtons.tsx | 52 +++++++++ .../views/location/LocationShareMenu-test.tsx | 100 ++++++++++++++---- 9 files changed, 205 insertions(+), 50 deletions(-) create mode 100644 res/css/components/views/location/_ShareDialogButtons.scss create mode 100644 res/img/element-icons/cancel-rounded.svg create mode 100644 res/img/element-icons/caret-left.svg create mode 100644 src/components/views/location/ShareDialogButtons.tsx diff --git a/res/css/_components.scss b/res/css/_components.scss index 4ae93f07270..65ce8742b87 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 00000000000..c6d77d2da84 --- /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 082912c92d8..76e56eedd9f 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 00000000000..7439aaeabac --- /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 00000000000..14c28dc3b1e --- /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 2300ba7ac6c..150b8355e82 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 1f29b482919..ab332517942 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 00000000000..fac113d169a --- /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 7607f6ef557..8ffd80bf294 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(); - }); + describe('when only Own share type is enabled', () => { + beforeEach(() => { + mocked(SettingsStore).getValue.mockReturnValue(false); + }); - 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(); + 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(); + }); + + 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 }); - expect(getShareTypeOption(component, LocationShareType.Own).length).toBeTruthy(); - expect(getShareTypeOption(component, LocationShareType.Pin).length).toBeTruthy(); + act(() => { + getCancelButton(component).at(0).simulate('click'); + }); + + expect(onFinished).toHaveBeenCalled(); + }); }); - it('selecting own location share type advances to location picker', () => { + describe('with pin drop share type enabled', () => { // feature_location_share_pin_drop is set to enabled by default mocking - const component = getComponent(); - act(() => { - getShareTypeOption(component, LocationShareType.Own).at(0).simulate('click'); + 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(); }); - component.setProps({}); + 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(component.find('LocationPicker').length).toBeTruthy(); + 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(); + }); }); });