Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Support sharing custom locations. (#7185)
Browse files Browse the repository at this point in the history
Add the ability to click on the map to share a specific named location.
  • Loading branch information
ara4n committed Dec 6, 2021
1 parent 1262021 commit 684b061
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 14 deletions.
80 changes: 70 additions & 10 deletions src/components/views/location/LocationPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const LocationShareTypeDropdown = ({
onChange,
}: IDropdownProps) => {
const options = [
// <div key={LocationShareType.Custom}>{ _t("Share custom location") }</div>,
<div key={LocationShareType.Custom}>{ _t("Share custom location") }</div>,
<div key={LocationShareType.OnceOff}>{ _t("Share my current location as a once off") }</div>,
// <div key={LocationShareType.OneMin}>{ _t("Share my current location for one minute") }</div>,
// <div key={LocationShareType.FiveMins}>{ _t("Share my current location for five minutes") }</div>,
Expand All @@ -56,7 +56,9 @@ const LocationShareTypeDropdown = ({
return <Dropdown
id="mx_LocationShareTypeDropdown"
className="mx_LocationShareTypeDropdown"
onOptionChange={(key: string)=>{ onChange(LocationShareType[LocationShareType[parseInt(key)]]); }}
onOptionChange={(key: string) => {
onChange(LocationShareType[LocationShareType[parseInt(key)]]);
}}
menuWidth={width}
label={label}
value={value.toString()}
Expand All @@ -74,13 +76,14 @@ interface IState {
description: string;
type: LocationShareType;
position?: GeolocationPosition;
manual: boolean;
manualPosition?: GeolocationPosition;
error: Error;
}

@replaceableComponent("views.location.LocationPicker")
class LocationPicker extends React.Component<IProps, IState> {
private map: maplibregl.Map;
private marker: maplibregl.Marker;
private geolocate: maplibregl.GeolocateControl;

constructor(props) {
Expand All @@ -90,7 +93,7 @@ class LocationPicker extends React.Component<IProps, IState> {
description: _t("My location"),
type: LocationShareType.OnceOff,
position: undefined,
manual: false,
manualPosition: undefined,
error: undefined,
};
}
Expand All @@ -113,23 +116,63 @@ class LocationPicker extends React.Component<IProps, IState> {
});
this.map.addControl(this.geolocate);

this.map.on('error', (e)=>{
this.map.on('error', (e) => {
logger.error("Failed to load map: check map_style_url in config.json has a valid URL and API key", e.error);
this.setState({ error: e.error });
});

this.map.on('load', ()=>{
this.map.on('load', () => {
this.geolocate.trigger();
});

this.map.on('click', (e) => {
this.addMarker(e.lngLat);
this.storeManualPosition(e.lngLat);
this.setState({ type: LocationShareType.Custom });
});

this.geolocate.on('geolocate', this.onGeolocate);
}

private addMarker(lngLat: maplibregl.LngLat): void {
if (this.marker) return;
this.marker = new maplibregl.Marker({
draggable: true,
})
.setLngLat(lngLat)
.addTo(this.map)
.on('dragend', () => {
this.storeManualPosition(this.marker.getLngLat());
});
}

private removeMarker(): void {
if (!this.marker) return;
this.marker.remove();
this.marker = undefined;
}

private storeManualPosition(lngLat: maplibregl.LngLat): void {
const manualPosition: GeolocationPosition = {
coords: {
longitude: lngLat.lng,
latitude: lngLat.lat,
altitude: undefined,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
timestamp: Date.now(),
};
this.setState({ manualPosition });
}

componentWillUnmount() {
this.geolocate.off('geolocate', this.onGeolocate);
}

private onGeolocate = (position) => {
private onGeolocate = (position: GeolocationPosition) => {
this.setState({ position });
};

Expand All @@ -146,16 +189,33 @@ class LocationPicker extends React.Component<IProps, IState> {
};

private onOk = () => {
const position = (this.state.type == LocationShareType.Custom) ?
this.state.manualPosition : this.state.position;

this.props.onChoose(
this.state.position ? this.getGeoUri(this.state.position) : undefined,
this.state.position ? this.state.position.timestamp : undefined,
position ? this.getGeoUri(position) : undefined,
position ? position.timestamp : undefined,
this.state.type,
this.state.description,
);
this.props.onFinished();
};

private onTypeChange= (type: LocationShareType) => {
if (type == LocationShareType.Custom) {
if (!this.state.manualPosition) {
this.setState({ manualPosition: this.state.position });
}
if (this.state.manualPosition) {
this.addMarker(new maplibregl.LngLat(
this.state.manualPosition?.coords.longitude,
this.state.manualPosition?.coords.latitude,
));
}
} else {
this.removeMarker();
}

this.setState({ type });
};

Expand Down Expand Up @@ -189,7 +249,7 @@ class LocationPicker extends React.Component<IProps, IState> {
<DialogButtons primaryButton={_t('Share')}
onPrimaryButtonClick={this.onOk}
onCancel={this.props.onFinished}
disabled={!this.state.position} />
primaryDisabled={!this.state.position} />
</form>
</div>
</div>
Expand Down
14 changes: 10 additions & 4 deletions src/components/views/messages/MLocationBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,22 @@ export default class MLocationBody extends React.Component<IBodyProps, IState> {

componentDidMount() {
const config = SdkConfig.get();
const coordinates = new maplibregl.LngLat(this.coords.longitude, this.coords.latitude);

this.map = new maplibregl.Map({
container: this.getBodyId(),
style: config.map_style_url,
center: [this.coords.longitude, this.coords.latitude],
center: coordinates,
zoom: 13,
});

new maplibregl.Marker()
.setLngLat([this.coords.longitude, this.coords.latitude])
new maplibregl.Popup({
closeButton: false,
closeOnClick: false,
closeOnMove: false,
})
.setLngLat(coordinates)
.setHTML(this.description)
.addTo(this.map);

this.map.on('error', (e)=>{
Expand All @@ -106,7 +113,6 @@ export default class MLocationBody extends React.Component<IBodyProps, IState> {
return <div className="mx_MLocationBody">
<div id={this.getBodyId()} className="mx_MLocationBody_map" />
{ error }
<span className="mx_EventTile_body">{ this.description }</span>
</div>;
}
}
1 change: 1 addition & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2103,6 +2103,7 @@
"edited": "edited",
"Submit logs": "Submit logs",
"Can't load this message": "Can't load this message",
"Share custom location": "Share custom location",
"Share my current location as a once off": "Share my current location as a once off",
"My location": "My location",
"Type of location share": "Type of location share",
Expand Down

0 comments on commit 684b061

Please sign in to comment.