diff --git a/res/css/views/location/_LocationPicker.scss b/res/css/views/location/_LocationPicker.scss index 23afae8a00..125b33994c 100644 --- a/res/css/views/location/_LocationPicker.scss +++ b/res/css/views/location/_LocationPicker.scss @@ -21,69 +21,96 @@ limitations under the License. border-radius: 8px; position: relative; -} -#mx_LocationPicker_map { - height: 100%; - border-radius: 8px; + #mx_LocationPicker_map { + height: 100%; + border-radius: 8px; - .maplibregl-ctrl.maplibregl-ctrl-group { - margin-top: 50px; - } - - .maplibregl-ctrl-bottom-right { - bottom: 68px; - } -} - -.mx_LocationPicker_footer { - position: absolute; - bottom: 0px; - width: 100%; - - .mx_Dialog_buttons { - text-align: center; - - /* Note the `button` prefix and `not()` clauses are needed to make - these selectors more specific than those in _common.scss. */ - - button.mx_Dialog_primary:not(.mx_Dialog_nonDialogButton):not(.mx_AccessibleButton) { - margin: 0px 0px 16px 0px; - min-width: 328px; - min-height: 48px; + .maplibregl-ctrl.maplibregl-ctrl-group { + margin-top: 50px; } - button.mx_LocationPicker_cancelButton { - border: none; - border-radius: 12px; + .maplibregl-ctrl-bottom-right { + bottom: 68px; + } + + .maplibregl-user-location-accuracy-circle { + display: none; + } + + .maplibregl-user-location-dot { + display: none; + } + + .mx_MLocationBody_markerBorder { + width: 31px; + height: 31px; + border-radius: 50%; + background-color: $accent; + filter: drop-shadow(0px 3px 5px rgba(0, 0, 0, 0.2)); + + .mx_BaseAvatar { + margin-top: 2px; + margin-left: 2px; + } + } + + .mx_MLocationBody_pointer { 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'); + bottom: -3px; + left: 12px; } } -} -.mx_LocationPicker_error { - color: red; - margin: auto; + .mx_LocationPicker_footer { + position: absolute; + bottom: 0px; + width: 100%; + + .mx_Dialog_buttons { + text-align: center; + + /* Note the `button` prefix and `not()` clauses are needed to make + these selectors more specific than those in _common.scss. */ + + button.mx_Dialog_primary:not(.mx_Dialog_nonDialogButton):not(.mx_AccessibleButton) { + margin: 0px 0px 16px 0px; + 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'); + } + } + } + + .mx_LocationPicker_error { + color: red; + margin: auto; + } } diff --git a/src/components/views/location/LocationButton.tsx b/src/components/views/location/LocationButton.tsx index b1c90ec0da..2281d87f6b 100644 --- a/src/components/views/location/LocationButton.tsx +++ b/src/components/views/location/LocationButton.tsx @@ -15,8 +15,8 @@ limitations under the License. */ import React, { ReactElement } from 'react'; -import { Room } from "matrix-js-sdk/src/models/room"; import classNames from 'classnames'; +import { RoomMember } from 'matrix-js-sdk/src/models/room-member'; import { _t } from '../../../languageHandler'; import LocationPicker from './LocationPicker'; @@ -24,14 +24,14 @@ import { CollapsibleButton, ICollapsibleButtonProps } from '../rooms/Collapsible import ContextMenu, { aboveLeftOf, useContextMenu, AboveLeftOf } from "../../structures/ContextMenu"; interface IProps extends Pick { - room: Room; + sender: RoomMember; shareLocation: (uri: string, ts: number) => boolean; menuPosition: AboveLeftOf; narrowMode: boolean; } export const LocationButton: React.FC = ( - { shareLocation, menuPosition, narrowMode }, + { sender, shareLocation, menuPosition, narrowMode }, ) => { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); @@ -45,7 +45,11 @@ export const LocationButton: React.FC = ( onFinished={closeMenu} managed={false} > - + ; } diff --git a/src/components/views/location/LocationPicker.tsx b/src/components/views/location/LocationPicker.tsx index 745d4f630e..c38e61b443 100644 --- a/src/components/views/location/LocationPicker.tsx +++ b/src/components/views/location/LocationPicker.tsx @@ -17,13 +17,17 @@ limitations under the License. import React, { SyntheticEvent } from 'react'; import maplibregl from 'maplibre-gl'; import { logger } from "matrix-js-sdk/src/logger"; +import { RoomMember } from 'matrix-js-sdk/src/models/room-member'; import SdkConfig from '../../../SdkConfig'; import DialogButtons from "../elements/DialogButtons"; import { _t } from '../../../languageHandler'; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import MemberAvatar from '../avatars/MemberAvatar'; +import MatrixClientContext from '../../../contexts/MatrixClientContext'; interface IProps { + sender: RoomMember; onChoose(uri: string, ts: number): boolean; onFinished(ev?: SyntheticEvent): void; } @@ -43,8 +47,11 @@ interface IState { @replaceableComponent("views.location.LocationPicker") class LocationPicker extends React.Component { + public static contextType = MatrixClientContext; + public context!: React.ContextType; private map: maplibregl.Map; private geolocate: maplibregl.GeolocateControl; + private marker: maplibregl.Marker; constructor(props: IProps) { super(props); @@ -55,6 +62,10 @@ class LocationPicker extends React.Component { }; } + private getMarkerId = () => { + return "mx_MLocationPicker_marker"; + }; + componentDidMount() { const config = SdkConfig.get(); this.map = new maplibregl.Map({ @@ -74,6 +85,14 @@ class LocationPicker extends React.Component { }); this.map.addControl(this.geolocate); + this.marker = new maplibregl.Marker({ + element: document.getElementById(this.getMarkerId()), + anchor: 'bottom', + offset: [0, -1], + }) + .setLngLat(new maplibregl.LngLat(0, 0)) + .addTo(this.map); + this.map.on('error', (e) => { logger.error( "Failed to load map: check map_style_url in config.json " @@ -100,6 +119,12 @@ class LocationPicker extends React.Component { private onGeolocate = (position: GeolocationPosition) => { this.setState({ position }); + this.marker.setLngLat( + new maplibregl.LngLat( + position.coords.longitude, + position.coords.latitude, + ), + ); }; private onOk = () => { @@ -134,6 +159,22 @@ class LocationPicker extends React.Component { /> +
+
+ +
+ +
); } diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index 6cbb9150a9..bc9b60f4a4 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -532,8 +532,8 @@ export default class MessageComposer extends React.Component { if (SettingsStore.getValue("feature_location_share")) { buttons.push(