CI / Build & Quality Checks (pull_request) Successful in 3m19s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 11s
CI / Playwright smoke (e2e) (pull_request) Successful in 14m32s
The composer's location button sent the exact position (6 decimals) from a single click once the browser permission had been granted, discarding the fix's accuracy, so a ±3.5 km Wi-Fi/IP fix was shown as exact. - ShareLocationDialog: "Share your location?" with the coordinates and ±accuracy, a "Check on OpenStreetMap" link, and Cancel / Send approximate (~1 km) / Send. Focus starts on Cancel; Esc cancels. - utils/geoShare.ts (unit-tested): RFC 5870 geo URI with `;u=` accuracy; approximate shares round to 2 decimals and never claim better than 1 km. - Location cards show the ± when the event carries `u=`. - The toolbar icon is a pin instead of the globe. Verified headless (fix 40.748817,-73.985428 ±3500 m): the click opens the dialog and sends nothing; Cancel/Esc send nothing; Send approximate → geo:40.75,-73.99;u=3500; Send → geo:40.748817,-73.985428;u=3500; the card reads "40.74882, -73.98543 (±3.5 km)". Fixes #340 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
125 lines
4.1 KiB
TypeScript
125 lines
4.1 KiB
TypeScript
import React from 'react';
|
|
import FocusTrap from 'focus-trap-react';
|
|
import {
|
|
Box,
|
|
Button,
|
|
config,
|
|
Dialog,
|
|
Header,
|
|
Icon,
|
|
IconButton,
|
|
Icons,
|
|
Overlay,
|
|
OverlayBackdrop,
|
|
OverlayCenter,
|
|
Text,
|
|
} from 'folds';
|
|
import { useModalStyle } from '../../hooks/useModalStyle';
|
|
import { stopPropagation } from '../../utils/keyboard';
|
|
import { formatAccuracy } from '../../utils/geoShare';
|
|
|
|
export type PendingLocation = { latitude: number; longitude: number; accuracy?: number };
|
|
|
|
type ShareLocationDialogProps = {
|
|
location: PendingLocation;
|
|
roomName: string;
|
|
onSend: (approximate: boolean) => void;
|
|
requestClose: () => void;
|
|
};
|
|
|
|
/**
|
|
* [Gitea #340] Confirm step before an m.location is posted: the toolbar button
|
|
* used to send the exact position from a single click. Shows what will be
|
|
* shared (coordinates + the fix's accuracy) and offers an approximate share.
|
|
*/
|
|
export function ShareLocationDialog({
|
|
location,
|
|
roomName,
|
|
onSend,
|
|
requestClose,
|
|
}: ShareLocationDialogProps) {
|
|
const modalStyle = useModalStyle(420);
|
|
const { latitude, longitude, accuracy } = location;
|
|
const accuracyLabel = formatAccuracy(accuracy);
|
|
const mapUrl = `https://www.openstreetmap.org/?mlat=${latitude}&mlon=${longitude}#map=16/${latitude}/${longitude}`;
|
|
|
|
return (
|
|
<Overlay open backdrop={<OverlayBackdrop />}>
|
|
<OverlayCenter>
|
|
<FocusTrap
|
|
focusTrapOptions={{
|
|
initialFocus: '#share-location-cancel',
|
|
onDeactivate: requestClose,
|
|
clickOutsideDeactivates: true,
|
|
escapeDeactivates: stopPropagation,
|
|
}}
|
|
>
|
|
<Dialog
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="share-location-title"
|
|
variant="Surface"
|
|
style={modalStyle}
|
|
>
|
|
<Header
|
|
style={{
|
|
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
|
|
borderBottomWidth: config.borderWidth.B300,
|
|
}}
|
|
variant="Surface"
|
|
size="500"
|
|
>
|
|
<Box grow="Yes">
|
|
<Text id="share-location-title" as="h2" size="H4">
|
|
Share your location?
|
|
</Text>
|
|
</Box>
|
|
<IconButton size="300" onClick={requestClose} radii="300" aria-label="Close">
|
|
<Icon src={Icons.Cross} />
|
|
</IconButton>
|
|
</Header>
|
|
<Box style={{ padding: config.space.S400 }} direction="Column" gap="400">
|
|
<Text>
|
|
Everyone in <b>{roomName}</b> will see this position, and it can't be taken
|
|
back from their devices once sent.
|
|
</Text>
|
|
<Box direction="Column" gap="100">
|
|
<Text size="T400">
|
|
<b>
|
|
{latitude.toFixed(5)}, {longitude.toFixed(5)}
|
|
</b>
|
|
{accuracyLabel && ` (${accuracyLabel})`}
|
|
</Text>
|
|
<Text size="T200" priority="300">
|
|
{accuracyLabel
|
|
? 'The ± is how sure your device is of this position.'
|
|
: 'Your device did not say how accurate this position is.'}{' '}
|
|
<a href={mapUrl} target="_blank" rel="noreferrer noopener">
|
|
Check on OpenStreetMap
|
|
</a>
|
|
</Text>
|
|
</Box>
|
|
<Box gap="200" justifyContent="End" wrap="Wrap">
|
|
<Button
|
|
id="share-location-cancel"
|
|
variant="Secondary"
|
|
fill="Soft"
|
|
onClick={requestClose}
|
|
>
|
|
<Text size="B400">Cancel</Text>
|
|
</Button>
|
|
<Button variant="Secondary" fill="Soft" onClick={() => onSend(true)}>
|
|
<Text size="B400">Send approximate (~1 km)</Text>
|
|
</Button>
|
|
<Button variant="Primary" onClick={() => onSend(false)}>
|
|
<Text size="B400">Send</Text>
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
</Dialog>
|
|
</FocusTrap>
|
|
</OverlayCenter>
|
|
</Overlay>
|
|
);
|
|
}
|