mv element.io @types __mocks__/ debian docker module_system/ playwright res src test webapp Dockerfile .dockerignore .eslintignore .stylelintrc.cjs babel.config.cjs recorder-worklet-loader.cjs .modernizr.json components.json config.json config.sample.json package.json project.json tsconfig.json tsconfig.module_system.json jest.config.ts playwright.config.ts webpack.config.ts build_config.sample.yaml apps/web/

mkdir apps/web/scripts
mv scripts/{cleanup.sh,ci_package.sh,copy-res.ts,deploy.py,package.sh} apps/web/scripts

And a couple of gitignore tweaks

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2026-02-24 15:43:58 +00:00
parent e7509c92a1
commit 91a3cb03c1
3408 changed files with 28 additions and 32 deletions
@@ -0,0 +1,28 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { _t } from "../../languageHandler";
export enum LocationShareError {
MapStyleUrlNotConfigured = "MapStyleUrlNotConfigured",
MapStyleUrlNotReachable = "MapStyleUrlNotReachable",
WebGLNotEnabled = "WebGLNotEnabled",
Default = "Default",
}
export const getLocationShareErrorMessage = (errorType?: LocationShareError): string => {
switch (errorType) {
case LocationShareError.MapStyleUrlNotConfigured:
return _t("location_sharing|MapStyleUrlNotConfigured");
case LocationShareError.WebGLNotEnabled:
return _t("location_sharing|WebGLNotEnabled");
case LocationShareError.MapStyleUrlNotReachable:
default:
return _t("location_sharing|MapStyleUrlNotReachable");
}
};
@@ -0,0 +1,30 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import SdkConfig from "../../SdkConfig";
import { getTileServerWellKnown } from "../WellKnownUtils";
import { LocationShareError } from "./LocationShareErrors";
/**
* Look up what map tile server style URL was provided in the homeserver's
* .well-known location, or, failing that, in our local config, or, failing
* that, defaults to the same tile server listed by matrix.org.
*/
export function findMapStyleUrl(matrixClient: MatrixClient): string {
const mapStyleUrl = getTileServerWellKnown(matrixClient)?.map_style_url ?? SdkConfig.get().map_style_url;
if (!mapStyleUrl) {
logger.error("'map_style_url' missing from homeserver .well-known area, and missing from from config.json.");
throw new Error(LocationShareError.MapStyleUrlNotConfigured);
}
return mapStyleUrl;
}
+15
View File
@@ -0,0 +1,15 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
export * from "./findMapStyleUrl";
export * from "./isSelfLocation";
export * from "./locationEventGeoUri";
export * from "./LocationShareErrors";
export * from "./links";
export * from "./parseGeoUri";
export * from "./positionFailureMessage";
@@ -0,0 +1,15 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { type ILocationContent, LocationAssetType, M_ASSET } from "matrix-js-sdk/src/matrix";
export const isSelfLocation = (locationContent: ILocationContent): boolean => {
const asset = M_ASSET.findIn(locationContent) as { type: string };
const assetType = asset?.type ?? LocationAssetType.Self;
return assetType == LocationAssetType.Self;
};
+39
View File
@@ -0,0 +1,39 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { type MatrixEvent, M_LOCATION } from "matrix-js-sdk/src/matrix";
import { parseGeoUri } from "./parseGeoUri";
export const makeMapSiteLink = (coords: GeolocationCoordinates): string => {
return (
"https://www.openstreetmap.org/" +
`?mlat=${coords.latitude}` +
`&mlon=${coords.longitude}` +
`#map=16/${coords.latitude}/${coords.longitude}`
);
};
export const createMapSiteLinkFromEvent = (event: MatrixEvent): string | null => {
const content = event.getContent();
const mLocation = content[M_LOCATION.name];
if (mLocation !== undefined) {
const uri = mLocation["uri"];
if (uri !== undefined) {
const geoCoords = parseGeoUri(uri);
return geoCoords ? makeMapSiteLink(geoCoords) : null;
}
} else {
const geoUri = content["geo_uri"];
if (geoUri) {
const geoCoords = parseGeoUri(geoUri);
return geoCoords ? makeMapSiteLink(geoCoords) : null;
}
}
return null;
};
@@ -0,0 +1,24 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { type MatrixEvent, M_LOCATION, type MLocationEvent } from "matrix-js-sdk/src/matrix";
type LocationEvent = { geo_uri: string } & MLocationEvent;
/**
* Find the geo-URI contained within a location event.
*/
export const locationEventGeoUri = (mxEvent: MatrixEvent): string => {
// unfortunately we're stuck supporting legacy `content.geo_uri`
// events until the end of days, or until we figure out mutable
// events - so folks can read their old chat history correctly.
// https://github.com/matrix-org/matrix-doc/issues/3516
const content = mxEvent.getContent<LocationEvent>();
const loc = M_LOCATION.findIn(content);
return loc?.uri ?? content["geo_uri"];
};
+68
View File
@@ -0,0 +1,68 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import * as maplibregl from "maplibre-gl";
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../languageHandler";
import { findMapStyleUrl } from "./findMapStyleUrl";
import { LocationShareError } from "./LocationShareErrors";
export const createMap = (
client: MatrixClient,
interactive: boolean,
bodyId: string,
onError?: (error: Error) => void,
): maplibregl.Map => {
try {
const styleUrl = findMapStyleUrl(client);
const map = new maplibregl.Map({
container: bodyId,
style: styleUrl,
zoom: 15,
interactive,
attributionControl: false,
locale: {
"AttributionControl.ToggleAttribution": _t("location_sharing|toggle_attribution"),
"AttributionControl.MapFeedback": _t("location_sharing|map_feedback"),
"FullscreenControl.Enter": _t("action|enter_fullscreen"),
"FullscreenControl.Exit": _t("action|exit_fullscreeen"),
"GeolocateControl.FindMyLocation": _t("location_sharing|find_my_location"),
"GeolocateControl.LocationNotAvailable": _t("location_sharing|location_not_available"),
"LogoControl.Title": _t("location_sharing|mapbox_logo"),
"NavigationControl.ResetBearing": _t("location_sharing|reset_bearing"),
"NavigationControl.ZoomIn": _t("action|zoom_in"),
"NavigationControl.ZoomOut": _t("action|zoom_out"),
},
});
map.addControl(new maplibregl.AttributionControl(), "top-right");
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);
onError?.(new Error(LocationShareError.MapStyleUrlNotReachable));
});
return map;
} catch (e) {
logger.error("Failed to render map", e);
const errorMessage = (e as Error)?.message;
if (errorMessage.includes("Failed to initialize WebGL")) throw new Error(LocationShareError.WebGLNotEnabled);
throw e;
}
};
export const createMarker = (coords: GeolocationCoordinates, element: HTMLElement): maplibregl.Marker => {
const marker = new maplibregl.Marker({
element,
anchor: "bottom",
offset: [0, -1],
}).setLngLat({ lon: coords.longitude, lat: coords.latitude });
return marker;
};
@@ -0,0 +1,49 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
export const parseGeoUri = (uri: string): GeolocationCoordinates | undefined => {
function parse(s: string): number | null {
const ret = parseFloat(s);
if (Number.isNaN(ret)) {
return null;
} else {
return ret;
}
}
const m = uri.match(/^\s*geo:(.*?)\s*$/);
if (!m) return;
const parts = m[1].split(";");
const coords = parts[0].split(",");
let uncertainty: number | null | undefined = undefined;
for (const param of parts.slice(1)) {
const m = param.match(/u=(.*)/);
if (m) uncertainty = parse(m[1]);
}
const latitude = parse(coords[0]);
const longitude = parse(coords[1]);
if (latitude === null || longitude === null) {
return;
}
const geoCoords = {
latitude: latitude!,
longitude: longitude!,
altitude: parse(coords[2]),
accuracy: uncertainty!,
altitudeAccuracy: null,
heading: null,
speed: null,
};
return {
toJSON: () => geoCoords,
...geoCoords,
};
};
@@ -0,0 +1,29 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { _t } from "../../languageHandler";
import SdkConfig from "../../SdkConfig";
/**
* Get a localised error message for GeolocationPositionError error codes
* @param code - error code from GeolocationPositionError
* @returns
*/
export const positionFailureMessage = (code: number): string | undefined => {
const brand = SdkConfig.get().brand;
switch (code) {
case 1:
return _t("location_sharing|failed_permission", { brand });
case 2:
return _t("location_sharing|failed_generic");
case 3:
return _t("location_sharing|failed_timeout");
case 4:
return _t("location_sharing|failed_unknown");
}
};
+55
View File
@@ -0,0 +1,55 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { useEffect, useState } from "react";
import type { Map as MapLibreMap } from "maplibre-gl";
import { createMap } from "./map";
import { useMatrixClientContext } from "../../contexts/MatrixClientContext";
interface UseMapProps {
bodyId: string;
onError?: (error: Error) => void;
interactive?: boolean;
}
/**
* Create a map instance
* Add listeners for errors
* Make sure `onError` has a stable reference
* As map is recreated on changes to it
*/
export const useMap = ({ interactive, bodyId, onError }: UseMapProps): MapLibreMap | undefined => {
const cli = useMatrixClientContext();
const [map, setMap] = useState<MapLibreMap>();
useEffect(
() => {
let map: MapLibreMap | undefined;
try {
map = createMap(cli, !!interactive, bodyId, onError);
setMap(map);
} catch (error) {
console.error("Error encountered in useMap", error);
if (error instanceof Error) {
onError?.(error);
}
}
return () => {
if (map) {
map.remove();
setMap(undefined);
}
};
},
// map is excluded as a dependency
[cli, interactive, bodyId, onError],
);
return map;
};