Tidy location code (#7402)
This commit is contained in:
parent
fb494a5098
commit
670d7824ec
4 changed files with 82 additions and 31 deletions
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, { SyntheticEvent } from 'react';
|
||||||
import maplibregl from 'maplibre-gl';
|
import maplibregl from 'maplibre-gl';
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
@ -40,16 +40,36 @@ const LocationShareTypeDropdown = ({
|
||||||
onChange,
|
onChange,
|
||||||
}: IDropdownProps) => {
|
}: IDropdownProps) => {
|
||||||
const options = [
|
const options = [
|
||||||
<div key={LocationShareType.Custom}>{ _t("Share custom location") }</div>,
|
<div key={LocationShareType.Custom}>{
|
||||||
<div key={LocationShareType.OnceOff}>{ _t("Share my current location as a once off") }</div>,
|
_t("Share custom location")
|
||||||
// <div key={LocationShareType.OneMin}>{ _t("Share my current location for one minute") }</div>,
|
}</div>,
|
||||||
// <div key={LocationShareType.FiveMins}>{ _t("Share my current location for five minutes") }</div>,
|
<div key={LocationShareType.OnceOff}>{
|
||||||
// <div key={LocationShareType.ThirtyMins}>{ _t("Share my current location for thirty minutes") }</div>,
|
_t("Share my current location as a once off")
|
||||||
// <div key={LocationShareType.OneHour}>{ _t("Share my current location for one hour") }</div>,
|
}</div>,
|
||||||
// <div key={LocationShareType.ThreeHours}>{ _t("Share my current location for three hours") }</div>,
|
// <div key={LocationShareType.OneMin}>{
|
||||||
// <div key={LocationShareType.SixHours}>{ _t("Share my current location for six hours") }</div>,
|
// _t("Share my current location for one minute")
|
||||||
// <div key={LocationShareType.OneDay}>{ _t("Share my current location for one day") }</div>,
|
// }</div>,
|
||||||
// <div key={LocationShareType.Forever}>{ _t("Share my current location until I disable it") }</div>,
|
// <div key={LocationShareType.FiveMins}>{
|
||||||
|
// _t("Share my current location for five minutes")
|
||||||
|
// }</div>,
|
||||||
|
// <div key={LocationShareType.ThirtyMins}>{
|
||||||
|
// _t("Share my current location for thirty minutes")
|
||||||
|
// }</div>,
|
||||||
|
// <div key={LocationShareType.OneHour}>{
|
||||||
|
// _t("Share my current location for one hour")
|
||||||
|
// }</div>,
|
||||||
|
// <div key={LocationShareType.ThreeHours}>{
|
||||||
|
// _t("Share my current location for three hours")
|
||||||
|
// }</div>,
|
||||||
|
// <div key={LocationShareType.SixHours}>{
|
||||||
|
// _t("Share my current location for six hours")
|
||||||
|
// }</div>,
|
||||||
|
// <div key={LocationShareType.OneDay}>{
|
||||||
|
// _t("Share my current location for one day")
|
||||||
|
// }</div>,
|
||||||
|
// <div key={LocationShareType.Forever}>{
|
||||||
|
// _t("Share my current location until I disable it")
|
||||||
|
// }</div>,
|
||||||
];
|
];
|
||||||
|
|
||||||
return <Dropdown
|
return <Dropdown
|
||||||
|
@ -67,8 +87,13 @@ const LocationShareTypeDropdown = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
onChoose(uri: string, ts: number, type: LocationShareType, description: string): boolean;
|
onChoose(
|
||||||
onFinished();
|
uri: string,
|
||||||
|
ts: number,
|
||||||
|
type: LocationShareType,
|
||||||
|
description: string,
|
||||||
|
): boolean;
|
||||||
|
onFinished(ev?: SyntheticEvent): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -85,7 +110,7 @@ class LocationPicker extends React.Component<IProps, IState> {
|
||||||
private marker: maplibregl.Marker;
|
private marker: maplibregl.Marker;
|
||||||
private geolocate: maplibregl.GeolocateControl;
|
private geolocate: maplibregl.GeolocateControl;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props: IProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -117,8 +142,11 @@ class LocationPicker extends React.Component<IProps, IState> {
|
||||||
this.map.addControl(this.geolocate);
|
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",
|
logger.error(
|
||||||
e.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.setState({ error: e.error });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -246,7 +274,10 @@ class LocationPicker extends React.Component<IProps, IState> {
|
||||||
<DialogButtons primaryButton={_t('Share')}
|
<DialogButtons primaryButton={_t('Share')}
|
||||||
onPrimaryButtonClick={this.onOk}
|
onPrimaryButtonClick={this.onOk}
|
||||||
onCancel={this.props.onFinished}
|
onCancel={this.props.onFinished}
|
||||||
primaryDisabled={!this.state.position && !this.state.manualPosition} />
|
primaryDisabled={
|
||||||
|
!this.state.position &&
|
||||||
|
!this.state.manualPosition
|
||||||
|
} />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -255,12 +286,19 @@ class LocationPicker extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getGeoUri(position: GeolocationPosition): string {
|
export function getGeoUri(position: GeolocationPosition): string {
|
||||||
return (`geo:${ position.coords.latitude },` +
|
const lat = position.coords.latitude;
|
||||||
position.coords.longitude +
|
const lon = position.coords.longitude;
|
||||||
( position.coords.altitude !== undefined ?
|
const alt = (
|
||||||
`,${ position.coords.altitude }` : '' ) +
|
position.coords.altitude !== undefined
|
||||||
( position.coords.accuracy !== undefined ?
|
? `,${position.coords.altitude}`
|
||||||
`;u=${ position.coords.accuracy }` : '' ));
|
: ""
|
||||||
|
);
|
||||||
|
const acc = (
|
||||||
|
position.coords.accuracy !== undefined
|
||||||
|
? `;u=${ position.coords.accuracy }`
|
||||||
|
: ""
|
||||||
|
);
|
||||||
|
return `geo:${lat},${lon}${alt}${acc}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LocationPicker;
|
export default LocationPicker;
|
||||||
|
|
|
@ -55,7 +55,8 @@ export default class MLocationBody extends React.Component<IBodyProps, IState> {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const config = SdkConfig.get();
|
const config = SdkConfig.get();
|
||||||
const coordinates = new maplibregl.LngLat(this.coords.longitude, this.coords.latitude);
|
const coordinates = new maplibregl.LngLat(
|
||||||
|
this.coords.longitude, this.coords.latitude);
|
||||||
|
|
||||||
this.map = new maplibregl.Map({
|
this.map = new maplibregl.Map({
|
||||||
container: this.getBodyId(),
|
container: this.getBodyId(),
|
||||||
|
@ -74,7 +75,11 @@ export default class MLocationBody extends React.Component<IBodyProps, IState> {
|
||||||
.addTo(this.map);
|
.addTo(this.map);
|
||||||
|
|
||||||
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);
|
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.setState({ error: e.error });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
import React, { ComponentProps, createRef } from 'react';
|
import React, { ComponentProps, createRef, ReactElement } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { MatrixEvent, IEventRelation } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent, IEventRelation } from "matrix-js-sdk/src/models/event";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
@ -138,13 +138,21 @@ interface ILocationButtonProps extends Pick<ICollapsibleButtonProps, "narrowMode
|
||||||
narrowMode: boolean;
|
narrowMode: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LocationButton: React.FC<ILocationButtonProps> = ({ shareLocation, menuPosition, narrowMode }) => {
|
const LocationButton: React.FC<ILocationButtonProps> = (
|
||||||
|
{ shareLocation, menuPosition, narrowMode },
|
||||||
|
) => {
|
||||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
||||||
|
|
||||||
let contextMenu;
|
let contextMenu: ReactElement;
|
||||||
if (menuDisplayed) {
|
if (menuDisplayed) {
|
||||||
const position = menuPosition ?? aboveLeftOf(button.current.getBoundingClientRect());
|
const position = menuPosition ?? aboveLeftOf(
|
||||||
contextMenu = <ContextMenu {...position} onFinished={closeMenu} managed={false}>
|
button.current.getBoundingClientRect());
|
||||||
|
|
||||||
|
contextMenu = <ContextMenu
|
||||||
|
{...position}
|
||||||
|
onFinished={closeMenu}
|
||||||
|
managed={false}
|
||||||
|
>
|
||||||
<LocationPicker onChoose={shareLocation} onFinished={closeMenu} />
|
<LocationPicker onChoose={shareLocation} onFinished={closeMenu} />
|
||||||
</ContextMenu>;
|
</ContextMenu>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import "../../../skinned-sdk";
|
import "../../../skinned-sdk"; // Must be first for skinning to work
|
||||||
import { getGeoUri } from "../../../../src/components/views/location/LocationPicker";
|
import { getGeoUri } from "../../../../src/components/views/location/LocationPicker";
|
||||||
|
|
||||||
describe("LocationPicker", () => {
|
describe("LocationPicker", () => {
|
||||||
|
|
Loading…
Reference in a new issue