Apply strictNullChecks to src/components/views/location/* (#10249
* strict fixes * accessiblebutton without onClick explicit * strict fix for UserMenu BaseAvatar
This commit is contained in:
parent
6de8d85f7e
commit
dd6fc124d7
12 changed files with 46 additions and 31 deletions
|
@ -432,7 +432,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
public render(): React.ReactNode {
|
||||
const avatarSize = 32; // should match border-radius of the avatar
|
||||
|
||||
const userId = MatrixClientPeg.get().getUserId();
|
||||
const userId = MatrixClientPeg.get().getSafeUserId();
|
||||
const displayName = OwnProfileStore.instance.displayName || userId;
|
||||
const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ import { toPx } from "../../../utils/units";
|
|||
import { _t } from "../../../languageHandler";
|
||||
|
||||
interface IProps {
|
||||
name: string; // The name (first initial used as default)
|
||||
name?: string; // The name (first initial used as default)
|
||||
idName?: string; // ID for generating hash colours
|
||||
title?: string; // onHover title text
|
||||
url?: string; // highest priority of them all, shortcut to set in urls[0]
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { ReactElement, SyntheticEvent, useContext } from "react";
|
||||
import React, { ReactNode, SyntheticEvent, useContext } from "react";
|
||||
import classNames from "classnames";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { IEventRelation } from "matrix-js-sdk/src/models/event";
|
||||
|
@ -41,9 +41,9 @@ export const LocationButton: React.FC<IProps> = ({ roomId, sender, menuPosition,
|
|||
overflowMenuCloser?.();
|
||||
};
|
||||
|
||||
let contextMenu: ReactElement;
|
||||
let contextMenu: ReactNode = null;
|
||||
if (menuDisplayed) {
|
||||
const position = menuPosition ?? aboveLeftOf(button.current.getBoundingClientRect());
|
||||
const position = menuPosition ?? (button.current && aboveLeftOf(button.current.getBoundingClientRect())) ?? {};
|
||||
|
||||
contextMenu = (
|
||||
<LocationShareMenu
|
||||
|
|
|
@ -52,9 +52,9 @@ const isSharingOwnLocation = (shareType: LocationShareType): boolean =>
|
|||
class LocationPicker extends React.Component<ILocationPickerProps, IState> {
|
||||
public static contextType = MatrixClientContext;
|
||||
public context!: React.ContextType<typeof MatrixClientContext>;
|
||||
private map?: maplibregl.Map = null;
|
||||
private geolocate?: maplibregl.GeolocateControl = null;
|
||||
private marker?: maplibregl.Marker = null;
|
||||
private map?: maplibregl.Map;
|
||||
private geolocate?: maplibregl.GeolocateControl;
|
||||
private marker?: maplibregl.Marker;
|
||||
|
||||
public constructor(props: ILocationPickerProps) {
|
||||
super(props);
|
||||
|
@ -100,7 +100,7 @@ class LocationPicker extends React.Component<ILocationPickerProps, IState> {
|
|||
});
|
||||
|
||||
this.map.on("load", () => {
|
||||
this.geolocate.trigger();
|
||||
this.geolocate?.trigger();
|
||||
});
|
||||
|
||||
this.geolocate.on("error", this.onGeolocateError);
|
||||
|
@ -120,7 +120,7 @@ class LocationPicker extends React.Component<ILocationPickerProps, IState> {
|
|||
} catch (e) {
|
||||
logger.error("Failed to render map", e);
|
||||
const errorType =
|
||||
e?.message === LocationShareError.MapStyleUrlNotConfigured
|
||||
(e as Error)?.message === LocationShareError.MapStyleUrlNotConfigured
|
||||
? LocationShareError.MapStyleUrlNotConfigured
|
||||
: LocationShareError.Default;
|
||||
this.setState({ error: errorType });
|
||||
|
@ -141,7 +141,7 @@ class LocationPicker extends React.Component<ILocationPickerProps, IState> {
|
|||
offset: [0, -1],
|
||||
})
|
||||
.setLngLat(new maplibregl.LngLat(0, 0))
|
||||
.addTo(this.map);
|
||||
.addTo(this.map!);
|
||||
};
|
||||
|
||||
private updateStyleUrl = (clientWellKnown: IClientWellKnown): void => {
|
||||
|
|
|
@ -64,14 +64,15 @@ const LocationShareMenu: React.FC<Props> = ({ menuPosition, onFinished, sender,
|
|||
);
|
||||
|
||||
const displayName = OwnProfileStore.instance.displayName;
|
||||
const userId = matrixClient.getSafeUserId();
|
||||
|
||||
const onLocationSubmit =
|
||||
shareType === LocationShareType.Live
|
||||
? shareLiveLocation(matrixClient, roomId, displayName, openMenu)
|
||||
: shareLocation(matrixClient, roomId, shareType, relation, openMenu);
|
||||
? shareLiveLocation(matrixClient, roomId, displayName || userId, openMenu)
|
||||
: shareLocation(matrixClient, roomId, shareType ?? LocationShareType.Own, relation, openMenu);
|
||||
|
||||
const onLiveShareEnableSubmit = (): void => {
|
||||
SettingsStore.setValue("feature_location_share_live", undefined, SettingLevel.DEVICE, true);
|
||||
SettingsStore.setValue("feature_location_share_live", null, SettingLevel.DEVICE, true);
|
||||
};
|
||||
|
||||
const shouldAdvertiseLiveLabsFlag = shareType === LocationShareType.Live && !isLiveShareEnabled;
|
||||
|
|
|
@ -31,7 +31,7 @@ interface IProps extends IDialogProps {
|
|||
}
|
||||
|
||||
interface IState {
|
||||
error: Error;
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,7 +58,7 @@ export default class LocationViewDialog extends React.Component<IProps, IState>
|
|||
const { mxEvent } = this.props;
|
||||
|
||||
// only pass member to marker when should render avatar marker
|
||||
const markerRoomMember = isSelfLocation(mxEvent.getContent()) ? mxEvent.sender : undefined;
|
||||
const markerRoomMember = (isSelfLocation(mxEvent.getContent()) && mxEvent.sender) || undefined;
|
||||
const geoUri = locationEventGeoUri(mxEvent);
|
||||
return (
|
||||
<BaseDialog className="mx_LocationViewDialog" onFinished={this.props.onFinished} fixedWidth={false}>
|
||||
|
|
|
@ -70,6 +70,9 @@ const useMapWithStyle = ({
|
|||
if (map && centerGeoUri) {
|
||||
try {
|
||||
const coords = parseGeoUri(centerGeoUri);
|
||||
if (!coords) {
|
||||
throw new Error("Invalid geo URI");
|
||||
}
|
||||
map.setCenter({ lon: coords.longitude, lat: coords.latitude });
|
||||
} catch (_error) {
|
||||
logger.error("Could not set map center");
|
||||
|
|
|
@ -20,7 +20,7 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
|||
import { _t } from "../../../languageHandler";
|
||||
import { OwnProfileStore } from "../../../stores/OwnProfileStore";
|
||||
import BaseAvatar from "../avatars/BaseAvatar";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
|
||||
import Heading from "../typography/Heading";
|
||||
import { Icon as LocationIcon } from "../../../../res/img/element-icons/location.svg";
|
||||
import { LocationShareType } from "./shareLocation";
|
||||
|
@ -28,11 +28,11 @@ import StyledLiveBeaconIcon from "../beacon/StyledLiveBeaconIcon";
|
|||
|
||||
const UserAvatar: React.FC = () => {
|
||||
const matrixClient = useContext(MatrixClientContext);
|
||||
const userId = matrixClient.getUserId();
|
||||
const displayName = OwnProfileStore.instance.displayName;
|
||||
const userId = matrixClient.getSafeUserId();
|
||||
const displayName = OwnProfileStore.instance.displayName ?? undefined;
|
||||
// 40 - 2px border
|
||||
const avatarSize = 36;
|
||||
const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize);
|
||||
const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize) ?? undefined;
|
||||
|
||||
return (
|
||||
<div className={`mx_ShareType_option-icon ${LocationShareType.Own}`}>
|
||||
|
@ -49,9 +49,13 @@ const UserAvatar: React.FC = () => {
|
|||
);
|
||||
};
|
||||
|
||||
type ShareTypeOptionProps = HTMLAttributes<Element> & { label: string; shareType: LocationShareType };
|
||||
type ShareTypeOptionProps = HTMLAttributes<Element> & {
|
||||
label: string;
|
||||
shareType: LocationShareType;
|
||||
onClick?: ((e: ButtonEvent) => void | Promise<void>) | null;
|
||||
};
|
||||
const ShareTypeOption: React.FC<ShareTypeOptionProps> = ({ onClick, label, shareType, ...rest }) => (
|
||||
<AccessibleButton element="button" className="mx_ShareType_option" onClick={onClick} {...rest}>
|
||||
<AccessibleButton element="button" className="mx_ShareType_option" onClick={onClick ?? null} {...rest}>
|
||||
{shareType === LocationShareType.Own && <UserAvatar />}
|
||||
{shareType === LocationShareType.Pin && (
|
||||
<LocationIcon className={`mx_ShareType_option-icon ${LocationShareType.Pin}`} />
|
||||
|
|
|
@ -33,9 +33,11 @@ const useMapMarker = (
|
|||
return;
|
||||
}
|
||||
const coords = parseGeoUri(geoUri);
|
||||
const newMarker = createMarker(coords, element);
|
||||
newMarker.addTo(map);
|
||||
setMarker(newMarker);
|
||||
if (coords) {
|
||||
const newMarker = createMarker(coords, element);
|
||||
newMarker.addTo(map);
|
||||
setMarker(newMarker);
|
||||
}
|
||||
},
|
||||
[marker, geoUri, map],
|
||||
);
|
||||
|
@ -43,7 +45,9 @@ const useMapMarker = (
|
|||
useEffect(() => {
|
||||
if (marker) {
|
||||
const coords = parseGeoUri(geoUri);
|
||||
marker.setLngLat({ lon: coords.longitude, lat: coords.latitude });
|
||||
if (coords) {
|
||||
marker.setLngLat({ lon: coords.longitude, lat: coords.latitude });
|
||||
}
|
||||
}
|
||||
}, [marker, geoUri]);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import { IContent } from "matrix-js-sdk/src/matrix";
|
||||
import { MatrixError } from "matrix-js-sdk/src/http-api";
|
||||
import { makeLocationContent, makeBeaconInfoContent } from "matrix-js-sdk/src/content-helpers";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
@ -94,7 +95,7 @@ const getDefaultErrorParams = (
|
|||
return { modalParams, errorMessage };
|
||||
};
|
||||
|
||||
const handleShareError = (error: Error, openMenu: () => void, shareType: LocationShareType): void => {
|
||||
const handleShareError = (error: unknown, openMenu: () => void, shareType: LocationShareType): void => {
|
||||
const { modalParams, errorMessage } =
|
||||
(error as MatrixError).errcode === "M_FORBIDDEN"
|
||||
? getPermissionsErrorParams(shareType)
|
||||
|
@ -135,9 +136,9 @@ export const shareLocation =
|
|||
async ({ uri, timestamp }): Promise<void> => {
|
||||
if (!uri) return;
|
||||
try {
|
||||
const threadId = relation?.rel_type === THREAD_RELATION_TYPE.name ? relation.event_id : null;
|
||||
const threadId = (relation?.rel_type === THREAD_RELATION_TYPE.name && relation?.event_id) || null;
|
||||
const assetType = shareType === LocationShareType.Pin ? LocationAssetType.Pin : LocationAssetType.Self;
|
||||
const content = makeLocationContent(undefined, uri, timestamp, undefined, assetType);
|
||||
const content = makeLocationContent(undefined, uri, timestamp, undefined, assetType) as IContent;
|
||||
await doMaybeLocalRoomAction(
|
||||
roomId,
|
||||
(actualRoomId: string) => client.sendMessage(actualRoomId, threadId, content),
|
||||
|
|
|
@ -33,6 +33,7 @@ import { LocationShareType } from "../../../../src/components/views/location/sha
|
|||
import {
|
||||
flushPromisesWithFakeTimers,
|
||||
getMockClientWithEventEmitter,
|
||||
mockClientMethodsUser,
|
||||
setupAsyncStoreWithClient,
|
||||
} from "../../../test-utils";
|
||||
import Modal from "../../../../src/Modal";
|
||||
|
@ -74,7 +75,7 @@ jest.mock("../../../../src/Modal", () => ({
|
|||
describe("<LocationShareMenu />", () => {
|
||||
const userId = "@ernie:server.org";
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
getUserId: jest.fn().mockReturnValue(userId),
|
||||
...mockClientMethodsUser(userId),
|
||||
getClientWellKnown: jest.fn().mockResolvedValue({
|
||||
map_style_url: "maps.com",
|
||||
}),
|
||||
|
@ -334,7 +335,7 @@ describe("<LocationShareMenu />", () => {
|
|||
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledWith(
|
||||
"feature_location_share_live",
|
||||
undefined,
|
||||
null,
|
||||
SettingLevel.DEVICE,
|
||||
true,
|
||||
);
|
||||
|
|
|
@ -48,6 +48,7 @@ jest.mock("../../../../src/customisations/helpers/UIComponents", () => ({
|
|||
describe("<SpacePanel />", () => {
|
||||
const mockClient = {
|
||||
getUserId: jest.fn().mockReturnValue("@test:test"),
|
||||
getSafeUserId: jest.fn().mockReturnValue("@test:test"),
|
||||
isGuest: jest.fn(),
|
||||
getAccountData: jest.fn(),
|
||||
} as unknown as MatrixClient;
|
||||
|
|
Loading…
Reference in a new issue