Add user avatar to location sharing dialog (#7520)

pull/21833/head
Andy Balaam 2022-01-12 13:32:08 +00:00 committed by GitHub
parent 5ae166777c
commit 11c8e720b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 134 additions and 62 deletions

View File

@ -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;
}
}

View File

@ -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<ICollapsibleButtonProps, "narrowMode"> {
room: Room;
sender: RoomMember;
shareLocation: (uri: string, ts: number) => boolean;
menuPosition: AboveLeftOf;
narrowMode: boolean;
}
export const LocationButton: React.FC<IProps> = (
{ shareLocation, menuPosition, narrowMode },
{ sender, shareLocation, menuPosition, narrowMode },
) => {
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
@ -45,7 +45,11 @@ export const LocationButton: React.FC<IProps> = (
onFinished={closeMenu}
managed={false}
>
<LocationPicker onChoose={shareLocation} onFinished={closeMenu} />
<LocationPicker
sender={sender}
onChoose={shareLocation}
onFinished={closeMenu}
/>
</ContextMenu>;
}

View File

@ -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<IProps, IState> {
public static contextType = MatrixClientContext;
public context!: React.ContextType<typeof MatrixClientContext>;
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<IProps, IState> {
};
}
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<IProps, IState> {
});
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<IProps, IState> {
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<IProps, IState> {
/>
</form>
</div>
<div className="mx_MLocationBody_marker" id={this.getMarkerId()}>
<div className="mx_MLocationBody_markerBorder">
<MemberAvatar
member={this.props.sender}
width={27}
height={27}
viewUserOnClick={false}
/>
</div>
<img
className="mx_MLocationBody_pointer"
src={require("../../../../res/img/location/pointer.svg")}
width="9"
height="5"
/>
</div>
</div>
);
}

View File

@ -532,8 +532,8 @@ export default class MessageComposer extends React.Component<IProps, IState> {
if (SettingsStore.getValue("feature_location_share")) {
buttons.push(
<LocationButton
sender={this.props.room.getMember(MatrixClientPeg.get().getUserId())}
key="location"
room={this.props.room}
shareLocation={this.shareLocation}
menuPosition={menuPosition}
narrowMode={this.state.narrowMode}