mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-15 04:34:59 +08:00
Location share type UI (#7924)
* copyright Signed-off-by: Kerry Archibald <kerrya@element.io> * empty line Signed-off-by: Kerry Archibald <kerrya@element.io> * functional picker Signed-off-by: Kerry Archibald <kerrya@element.io> * most style Signed-off-by: Kerry Archibald <kerrya@element.io> * nice style for options Signed-off-by: Kerry Archibald <kerrya@element.io> * get ShareType test passing Signed-off-by: Kerry Archibald <kerrya@element.io> * add maplibre mock Signed-off-by: Kerry Archibald <kerrya@element.io> * lint and test Signed-off-by: Kerry Archibald <kerrya@element.io> * add section to themes for location sharing cols Signed-off-by: Kerry Archibald <kerrya@element.io> * add svg mock Signed-off-by: Kerry Archibald <kerrya@element.io> * use same mock string as imageMock Signed-off-by: Kerry Archibald <kerrya@element.io> * newline Signed-off-by: Kerry Archibald <kerrya@element.io> * lint Signed-off-by: Kerry Archibald <kerrya@element.io> * add live location icon Signed-off-by: Kerry Archibald <kerrya@element.io> * rename useEnabledShareTypes Signed-off-by: Kerry Archibald <kerrya@element.io> * use solid color for live border * use ternary Signed-off-by: Kerry Archibald <kerrya@element.io> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
547144a565
commit
b480bffab0
20
__mocks__/maplibre-gl.js
Normal file
20
__mocks__/maplibre-gl.js
Normal file
@ -0,0 +1,20 @@
|
||||
const EventEmitter = require("events");
|
||||
const { LngLat } = require('maplibre-gl');
|
||||
|
||||
class MockMap extends EventEmitter {
|
||||
addControl = jest.fn();
|
||||
removeControl = jest.fn();
|
||||
}
|
||||
class MockGeolocateControl extends EventEmitter {
|
||||
|
||||
}
|
||||
class MockMarker extends EventEmitter {
|
||||
setLngLat = jest.fn().mockReturnValue(this);
|
||||
addTo = jest.fn();
|
||||
}
|
||||
module.exports = {
|
||||
Map: MockMap,
|
||||
GeolocateControl: MockGeolocateControl,
|
||||
Marker: MockMarker,
|
||||
LngLat,
|
||||
};
|
@ -5,6 +5,7 @@
|
||||
@import "./_font-weights.scss";
|
||||
@import "./_spacing.scss";
|
||||
@import "./components/views/location/_LocationShareMenu.scss";
|
||||
@import "./components/views/location/_ShareType.scss";
|
||||
@import "./components/views/spaces/_QuickThemeSwitcher.scss";
|
||||
@import "./structures/_AutoHideScrollbar.scss";
|
||||
@import "./structures/_BackdropPanel.scss";
|
||||
|
108
res/css/components/views/location/_ShareType.scss
Normal file
108
res/css/components/views/location/_ShareType.scss
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
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_ShareType {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
padding: 60px $spacing-12 $spacing-32;
|
||||
|
||||
color: $primary-content;
|
||||
}
|
||||
|
||||
.mx_ShareType_badge {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
margin-bottom: $spacing-20;
|
||||
background-color: $accent;
|
||||
border-radius: 50%;
|
||||
border: 14px solid $accent;
|
||||
// colors icon
|
||||
color: white;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.mx_ShareType_heading {
|
||||
padding-bottom: $spacing-32;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mx_ShareType_option {
|
||||
@mixin ButtonResetDefault;
|
||||
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: $spacing-8 $spacing-20;
|
||||
margin-top: $spacing-12;
|
||||
|
||||
color: $primary-content;
|
||||
border: 1px solid $quinary-content;
|
||||
border-radius: 8px;
|
||||
|
||||
font-size: $font-15px;
|
||||
|
||||
&:hover, &:focus {
|
||||
border-color: $accent;
|
||||
}
|
||||
|
||||
// this style is only during active development
|
||||
// when lab is enabled but feature not fully implemented
|
||||
// pin drop option will be disabled
|
||||
&.mx_AccessibleButton_disabled {
|
||||
pointer-events: none;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_ShareType_option-icon {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
box-sizing: border-box;
|
||||
margin-right: $spacing-12;
|
||||
flex: 0 0 40px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-radius: 50%;
|
||||
|
||||
&.Own {
|
||||
// color is set by user color class
|
||||
// generated from id
|
||||
border-color: currentColor;
|
||||
}
|
||||
|
||||
&.Live {
|
||||
background-color: $location-live-color;
|
||||
// 20% brightness $location-live-color
|
||||
border-color: #deddfd;
|
||||
padding: 2px;
|
||||
// colors icon
|
||||
color: white;
|
||||
}
|
||||
|
||||
&.Pin {
|
||||
border-color: $accent;
|
||||
background-color: $accent;
|
||||
padding: 7px;
|
||||
// colors icon
|
||||
color: white;
|
||||
}
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 1.99999C8.13 1.99999 5 5.2152 5 9.19054C5 13.4741 9.42 19.3806 11.24 21.6302C11.64 22.1233 12.37 22.1233 12.77 21.6302C14.58 19.3806 19 13.4741 19 9.19054C19 5.2152 15.87 1.99999 12 1.99999ZM12 11.7586C10.62 11.7586 9.5 10.6081 9.5 9.19054C9.5 7.77298 10.62 6.62249 12 6.62249C13.38 6.62249 14.5 7.77298 14.5 9.19054C14.5 10.6081 13.38 11.7586 12 11.7586Z" fill="#737D8C"/>
|
||||
<path d="M12 1.99999C8.13 1.99999 5 5.2152 5 9.19054C5 13.4741 9.42 19.3806 11.24 21.6302C11.64 22.1233 12.37 22.1233 12.77 21.6302C14.58 19.3806 19 13.4741 19 9.19054C19 5.2152 15.87 1.99999 12 1.99999ZM12 11.7586C10.62 11.7586 9.5 10.6081 9.5 9.19054C9.5 7.77298 10.62 6.62249 12 6.62249C13.38 6.62249 14.5 7.77298 14.5 9.19054C14.5 10.6081 13.38 11.7586 12 11.7586Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 490 B After Width: | Height: | Size: 495 B |
3
res/img/location/live-location.svg
Normal file
3
res/img/location/live-location.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="26" height="14" viewBox="0 0 26 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.65397 13.1529C3.97397 12.8329 4.00534 12.3247 3.71671 11.9796C1.3073 9.04941 1.3073 4.7953 3.71044 1.85883C3.99906 1.50745 3.97397 0.992943 3.65397 0.672942C3.28377 0.302747 2.66887 0.327845 2.33632 0.735688C-0.593877 4.31843 -0.593877 9.50118 2.33632 13.0902C2.66259 13.498 3.2775 13.5294 3.65397 13.1529ZM6.18259 10.6243C6.49004 10.3169 6.52142 9.83373 6.26416 9.47608C5.17867 7.9451 5.17867 5.88706 6.26416 4.35608C6.51514 3.99843 6.49004 3.5153 6.18259 3.20784L6.17632 3.20157C5.79985 2.8251 5.15985 2.8502 4.8524 3.28314C3.29004 5.44157 3.29004 8.38432 4.8524 10.549C5.16612 10.982 5.79985 11.0071 6.18259 10.6243ZM13.3147 1.03914C10.8864 1.03914 8.92253 3.05652 8.92253 5.55086C8.92253 8.23855 11.6959 11.9446 12.8378 13.3561C13.0888 13.6655 13.5468 13.6655 13.7978 13.3561C14.9335 11.9446 17.7068 8.23855 17.7068 5.55086C17.7068 3.05652 15.7429 1.03914 13.3147 1.03914ZM13.3147 7.16219C12.4488 7.16219 11.7461 6.44031 11.7461 5.55086C11.7461 4.66141 12.4488 3.93953 13.3147 3.93953C14.1806 3.93953 14.8833 4.66141 14.8833 5.55086C14.8833 6.44031 14.1806 7.16219 13.3147 7.16219ZM22.3093 11.9796C22.0207 12.3247 22.0521 12.8329 22.3721 13.1529C22.7485 13.5294 23.3634 13.498 23.6897 13.0902C26.6199 9.50118 26.6199 4.31843 23.6897 0.735688C23.3572 0.327845 22.7423 0.302747 22.3721 0.672942C22.0521 0.992943 22.027 1.50745 22.3156 1.85883C24.7187 4.7953 24.7187 9.04941 22.3093 11.9796ZM19.7619 9.47608C19.5046 9.83373 19.536 10.3169 19.8434 10.6243C20.2262 11.0071 20.8599 10.982 21.1736 10.549C22.736 8.38432 22.736 5.44157 21.1736 3.28314C20.8662 2.8502 20.2262 2.8251 19.8497 3.20157L19.8434 3.20784C19.536 3.5153 19.5109 3.99843 19.7619 4.35608C20.8474 5.88706 20.8474 7.9451 19.7619 9.47608Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
@ -182,6 +182,11 @@ $call-view-button-off-background: $primary-content;
|
||||
$video-feed-secondary-background: $system;
|
||||
// ********************
|
||||
|
||||
// Location sharing
|
||||
// ********************
|
||||
$location-live-color: #5c56f5;
|
||||
// ********************
|
||||
|
||||
// Location sharing
|
||||
// ********************
|
||||
.maplibregl-ctrl-attrib-button {
|
||||
|
@ -188,6 +188,12 @@ $eventbubble-others-bg: $event-selected-color;
|
||||
$eventbubble-bg-hover: #1C2026;
|
||||
$eventbubble-reply-color: #C1C6CD;
|
||||
|
||||
// Location sharing
|
||||
// ********************
|
||||
$location-marker-color: #ffffff;
|
||||
$location-live-color: #5c56f5;
|
||||
// ********************
|
||||
|
||||
// ***** Mixins! *****
|
||||
|
||||
@define-mixin mx_DialogButton {
|
||||
|
@ -36,7 +36,6 @@ $accent-alt: #238cf5;
|
||||
$selection-fg-color: $primary-bg-color;
|
||||
|
||||
$focus-brightness: 105%;
|
||||
$location-marker-color: #ffffff;
|
||||
|
||||
$other-user-pill-bg-color: rgba(0, 0, 0, 0.1);
|
||||
|
||||
@ -284,6 +283,12 @@ $pinned-color: $tertiary-content;
|
||||
|
||||
$groupFilterPanel-divider-color: $tertiary-content;
|
||||
|
||||
// Location sharing
|
||||
// ********************
|
||||
$location-marker-color: #ffffff;
|
||||
$location-live-color: #5c56f5;
|
||||
// ********************
|
||||
|
||||
// ***** Mixins! *****
|
||||
|
||||
@define-mixin mx_DialogButton {
|
||||
|
@ -283,7 +283,6 @@ $pinned-color: $tertiary-content;
|
||||
$avatar-initial-color: $background;
|
||||
$primary-hairline-color: transparent;
|
||||
$focus-brightness: 105%;
|
||||
$location-marker-color: #ffffff;
|
||||
// ********************
|
||||
|
||||
// blur amounts for left left panel (only for element theme)
|
||||
@ -298,6 +297,12 @@ $location-marker-color: #ffffff;
|
||||
$copy-button-url: "$(res)/img/feather-customised/clipboard.svg";
|
||||
// ********************
|
||||
|
||||
// Location sharing
|
||||
// ********************
|
||||
$location-marker-color: #ffffff;
|
||||
$location-live-color: #5c56f5;
|
||||
// ********************
|
||||
|
||||
// Mixins
|
||||
// ********************
|
||||
@define-mixin mx_DialogButton {
|
||||
|
@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { SyntheticEvent, useContext } from 'react';
|
||||
import React, { SyntheticEvent, useContext, useState } from 'react';
|
||||
import { Room } from 'matrix-js-sdk/src/models/room';
|
||||
|
||||
import MatrixClientContext from '../../../contexts/MatrixClientContext';
|
||||
import ContextMenu, { AboveLeftOf } from '../../structures/ContextMenu';
|
||||
import LocationPicker, { ILocationPickerProps } from "./LocationPicker";
|
||||
import { shareLocation } from './shareLocation';
|
||||
import SettingsStore from '../../../settings/SettingsStore';
|
||||
import ShareType, { LocationShareType } from './ShareType';
|
||||
|
||||
type Props = Omit<ILocationPickerProps, 'onChoose'> & {
|
||||
onFinished: (ev?: SyntheticEvent) => void;
|
||||
@ -29,10 +31,26 @@ type Props = Omit<ILocationPickerProps, 'onChoose'> & {
|
||||
roomId: Room["roomId"];
|
||||
};
|
||||
|
||||
const getEnabledShareTypes = (): LocationShareType[] => {
|
||||
const isPinDropLocationShareEnabled = SettingsStore.getValue("feature_location_share_pin_drop");
|
||||
|
||||
if (isPinDropLocationShareEnabled) {
|
||||
return [LocationShareType.Own, LocationShareType.Pin];
|
||||
}
|
||||
return [
|
||||
LocationShareType.Own,
|
||||
];
|
||||
};
|
||||
|
||||
const LocationShareMenu: React.FC<Props> = ({
|
||||
menuPosition, onFinished, sender, roomId, openMenu,
|
||||
}) => {
|
||||
const matrixClient = useContext(MatrixClientContext);
|
||||
const enabledShareTypes = getEnabledShareTypes();
|
||||
|
||||
const [shareType, setShareType] = useState<LocationShareType>(
|
||||
enabledShareTypes.length === 1 ? LocationShareType.Own : undefined,
|
||||
);
|
||||
|
||||
return <ContextMenu
|
||||
{...menuPosition}
|
||||
@ -40,11 +58,13 @@ const LocationShareMenu: React.FC<Props> = ({
|
||||
managed={false}
|
||||
>
|
||||
<div className="mx_LocationShareMenu">
|
||||
<LocationPicker
|
||||
{ shareType ? <LocationPicker
|
||||
sender={sender}
|
||||
onChoose={shareLocation(matrixClient, roomId, openMenu)}
|
||||
onFinished={onFinished}
|
||||
/>
|
||||
:
|
||||
<ShareType setShareType={setShareType} enabledShareTypes={enabledShareTypes} /> }
|
||||
</div>
|
||||
</ContextMenu>;
|
||||
};
|
||||
|
103
src/components/views/location/ShareType.tsx
Normal file
103
src/components/views/location/ShareType.tsx
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
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, { HTMLAttributes, useContext } from 'react';
|
||||
|
||||
import MatrixClientContext from '../../../contexts/MatrixClientContext';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { OwnProfileStore } from '../../../stores/OwnProfileStore';
|
||||
import { getUserNameColorClass } from '../../../utils/FormattingUtils';
|
||||
import BaseAvatar from '../avatars/BaseAvatar';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import Heading from '../typography/Heading';
|
||||
import { Icon as LocationIcon } from '../../../../res/img/element-icons/location.svg';
|
||||
import { Icon as LiveLocationIcon } from '../../../../res/img/location/live-location.svg';
|
||||
|
||||
const UserAvatar = () => {
|
||||
const matrixClient = useContext(MatrixClientContext);
|
||||
const userId = matrixClient.getUserId();
|
||||
const displayName = OwnProfileStore.instance.displayName;
|
||||
// 40 - 2px border
|
||||
const avatarSize = 36;
|
||||
const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
|
||||
const colorClass = getUserNameColorClass(userId);
|
||||
|
||||
return <div className={`mx_ShareType_option-icon ${LocationShareType.Own} ${colorClass}`}>
|
||||
<BaseAvatar
|
||||
idName={userId}
|
||||
name={displayName}
|
||||
url={avatarUrl}
|
||||
width={avatarSize}
|
||||
height={avatarSize}
|
||||
resizeMethod="crop"
|
||||
className="mx_UserMenu_userAvatar_BaseAvatar"
|
||||
/>
|
||||
</div>;
|
||||
};
|
||||
|
||||
// TODO this will be defined somewhere better
|
||||
export enum LocationShareType {
|
||||
Own = 'Own',
|
||||
Pin = 'Pin',
|
||||
Live = 'Live'
|
||||
}
|
||||
type ShareTypeOptionProps = HTMLAttributes<Element> & { label: string, shareType: LocationShareType };
|
||||
const ShareTypeOption: React.FC<ShareTypeOptionProps> = ({
|
||||
onClick, label, shareType, ...rest
|
||||
}) => <AccessibleButton
|
||||
element='button'
|
||||
className='mx_ShareType_option'
|
||||
onClick={onClick}
|
||||
// not yet implemented
|
||||
disabled={shareType !== LocationShareType.Own}
|
||||
{...rest}>
|
||||
{ shareType === LocationShareType.Own && <UserAvatar /> }
|
||||
{ shareType === LocationShareType.Pin &&
|
||||
<LocationIcon className={`mx_ShareType_option-icon ${LocationShareType.Pin}`} /> }
|
||||
{ shareType === LocationShareType.Live &&
|
||||
<LiveLocationIcon className={`mx_ShareType_option-icon ${LocationShareType.Live}`} /> }
|
||||
|
||||
{ label }
|
||||
</AccessibleButton>;
|
||||
|
||||
interface Props {
|
||||
setShareType: (shareType: LocationShareType) => void;
|
||||
enabledShareTypes: LocationShareType[];
|
||||
}
|
||||
const ShareType: React.FC<Props> = ({
|
||||
setShareType, enabledShareTypes,
|
||||
}) => {
|
||||
const labels = {
|
||||
[LocationShareType.Own]: _t('My current location'),
|
||||
[LocationShareType.Live]: _t('My live location'),
|
||||
[LocationShareType.Pin]: _t('Drop a Pin'),
|
||||
};
|
||||
return <div className='mx_ShareType'>
|
||||
<LocationIcon className='mx_ShareType_badge' />
|
||||
<Heading className='mx_ShareType_heading' size='h3'>{ _t("What location type do you want to share?") }</Heading>
|
||||
{ enabledShareTypes.map((type) =>
|
||||
<ShareTypeOption
|
||||
key={type}
|
||||
onClick={() => setShareType(type)}
|
||||
label={labels[type]}
|
||||
shareType={type}
|
||||
data-test-id={`share-location-option-${type}`}
|
||||
/>,
|
||||
) }
|
||||
</div>;
|
||||
};
|
||||
|
||||
export default ShareType;
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
|
@ -2179,6 +2179,10 @@
|
||||
"Unknown error fetching location. Please try again later.": "Unknown error fetching location. Please try again later.",
|
||||
"We couldn’t send your location": "We couldn’t send your location",
|
||||
"Element could not send your location. Please try again later.": "Element could not send your location. Please try again later.",
|
||||
"My current location": "My current location",
|
||||
"My live location": "My live location",
|
||||
"Drop a Pin": "Drop a Pin",
|
||||
"What location type do you want to share?": "What location type do you want to share?",
|
||||
"Failed to load group members": "Failed to load group members",
|
||||
"Filter community members": "Filter community members",
|
||||
"Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "Are you sure you want to remove '%(roomName)s' from %(groupId)s?",
|
||||
|
@ -17,15 +17,46 @@ limitations under the License.
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
|
||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||
import { mocked } from 'jest-mock';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import '../../../skinned-sdk';
|
||||
import LocationShareMenu from '../../../../src/components/views/location/LocationShareMenu';
|
||||
import MatrixClientContext from '../../../../src/contexts/MatrixClientContext';
|
||||
import { ChevronFace } from '../../../../src/components/structures/ContextMenu';
|
||||
import SettingsStore from '../../../../src/settings/SettingsStore';
|
||||
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
|
||||
import { LocationShareType } from '../../../../src/components/views/location/ShareType';
|
||||
import { findByTestId } from '../../../test-utils';
|
||||
|
||||
jest.mock('../../../../src/components/views/messages/MLocationBody', () => ({
|
||||
findMapStyleUrl: jest.fn().mockReturnValue('test'),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../src/settings/SettingsStore', () => ({
|
||||
getValue: jest.fn(),
|
||||
monitorSetting: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../src/stores/OwnProfileStore', () => ({
|
||||
OwnProfileStore: {
|
||||
instance: {
|
||||
displayName: 'Ernie',
|
||||
getHttpAvatarUrl: jest.fn().mockReturnValue('image.com/img'),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('<LocationShareMenu />', () => {
|
||||
const userId = '@ernie:server.org';
|
||||
const mockClient = {
|
||||
on: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
getUserId: jest.fn().mockReturnValue(userId),
|
||||
getClientWellKnown: jest.fn().mockResolvedValue({
|
||||
map_style_url: 'maps.com',
|
||||
}),
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
@ -36,7 +67,7 @@ describe('<LocationShareMenu />', () => {
|
||||
onFinished: jest.fn(),
|
||||
openMenu: jest.fn(),
|
||||
roomId: '!room:server.org',
|
||||
sender: { id: '@ernie:server.org' } as unknown as RoomMember,
|
||||
sender: new RoomMember('!room:server.org', userId),
|
||||
};
|
||||
const getComponent = (props = {}) =>
|
||||
mount(<LocationShareMenu {...defaultProps} {...props} />, {
|
||||
@ -44,8 +75,43 @@ describe('<LocationShareMenu />', () => {
|
||||
wrappingComponentProps: { value: mockClient },
|
||||
});
|
||||
|
||||
it('renders', () => {
|
||||
beforeEach(() => {
|
||||
mocked(SettingsStore).getValue.mockImplementation(
|
||||
(settingName) => settingName === "feature_location_share_pin_drop",
|
||||
);
|
||||
|
||||
jest.spyOn(MatrixClientPeg, 'get').mockReturnValue(mockClient as unknown as MatrixClient);
|
||||
});
|
||||
|
||||
const getShareTypeOption = (component, shareType: LocationShareType) =>
|
||||
findByTestId(component, `share-location-option-${shareType}`);
|
||||
|
||||
it('renders location picker when only Own share type is enabled', () => {
|
||||
mocked(SettingsStore).getValue.mockReturnValue(false);
|
||||
const component = getComponent();
|
||||
expect(component).toMatchSnapshot();
|
||||
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');
|
||||
});
|
||||
|
||||
component.setProps({});
|
||||
|
||||
expect(component.find('LocationPicker').length).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -1,289 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<LocationShareMenu /> renders 1`] = `
|
||||
<LocationShareMenu
|
||||
menuPosition={
|
||||
Object {
|
||||
"chevronFace": "bottom",
|
||||
"left": 1,
|
||||
"top": 1,
|
||||
}
|
||||
}
|
||||
onFinished={[MockFunction]}
|
||||
openMenu={[MockFunction]}
|
||||
roomId="!room:server.org"
|
||||
sender={
|
||||
Object {
|
||||
"id": "@ernie:server.org",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ContextMenu
|
||||
chevronFace="bottom"
|
||||
hasBackground={true}
|
||||
left={1}
|
||||
managed={false}
|
||||
onFinished={[MockFunction]}
|
||||
top={1}
|
||||
>
|
||||
<Portal
|
||||
containerInfo={
|
||||
<div
|
||||
id="mx_ContextualMenu_Container"
|
||||
>
|
||||
<div
|
||||
class="mx_ContextualMenu_wrapper"
|
||||
style="top: 1px; left: 1px;"
|
||||
>
|
||||
<div
|
||||
class="mx_ContextualMenu_background"
|
||||
/>
|
||||
<div
|
||||
class="mx_ContextualMenu mx_ContextualMenu_withChevron_bottom"
|
||||
>
|
||||
<div
|
||||
class="mx_ContextualMenu_chevron_bottom"
|
||||
/>
|
||||
<div
|
||||
class="mx_LocationShareMenu"
|
||||
>
|
||||
<div
|
||||
class="mx_LocationPicker"
|
||||
>
|
||||
<div
|
||||
id="mx_LocationPicker_map"
|
||||
/>
|
||||
<div
|
||||
class="mx_LocationPicker_error"
|
||||
>
|
||||
Failed to load map
|
||||
</div>
|
||||
<div
|
||||
class="mx_LocationPicker_footer"
|
||||
>
|
||||
<form>
|
||||
<div
|
||||
class="mx_Dialog_buttons"
|
||||
>
|
||||
<button
|
||||
class="mx_LocationPicker_cancelButton"
|
||||
data-test-id="dialog-cancel-button"
|
||||
type="button"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="mx_Dialog_primary"
|
||||
data-test-id="dialog-primary-button"
|
||||
disabled=""
|
||||
type="submit"
|
||||
>
|
||||
Share location
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
class="mx_MLocationBody_marker"
|
||||
id="mx_MLocationPicker_marker"
|
||||
>
|
||||
<div
|
||||
class="mx_MLocationBody_markerBorder"
|
||||
>
|
||||
<span
|
||||
class="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_initial"
|
||||
style="font-size: 17.55px; width: 27px; line-height: 27px;"
|
||||
/>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_image"
|
||||
src=""
|
||||
style="width: 27px; height: 27px;"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_MLocationBody_pointer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<RovingTabIndexProvider
|
||||
handleHomeEnd={true}
|
||||
handleUpDown={true}
|
||||
onKeyDown={[Function]}
|
||||
>
|
||||
<div
|
||||
className="mx_ContextualMenu_wrapper"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"left": 1,
|
||||
"top": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="mx_ContextualMenu_background"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
style={Object {}}
|
||||
/>
|
||||
<div
|
||||
className="mx_ContextualMenu mx_ContextualMenu_withChevron_bottom"
|
||||
style={Object {}}
|
||||
>
|
||||
<div
|
||||
className="mx_ContextualMenu_chevron_bottom"
|
||||
style={
|
||||
Object {
|
||||
"left": undefined,
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="mx_LocationShareMenu"
|
||||
>
|
||||
<LocationPicker
|
||||
onChoose={[Function]}
|
||||
onFinished={[MockFunction]}
|
||||
sender={
|
||||
Object {
|
||||
"id": "@ernie:server.org",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="mx_LocationPicker"
|
||||
>
|
||||
<div
|
||||
id="mx_LocationPicker_map"
|
||||
/>
|
||||
<div
|
||||
className="mx_LocationPicker_error"
|
||||
>
|
||||
Failed to load map
|
||||
</div>
|
||||
<div
|
||||
className="mx_LocationPicker_footer"
|
||||
>
|
||||
<form
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<DialogButtons
|
||||
cancelButtonClass="mx_LocationPicker_cancelButton"
|
||||
disabled={false}
|
||||
hasCancel={true}
|
||||
onCancel={[MockFunction]}
|
||||
onPrimaryButtonClick={[Function]}
|
||||
primaryButton="Share location"
|
||||
primaryDisabled={true}
|
||||
primaryIsSubmit={true}
|
||||
>
|
||||
<div
|
||||
className="mx_Dialog_buttons"
|
||||
>
|
||||
<button
|
||||
className="mx_LocationPicker_cancelButton"
|
||||
data-test-id="dialog-cancel-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
className="mx_Dialog_primary"
|
||||
data-test-id="dialog-primary-button"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
Share location
|
||||
</button>
|
||||
</div>
|
||||
</DialogButtons>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
className="mx_MLocationBody_marker"
|
||||
id="mx_MLocationPicker_marker"
|
||||
>
|
||||
<div
|
||||
className="mx_MLocationBody_markerBorder"
|
||||
>
|
||||
<MemberAvatar
|
||||
height={27}
|
||||
member={
|
||||
Object {
|
||||
"id": "@ernie:server.org",
|
||||
}
|
||||
}
|
||||
resizeMethod="crop"
|
||||
viewUserOnClick={false}
|
||||
width={27}
|
||||
>
|
||||
<BaseAvatar
|
||||
height={27}
|
||||
resizeMethod="crop"
|
||||
width={27}
|
||||
>
|
||||
<span
|
||||
className="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="mx_BaseAvatar_initial"
|
||||
style={
|
||||
Object {
|
||||
"fontSize": "17.55px",
|
||||
"lineHeight": "27px",
|
||||
"width": "27px",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
className="mx_BaseAvatar_image"
|
||||
onError={[Function]}
|
||||
src=""
|
||||
style={
|
||||
Object {
|
||||
"height": "27px",
|
||||
"width": "27px",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
</BaseAvatar>
|
||||
</MemberAvatar>
|
||||
</div>
|
||||
<div
|
||||
className="mx_MLocationBody_pointer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</LocationPicker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</RovingTabIndexProvider>
|
||||
</Portal>
|
||||
</ContextMenu>
|
||||
</LocationShareMenu>
|
||||
`;
|
Loading…
Reference in New Issue
Block a user