Eliminate the use of MatrixClientPeg in utils (#10910)
This commit is contained in:
parent
a0c2676c38
commit
30429df948
108 changed files with 409 additions and 325 deletions
|
@ -436,15 +436,18 @@ export default class ContentMessages {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
promBefore = doMaybeLocalRoomAction(roomId, (actualRoomId) =>
|
promBefore = doMaybeLocalRoomAction(
|
||||||
this.sendContentToRoom(
|
roomId,
|
||||||
file,
|
(actualRoomId) =>
|
||||||
actualRoomId,
|
this.sendContentToRoom(
|
||||||
relation,
|
file,
|
||||||
matrixClient,
|
actualRoomId,
|
||||||
replyToEvent ?? undefined,
|
relation,
|
||||||
loopPromiseBefore,
|
matrixClient,
|
||||||
),
|
replyToEvent ?? undefined,
|
||||||
|
loopPromiseBefore,
|
||||||
|
),
|
||||||
|
matrixClient,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -301,7 +301,7 @@ export default class DeviceListener {
|
||||||
} else {
|
} else {
|
||||||
// No cross-signing or key backup on account (set up encryption)
|
// No cross-signing or key backup on account (set up encryption)
|
||||||
await cli.waitForClientWellKnown();
|
await cli.waitForClientWellKnown();
|
||||||
if (isSecureBackupRequired() && isLoggedIn()) {
|
if (isSecureBackupRequired(cli) && isLoggedIn()) {
|
||||||
// If we're meant to set up, and Secure Backup is required,
|
// If we're meant to set up, and Secure Backup is required,
|
||||||
// trigger the flow directly without a toast once logged in.
|
// trigger the flow directly without a toast once logged in.
|
||||||
hideSetupEncryptionToast();
|
hideSetupEncryptionToast();
|
||||||
|
|
|
@ -133,8 +133,8 @@ export default class IdentityAuthClient {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!this.tempClient &&
|
!this.tempClient &&
|
||||||
!doesAccountDataHaveIdentityServer() &&
|
!doesAccountDataHaveIdentityServer(this.matrixClient) &&
|
||||||
!(await doesIdentityServerHaveTerms(identityServerUrl))
|
!(await doesIdentityServerHaveTerms(this.matrixClient, identityServerUrl))
|
||||||
) {
|
) {
|
||||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||||
title: _t("Identity server has no terms of service"),
|
title: _t("Identity server has no terms of service"),
|
||||||
|
@ -158,7 +158,7 @@ export default class IdentityAuthClient {
|
||||||
});
|
});
|
||||||
const [confirmed] = await finished;
|
const [confirmed] = await finished;
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
setToDefaultIdentityServer();
|
setToDefaultIdentityServer(this.matrixClient);
|
||||||
} else {
|
} else {
|
||||||
throw new AbortedIdentityActionError("User aborted identity server action without terms");
|
throw new AbortedIdentityActionError("User aborted identity server action without terms");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1209,7 +1209,7 @@ export default class LegacyCallHandler extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await WidgetUtils.addJitsiWidget(roomId, type, "Jitsi", false);
|
await WidgetUtils.addJitsiWidget(client, roomId, type, "Jitsi", false);
|
||||||
logger.log("Jitsi widget added");
|
logger.log("Jitsi widget added");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof MatrixError && e.errcode === "M_FORBIDDEN") {
|
if (e instanceof MatrixError && e.errcode === "M_FORBIDDEN") {
|
||||||
|
|
|
@ -636,7 +636,7 @@ async function doSetLoggedIn(credentials: IMatrixClientCreds, clearStorageEnable
|
||||||
}
|
}
|
||||||
|
|
||||||
dis.fire(Action.OnLoggedIn);
|
dis.fire(Action.OnLoggedIn);
|
||||||
await startMatrixClient(/*startSyncing=*/ !softLogout);
|
await startMatrixClient(client, /*startSyncing=*/ !softLogout);
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
@ -780,10 +780,11 @@ export function isLoggingOut(): boolean {
|
||||||
/**
|
/**
|
||||||
* Starts the matrix client and all other react-sdk services that
|
* Starts the matrix client and all other react-sdk services that
|
||||||
* listen for events while a session is logged in.
|
* listen for events while a session is logged in.
|
||||||
|
* @param client the matrix client to start
|
||||||
* @param {boolean} startSyncing True (default) to actually start
|
* @param {boolean} startSyncing True (default) to actually start
|
||||||
* syncing the client.
|
* syncing the client.
|
||||||
*/
|
*/
|
||||||
async function startMatrixClient(startSyncing = true): Promise<void> {
|
async function startMatrixClient(client: MatrixClient, startSyncing = true): Promise<void> {
|
||||||
logger.log(`Lifecycle: Starting MatrixClient`);
|
logger.log(`Lifecycle: Starting MatrixClient`);
|
||||||
|
|
||||||
// dispatch this before starting the matrix client: it's used
|
// dispatch this before starting the matrix client: it's used
|
||||||
|
@ -796,10 +797,10 @@ async function startMatrixClient(startSyncing = true): Promise<void> {
|
||||||
SdkContextClass.instance.typingStore.reset();
|
SdkContextClass.instance.typingStore.reset();
|
||||||
ToastStore.sharedInstance().reset();
|
ToastStore.sharedInstance().reset();
|
||||||
|
|
||||||
DialogOpener.instance.prepare();
|
DialogOpener.instance.prepare(client);
|
||||||
Notifier.start();
|
Notifier.start();
|
||||||
UserActivity.sharedInstance().start();
|
UserActivity.sharedInstance().start();
|
||||||
DMRoomMap.makeShared().start();
|
DMRoomMap.makeShared(client).start();
|
||||||
IntegrationManagers.sharedInstance().startWatching();
|
IntegrationManagers.sharedInstance().startWatching();
|
||||||
ActiveWidgetStore.instance.start();
|
ActiveWidgetStore.instance.start();
|
||||||
LegacyCallHandler.instance.start();
|
LegacyCallHandler.instance.start();
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { User } from "matrix-js-sdk/src/models/user";
|
import { User } from "matrix-js-sdk/src/models/user";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||||
import MultiInviter, { CompletionStates } from "./utils/MultiInviter";
|
import MultiInviter, { CompletionStates } from "./utils/MultiInviter";
|
||||||
|
@ -49,12 +50,13 @@ export interface IInviteResult {
|
||||||
* @returns {Promise} Promise
|
* @returns {Promise} Promise
|
||||||
*/
|
*/
|
||||||
export function inviteMultipleToRoom(
|
export function inviteMultipleToRoom(
|
||||||
|
client: MatrixClient,
|
||||||
roomId: string,
|
roomId: string,
|
||||||
addresses: string[],
|
addresses: string[],
|
||||||
sendSharedHistoryKeys = false,
|
sendSharedHistoryKeys = false,
|
||||||
progressCallback?: () => void,
|
progressCallback?: () => void,
|
||||||
): Promise<IInviteResult> {
|
): Promise<IInviteResult> {
|
||||||
const inviter = new MultiInviter(roomId, progressCallback);
|
const inviter = new MultiInviter(client, roomId, progressCallback);
|
||||||
return inviter
|
return inviter
|
||||||
.invite(addresses, undefined, sendSharedHistoryKeys)
|
.invite(addresses, undefined, sendSharedHistoryKeys)
|
||||||
.then((states) => Promise.resolve({ states, inviter }));
|
.then((states) => Promise.resolve({ states, inviter }));
|
||||||
|
@ -105,12 +107,13 @@ export function isValid3pidInvite(event: MatrixEvent): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inviteUsersToRoom(
|
export function inviteUsersToRoom(
|
||||||
|
client: MatrixClient,
|
||||||
roomId: string,
|
roomId: string,
|
||||||
userIds: string[],
|
userIds: string[],
|
||||||
sendSharedHistoryKeys = false,
|
sendSharedHistoryKeys = false,
|
||||||
progressCallback?: () => void,
|
progressCallback?: () => void,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return inviteMultipleToRoom(roomId, userIds, sendSharedHistoryKeys, progressCallback)
|
return inviteMultipleToRoom(client, roomId, userIds, sendSharedHistoryKeys, progressCallback)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
const room = MatrixClientPeg.get().getRoom(roomId)!;
|
const room = MatrixClientPeg.get().getRoom(roomId)!;
|
||||||
showAnyInviteErrors(result.states, room, result.inviter);
|
showAnyInviteErrors(result.states, room, result.inviter);
|
||||||
|
|
|
@ -411,6 +411,7 @@ function kickUser(event: MessageEvent<any>, roomId: string, userId: string): voi
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWidget(event: MessageEvent<any>, roomId: string | null): void {
|
function setWidget(event: MessageEvent<any>, roomId: string | null): void {
|
||||||
|
const client = MatrixClientPeg.get();
|
||||||
const widgetId = event.data.widget_id;
|
const widgetId = event.data.widget_id;
|
||||||
let widgetType = event.data.type;
|
let widgetType = event.data.type;
|
||||||
const widgetUrl = event.data.url;
|
const widgetUrl = event.data.url;
|
||||||
|
@ -458,7 +459,7 @@ function setWidget(event: MessageEvent<any>, roomId: string | null): void {
|
||||||
widgetType = WidgetType.fromString(widgetType);
|
widgetType = WidgetType.fromString(widgetType);
|
||||||
|
|
||||||
if (userWidget) {
|
if (userWidget) {
|
||||||
WidgetUtils.setUserWidget(widgetId, widgetType, widgetUrl, widgetName, widgetData)
|
WidgetUtils.setUserWidget(client, widgetId, widgetType, widgetUrl, widgetName, widgetData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
sendResponse(event, {
|
sendResponse(event, {
|
||||||
success: true,
|
success: true,
|
||||||
|
@ -476,6 +477,7 @@ function setWidget(event: MessageEvent<any>, roomId: string | null): void {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WidgetUtils.setRoomWidget(
|
WidgetUtils.setRoomWidget(
|
||||||
|
client,
|
||||||
roomId,
|
roomId,
|
||||||
widgetId,
|
widgetId,
|
||||||
widgetType,
|
widgetType,
|
||||||
|
@ -516,7 +518,7 @@ function getWidgets(event: MessageEvent<any>, roomId: string | null): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add user widgets (not linked to a specific room)
|
// Add user widgets (not linked to a specific room)
|
||||||
const userWidgets = WidgetUtils.getUserWidgetsArray();
|
const userWidgets = WidgetUtils.getUserWidgetsArray(client);
|
||||||
widgetStateEvents = widgetStateEvents.concat(userWidgets);
|
widgetStateEvents = widgetStateEvents.concat(userWidgets);
|
||||||
|
|
||||||
sendResponse(event, widgetStateEvents);
|
sendResponse(event, widgetStateEvents);
|
||||||
|
|
|
@ -344,7 +344,7 @@ export async function accessSecretStorage(func = async (): Promise<void> => {},
|
||||||
onBeforeClose: async (reason): Promise<boolean> => {
|
onBeforeClose: async (reason): Promise<boolean> => {
|
||||||
// If Secure Backup is required, you cannot leave the modal.
|
// If Secure Backup is required, you cannot leave the modal.
|
||||||
if (reason === "backgroundClick") {
|
if (reason === "backgroundClick") {
|
||||||
return !isSecureBackupRequired();
|
return !isSecureBackupRequired(cli);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
|
@ -576,7 +576,7 @@ export const Commands = [
|
||||||
|
|
||||||
prom = finished.then(([useDefault]) => {
|
prom = finished.then(([useDefault]) => {
|
||||||
if (useDefault) {
|
if (useDefault) {
|
||||||
setToDefaultIdentityServer();
|
setToDefaultIdentityServer(MatrixClientPeg.get());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new UserFriendlyError(
|
throw new UserFriendlyError(
|
||||||
|
@ -589,7 +589,7 @@ export const Commands = [
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const inviter = new MultiInviter(roomId);
|
const inviter = new MultiInviter(MatrixClientPeg.get(), roomId);
|
||||||
return success(
|
return success(
|
||||||
prom
|
prom
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -765,7 +765,7 @@ export const Commands = [
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!targetRoomId) targetRoomId = roomId;
|
if (!targetRoomId) targetRoomId = roomId;
|
||||||
return success(leaveRoomBehaviour(targetRoomId));
|
return success(leaveRoomBehaviour(cli, targetRoomId));
|
||||||
},
|
},
|
||||||
category: CommandCategories.actions,
|
category: CommandCategories.actions,
|
||||||
renderingTypes: [TimelineRenderingType.Room],
|
renderingTypes: [TimelineRenderingType.Room],
|
||||||
|
@ -1018,7 +1018,7 @@ export const Commands = [
|
||||||
if (!widgetUrl.startsWith("https://") && !widgetUrl.startsWith("http://")) {
|
if (!widgetUrl.startsWith("https://") && !widgetUrl.startsWith("http://")) {
|
||||||
return reject(new UserFriendlyError("Please supply a https:// or http:// widget URL"));
|
return reject(new UserFriendlyError("Please supply a https:// or http:// widget URL"));
|
||||||
}
|
}
|
||||||
if (WidgetUtils.canUserModifyWidgets(roomId)) {
|
if (WidgetUtils.canUserModifyWidgets(MatrixClientPeg.get(), roomId)) {
|
||||||
const userId = MatrixClientPeg.get().getUserId();
|
const userId = MatrixClientPeg.get().getUserId();
|
||||||
const nowMs = new Date().getTime();
|
const nowMs = new Date().getTime();
|
||||||
const widgetId = encodeURIComponent(`${roomId}_${userId}_${nowMs}`);
|
const widgetId = encodeURIComponent(`${roomId}_${userId}_${nowMs}`);
|
||||||
|
@ -1036,7 +1036,9 @@ export const Commands = [
|
||||||
widgetUrl = WidgetUtils.getLocalJitsiWrapperUrl();
|
widgetUrl = WidgetUtils.getLocalJitsiWrapperUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
return success(WidgetUtils.setRoomWidget(roomId, widgetId, type, widgetUrl, name, data));
|
return success(
|
||||||
|
WidgetUtils.setRoomWidget(MatrixClientPeg.get(), roomId, widgetId, type, widgetUrl, name, data),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return reject(new UserFriendlyError("You cannot modify widgets in this room."));
|
return reject(new UserFriendlyError("You cannot modify widgets in this room."));
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,8 +110,10 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
|
||||||
public constructor(props: IProps) {
|
public constructor(props: IProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
let passPhraseKeySelected;
|
const cli = MatrixClientPeg.get();
|
||||||
const setupMethods = getSecureBackupSetupMethods();
|
|
||||||
|
let passPhraseKeySelected: SecureBackupSetupMethod;
|
||||||
|
const setupMethods = getSecureBackupSetupMethods(cli);
|
||||||
if (setupMethods.includes(SecureBackupSetupMethod.Key)) {
|
if (setupMethods.includes(SecureBackupSetupMethod.Key)) {
|
||||||
passPhraseKeySelected = SecureBackupSetupMethod.Key;
|
passPhraseKeySelected = SecureBackupSetupMethod.Key;
|
||||||
} else {
|
} else {
|
||||||
|
@ -143,13 +145,13 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
|
||||||
// does the server offer a UI auth flow with just m.login.password
|
// does the server offer a UI auth flow with just m.login.password
|
||||||
// for /keys/device_signing/upload?
|
// for /keys/device_signing/upload?
|
||||||
accountPasswordCorrect: null,
|
accountPasswordCorrect: null,
|
||||||
canSkip: !isSecureBackupRequired(),
|
canSkip: !isSecureBackupRequired(cli),
|
||||||
canUploadKeysWithPasswordOnly,
|
canUploadKeysWithPasswordOnly,
|
||||||
passPhraseKeySelected,
|
passPhraseKeySelected,
|
||||||
accountPassword,
|
accountPassword,
|
||||||
};
|
};
|
||||||
|
|
||||||
MatrixClientPeg.get().on(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatusChange);
|
cli.on(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatusChange);
|
||||||
|
|
||||||
this.getInitialPhase();
|
this.getInitialPhase();
|
||||||
}
|
}
|
||||||
|
@ -542,7 +544,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent<IProp
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderPhaseChooseKeyPassphrase(): JSX.Element {
|
private renderPhaseChooseKeyPassphrase(): JSX.Element {
|
||||||
const setupMethods = getSecureBackupSetupMethods();
|
const setupMethods = getSecureBackupSetupMethods(MatrixClientPeg.get());
|
||||||
const optionKey = setupMethods.includes(SecureBackupSetupMethod.Key) ? this.renderOptionKey() : null;
|
const optionKey = setupMethods.includes(SecureBackupSetupMethod.Key) ? this.renderOptionKey() : null;
|
||||||
const optionPassphrase = setupMethods.includes(SecureBackupSetupMethod.Passphrase)
|
const optionPassphrase = setupMethods.includes(SecureBackupSetupMethod.Passphrase)
|
||||||
? this.renderOptionPassphrase()
|
? this.renderOptionPassphrase()
|
||||||
|
|
|
@ -57,7 +57,7 @@ function matcherObject(
|
||||||
export default class RoomProvider extends AutocompleteProvider {
|
export default class RoomProvider extends AutocompleteProvider {
|
||||||
protected matcher: QueryMatcher<ReturnType<typeof matcherObject>>;
|
protected matcher: QueryMatcher<ReturnType<typeof matcherObject>>;
|
||||||
|
|
||||||
public constructor(room: Room, renderingType?: TimelineRenderingType) {
|
public constructor(private readonly room: Room, renderingType?: TimelineRenderingType) {
|
||||||
super({ commandRegex: ROOM_REGEX, renderingType });
|
super({ commandRegex: ROOM_REGEX, renderingType });
|
||||||
this.matcher = new QueryMatcher<ReturnType<typeof matcherObject>>([], {
|
this.matcher = new QueryMatcher<ReturnType<typeof matcherObject>>([], {
|
||||||
keys: ["displayedAlias", "matchName"],
|
keys: ["displayedAlias", "matchName"],
|
||||||
|
@ -119,7 +119,7 @@ export default class RoomProvider extends AutocompleteProvider {
|
||||||
completionId: room.room.roomId,
|
completionId: room.room.roomId,
|
||||||
type: "room",
|
type: "room",
|
||||||
suffix: " ",
|
suffix: " ",
|
||||||
href: makeRoomPermalink(room.displayedAlias),
|
href: makeRoomPermalink(this.room.client, room.displayedAlias),
|
||||||
component: (
|
component: (
|
||||||
<PillCompletion title={room.room.name} description={room.displayedAlias}>
|
<PillCompletion title={room.room.name} description={room.displayedAlias}>
|
||||||
<RoomAvatar width={24} height={24} room={room.room} />
|
<RoomAvatar width={24} height={24} room={room.room} />
|
||||||
|
|
|
@ -28,7 +28,7 @@ import { OwnProfileStore } from "../../stores/OwnProfileStore";
|
||||||
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
|
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
|
||||||
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||||
import { useEventEmitter } from "../../hooks/useEventEmitter";
|
import { useEventEmitter } from "../../hooks/useEventEmitter";
|
||||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
import MatrixClientContext, { useMatrixClientContext } from "../../contexts/MatrixClientContext";
|
||||||
import MiniAvatarUploader, { AVATAR_SIZE } from "../views/elements/MiniAvatarUploader";
|
import MiniAvatarUploader, { AVATAR_SIZE } from "../views/elements/MiniAvatarUploader";
|
||||||
import PosthogTrackers from "../../PosthogTrackers";
|
import PosthogTrackers from "../../PosthogTrackers";
|
||||||
import EmbeddedPage from "./EmbeddedPage";
|
import EmbeddedPage from "./EmbeddedPage";
|
||||||
|
@ -97,8 +97,9 @@ const UserWelcomeTop: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
|
const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
|
||||||
|
const cli = useMatrixClientContext();
|
||||||
const config = SdkConfig.get();
|
const config = SdkConfig.get();
|
||||||
const pageUrl = getHomePageUrl(config);
|
const pageUrl = getHomePageUrl(config, cli);
|
||||||
|
|
||||||
if (pageUrl) {
|
if (pageUrl) {
|
||||||
return <EmbeddedPage className="mx_HomePage" url={pageUrl} scrollbar={true} />;
|
return <EmbeddedPage className="mx_HomePage" url={pageUrl} scrollbar={true} />;
|
||||||
|
|
|
@ -1154,7 +1154,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private leaveRoom(roomId: string): void {
|
private leaveRoom(roomId: string): void {
|
||||||
const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
|
const cli = MatrixClientPeg.get();
|
||||||
|
const roomToLeave = cli.getRoom(roomId);
|
||||||
const warnings = this.leaveRoomWarnings(roomId);
|
const warnings = this.leaveRoomWarnings(roomId);
|
||||||
|
|
||||||
const isSpace = roomToLeave?.isSpaceRoom();
|
const isSpace = roomToLeave?.isSpaceRoom();
|
||||||
|
@ -1173,9 +1174,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
button: _t("Leave"),
|
button: _t("Leave"),
|
||||||
onFinished: (shouldLeave) => {
|
onFinished: async (shouldLeave) => {
|
||||||
if (shouldLeave) {
|
if (shouldLeave) {
|
||||||
leaveRoomBehaviour(roomId);
|
await leaveRoomBehaviour(cli, roomId);
|
||||||
|
|
||||||
dis.dispatch<AfterLeaveRoomPayload>({
|
dis.dispatch<AfterLeaveRoomPayload>({
|
||||||
action: Action.AfterLeaveRoom,
|
action: Action.AfterLeaveRoom,
|
||||||
|
@ -1211,7 +1212,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async copyRoom(roomId: string): Promise<void> {
|
private async copyRoom(roomId: string): Promise<void> {
|
||||||
const roomLink = makeRoomPermalink(roomId);
|
const roomLink = makeRoomPermalink(MatrixClientPeg.get(), roomId);
|
||||||
const success = await copyPlaintext(roomLink);
|
const success = await copyPlaintext(roomLink);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
|
|
@ -743,7 +743,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
||||||
lastInSection =
|
lastInSection =
|
||||||
willWantDateSeparator ||
|
willWantDateSeparator ||
|
||||||
mxEv.getSender() !== nextEv.getSender() ||
|
mxEv.getSender() !== nextEv.getSender() ||
|
||||||
getEventDisplayInfo(nextEv, this.showHiddenEvents).isInfoMessage ||
|
getEventDisplayInfo(MatrixClientPeg.get(), nextEv, this.showHiddenEvents).isInfoMessage ||
|
||||||
!shouldFormContinuation(mxEv, nextEv, this.showHiddenEvents, this.context.timelineRenderingType);
|
!shouldFormContinuation(mxEv, nextEv, this.showHiddenEvents, this.context.timelineRenderingType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -561,7 +561,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
createdByCurrentUserTs - lastCreatedByOtherTs < PREVENT_MULTIPLE_JITSI_WITHIN
|
createdByCurrentUserTs - lastCreatedByOtherTs < PREVENT_MULTIPLE_JITSI_WITHIN
|
||||||
) {
|
) {
|
||||||
// more than one Jitsi widget with the last one from the current user → remove it
|
// more than one Jitsi widget with the last one from the current user → remove it
|
||||||
WidgetUtils.setRoomWidget(this.state.roomId, createdByCurrentUser.id);
|
WidgetUtils.setRoomWidget(this.context.client, this.state.roomId, createdByCurrentUser.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -549,7 +549,7 @@ const SpaceSetupPrivateInvite: React.FC<{
|
||||||
setBusy(true);
|
setBusy(true);
|
||||||
const targetIds = emailAddresses.map((name) => name.trim()).filter(Boolean);
|
const targetIds = emailAddresses.map((name) => name.trim()).filter(Boolean);
|
||||||
try {
|
try {
|
||||||
const result = await inviteMultipleToRoom(space.roomId, targetIds);
|
const result = await inviteMultipleToRoom(space.client, space.roomId, targetIds);
|
||||||
|
|
||||||
const failedUsers = Object.keys(result.states).filter((a) => result.states[a] === "error");
|
const failedUsers = Object.keys(result.states).filter((a) => result.states[a] === "error");
|
||||||
if (failedUsers.length > 0) {
|
if (failedUsers.length > 0) {
|
||||||
|
|
|
@ -110,7 +110,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private get hasHomePage(): boolean {
|
private get hasHomePage(): boolean {
|
||||||
return !!getHomePageUrl(SdkConfig.get());
|
return !!getHomePageUrl(SdkConfig.get(), this.context.client!);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onCurrentVoiceBroadcastRecordingChanged = (recording: VoiceBroadcastRecording | null): void => {
|
private onCurrentVoiceBroadcastRecordingChanged = (recording: VoiceBroadcastRecording | null): void => {
|
||||||
|
|
|
@ -153,7 +153,9 @@ export default class ViewSource extends React.Component<IProps, IState> {
|
||||||
const isEditing = this.state.isEditing;
|
const isEditing = this.state.isEditing;
|
||||||
const roomId = mxEvent.getRoomId()!;
|
const roomId = mxEvent.getRoomId()!;
|
||||||
const eventId = mxEvent.getId()!;
|
const eventId = mxEvent.getId()!;
|
||||||
const canEdit = mxEvent.isState() ? this.canSendStateEvent(mxEvent) : canEditContent(this.props.mxEvent);
|
const canEdit = mxEvent.isState()
|
||||||
|
? this.canSendStateEvent(mxEvent)
|
||||||
|
: canEditContent(MatrixClientPeg.get(), this.props.mxEvent);
|
||||||
return (
|
return (
|
||||||
<BaseDialog className="mx_ViewSource" onFinished={this.props.onFinished} title={_t("View Source")}>
|
<BaseDialog className="mx_ViewSource" onFinished={this.props.onFinished} title={_t("View Source")}>
|
||||||
<div className="mx_ViewSource_header">
|
<div className="mx_ViewSource_header">
|
||||||
|
|
|
@ -22,6 +22,7 @@ import SdkConfig from "../../../SdkConfig";
|
||||||
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
|
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
|
||||||
import { _t, _td } from "../../../languageHandler";
|
import { _t, _td } from "../../../languageHandler";
|
||||||
import Field, { IInputProps } from "../elements/Field";
|
import Field, { IInputProps } from "../elements/Field";
|
||||||
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
|
||||||
interface IProps extends Omit<IInputProps, "onValidate" | "element"> {
|
interface IProps extends Omit<IInputProps, "onValidate" | "element"> {
|
||||||
autoFocus?: boolean;
|
autoFocus?: boolean;
|
||||||
|
@ -56,7 +57,7 @@ class PassphraseField extends PureComponent<IProps> {
|
||||||
deriveData: async ({ value }): Promise<zxcvbn.ZXCVBNResult | null> => {
|
deriveData: async ({ value }): Promise<zxcvbn.ZXCVBNResult | null> => {
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
const { scorePassword } = await import("../../../utils/PasswordScorer");
|
const { scorePassword } = await import("../../../utils/PasswordScorer");
|
||||||
return scorePassword(value);
|
return scorePassword(MatrixClientPeg.get(), value);
|
||||||
},
|
},
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -165,7 +165,7 @@ export default class DecoratedRoomAvatar extends React.PureComponent<IProps, ISt
|
||||||
const otherUserId = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId);
|
const otherUserId = DMRoomMap.shared().getUserIdForRoomId(this.props.room.roomId);
|
||||||
if (otherUserId && this.props.room.getJoinedMemberCount() === 2) {
|
if (otherUserId && this.props.room.getJoinedMemberCount() === 2) {
|
||||||
// Track presence, if available
|
// Track presence, if available
|
||||||
if (isPresenceEnabled()) {
|
if (isPresenceEnabled(this.props.room.client)) {
|
||||||
this.dmUser = MatrixClientPeg.get().getUser(otherUserId);
|
this.dmUser = MatrixClientPeg.get().getUser(otherUserId);
|
||||||
icon = this.getPresenceIcon();
|
icon = this.getPresenceIcon();
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,7 +317,12 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||||
};
|
};
|
||||||
|
|
||||||
private onEditClick = (): void => {
|
private onEditClick = (): void => {
|
||||||
editEvent(this.props.mxEvent, this.context.timelineRenderingType, this.props.getRelationsForEvent);
|
editEvent(
|
||||||
|
MatrixClientPeg.get(),
|
||||||
|
this.props.mxEvent,
|
||||||
|
this.context.timelineRenderingType,
|
||||||
|
this.props.getRelationsForEvent,
|
||||||
|
);
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -617,7 +622,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
|
||||||
}
|
}
|
||||||
|
|
||||||
let editButton: JSX.Element | undefined;
|
let editButton: JSX.Element | undefined;
|
||||||
if (rightClick && canEditContent(mxEvent)) {
|
if (rightClick && canEditContent(cli, mxEvent)) {
|
||||||
editButton = (
|
editButton = (
|
||||||
<IconizedContextMenuOption
|
<IconizedContextMenuOption
|
||||||
iconClassName="mx_MessageContextMenu_iconEdit"
|
iconClassName="mx_MessageContextMenu_iconEdit"
|
||||||
|
|
|
@ -61,7 +61,7 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
||||||
const { room, roomId } = useContext(RoomContext);
|
const { room, roomId } = useContext(RoomContext);
|
||||||
|
|
||||||
const widgetMessaging = WidgetMessagingStore.instance.getMessagingForUid(WidgetUtils.getWidgetUid(app));
|
const widgetMessaging = WidgetMessagingStore.instance.getMessagingForUid(WidgetUtils.getWidgetUid(app));
|
||||||
const canModify = userWidget || WidgetUtils.canUserModifyWidgets(roomId);
|
const canModify = userWidget || WidgetUtils.canUserModifyWidgets(cli, roomId);
|
||||||
|
|
||||||
let streamAudioStreamButton: JSX.Element | undefined;
|
let streamAudioStreamButton: JSX.Element | undefined;
|
||||||
if (roomId && getConfigLivestreamUrl() && WidgetType.JITSI.matches(app.type)) {
|
if (roomId && getConfigLivestreamUrl() && WidgetType.JITSI.matches(app.type)) {
|
||||||
|
@ -138,7 +138,7 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
||||||
button: _t("Delete widget"),
|
button: _t("Delete widget"),
|
||||||
onFinished: (confirmed) => {
|
onFinished: (confirmed) => {
|
||||||
if (!confirmed) return;
|
if (!confirmed) return;
|
||||||
WidgetUtils.setRoomWidget(roomId, app.id);
|
WidgetUtils.setRoomWidget(cli, roomId, app.id);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,9 +75,10 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
joinRule = JoinRule.Restricted;
|
joinRule = JoinRule.Restricted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cli = MatrixClientPeg.get();
|
||||||
this.state = {
|
this.state = {
|
||||||
isPublic: this.props.defaultPublic || false,
|
isPublic: this.props.defaultPublic || false,
|
||||||
isEncrypted: this.props.defaultEncrypted ?? privateShouldBeEncrypted(),
|
isEncrypted: this.props.defaultEncrypted ?? privateShouldBeEncrypted(cli),
|
||||||
joinRule,
|
joinRule,
|
||||||
name: this.props.defaultName || "",
|
name: this.props.defaultName || "",
|
||||||
topic: "",
|
topic: "",
|
||||||
|
@ -88,9 +89,9 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
canChangeEncryption: true,
|
canChangeEncryption: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
MatrixClientPeg.get()
|
cli.doesServerForceEncryptionForPreset(Preset.PrivateChat).then((isForced) =>
|
||||||
.doesServerForceEncryptionForPreset(Preset.PrivateChat)
|
this.setState({ canChangeEncryption: !isForced }),
|
||||||
.then((isForced) => this.setState({ canChangeEncryption: !isForced }));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private roomCreateOptions(): IOpts {
|
private roomCreateOptions(): IOpts {
|
||||||
|
@ -284,7 +285,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
|
||||||
let e2eeSection: JSX.Element | undefined;
|
let e2eeSection: JSX.Element | undefined;
|
||||||
if (this.state.joinRule !== JoinRule.Public) {
|
if (this.state.joinRule !== JoinRule.Public) {
|
||||||
let microcopy: string;
|
let microcopy: string;
|
||||||
if (privateShouldBeEncrypted()) {
|
if (privateShouldBeEncrypted(MatrixClientPeg.get())) {
|
||||||
if (this.state.canChangeEncryption) {
|
if (this.state.canChangeEncryption) {
|
||||||
microcopy = isVideoRoom
|
microcopy = isVideoRoom
|
||||||
? _t("You can't disable this later. The room will be encrypted but the embedded call will not.")
|
? _t("You can't disable this later. The room will be encrypted but the embedded call will not.")
|
||||||
|
|
|
@ -407,7 +407,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidMount(): void {
|
public componentDidMount(): void {
|
||||||
this.encryptionByDefault = privateShouldBeEncrypted();
|
this.encryptionByDefault = privateShouldBeEncrypted(MatrixClientPeg.get());
|
||||||
|
|
||||||
if (this.props.initialText) {
|
if (this.props.initialText) {
|
||||||
this.updateSuggestions(this.props.initialText);
|
this.updateSuggestions(this.props.initialText);
|
||||||
|
@ -613,7 +613,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await inviteMultipleToRoom(this.props.roomId, targetIds, true);
|
const result = await inviteMultipleToRoom(cli, this.props.roomId, targetIds, true);
|
||||||
if (!this.shouldAbortAfterInviteError(result, room)) {
|
if (!this.shouldAbortAfterInviteError(result, room)) {
|
||||||
// handles setting error message too
|
// handles setting error message too
|
||||||
this.props.onFinished(true);
|
this.props.onFinished(true);
|
||||||
|
@ -986,7 +986,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
|
||||||
|
|
||||||
// Update the IS in account data. Actually using it may trigger terms.
|
// Update the IS in account data. Actually using it may trigger terms.
|
||||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||||
setToDefaultIdentityServer();
|
setToDefaultIdentityServer(MatrixClientPeg.get());
|
||||||
this.setState({ canUseIdentityServer: true, tryingIdentityServer: false });
|
this.setState({ canUseIdentityServer: true, tryingIdentityServer: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1395,7 +1395,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
|
||||||
</a>
|
</a>
|
||||||
),
|
),
|
||||||
a: (sub) => (
|
a: (sub) => (
|
||||||
<a href={makeRoomPermalink(roomId)} rel="noreferrer noopener" target="_blank">
|
<a href={makeRoomPermalink(cli, roomId)} rel="noreferrer noopener" target="_blank">
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</a>
|
||||||
),
|
),
|
||||||
|
|
|
@ -76,7 +76,7 @@ class LocationPicker extends React.Component<ILocationPickerProps, IState> {
|
||||||
try {
|
try {
|
||||||
this.map = new maplibregl.Map({
|
this.map = new maplibregl.Map({
|
||||||
container: "mx_LocationPicker_map",
|
container: "mx_LocationPicker_map",
|
||||||
style: findMapStyleUrl(),
|
style: findMapStyleUrl(this.context),
|
||||||
center: [0, 0],
|
center: [0, 0],
|
||||||
zoom: 1,
|
zoom: 1,
|
||||||
});
|
});
|
||||||
|
|
|
@ -101,7 +101,7 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
|
||||||
private pillifyLinks(): void {
|
private pillifyLinks(): void {
|
||||||
// not present for redacted events
|
// not present for redacted events
|
||||||
if (this.content.current) {
|
if (this.content.current) {
|
||||||
pillifyLinks(this.content.current.children, this.props.mxEvent, this.pills);
|
pillifyLinks(MatrixClientPeg.get(), this.content.current.children, this.props.mxEvent, this.pills);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,16 +114,18 @@ export default class MKeyVerificationConclusion extends React.Component<IProps>
|
||||||
|
|
||||||
if (request.done) {
|
if (request.done) {
|
||||||
title = _t("You verified %(name)s", {
|
title = _t("You verified %(name)s", {
|
||||||
name: getNameForEventRoom(request.otherUserId, mxEvent.getRoomId()!),
|
name: getNameForEventRoom(client, request.otherUserId, mxEvent.getRoomId()!),
|
||||||
});
|
});
|
||||||
} else if (request.cancelled) {
|
} else if (request.cancelled) {
|
||||||
const userId = request.cancellingUserId;
|
const userId = request.cancellingUserId;
|
||||||
if (userId === myUserId) {
|
if (userId === myUserId) {
|
||||||
title = _t("You cancelled verifying %(name)s", {
|
title = _t("You cancelled verifying %(name)s", {
|
||||||
name: getNameForEventRoom(request.otherUserId, mxEvent.getRoomId()!),
|
name: getNameForEventRoom(client, request.otherUserId, mxEvent.getRoomId()!),
|
||||||
});
|
});
|
||||||
} else if (userId) {
|
} else if (userId) {
|
||||||
title = _t("%(name)s cancelled verifying", { name: getNameForEventRoom(userId, mxEvent.getRoomId()!) });
|
title = _t("%(name)s cancelled verifying", {
|
||||||
|
name: getNameForEventRoom(client, userId, mxEvent.getRoomId()!),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +137,7 @@ export default class MKeyVerificationConclusion extends React.Component<IProps>
|
||||||
<EventTileBubble
|
<EventTileBubble
|
||||||
className={classes}
|
className={classes}
|
||||||
title={title}
|
title={title}
|
||||||
subtitle={userLabelForEventRoom(request.otherUserId, mxEvent.getRoomId()!)}
|
subtitle={userLabelForEventRoom(client, request.otherUserId, mxEvent.getRoomId()!)}
|
||||||
timestamp={this.props.timestamp}
|
timestamp={this.props.timestamp}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -93,7 +93,9 @@ export default class MKeyVerificationRequest extends React.Component<IProps> {
|
||||||
if (userId === myUserId) {
|
if (userId === myUserId) {
|
||||||
return _t("You accepted");
|
return _t("You accepted");
|
||||||
} else {
|
} else {
|
||||||
return _t("%(name)s accepted", { name: getNameForEventRoom(userId, this.props.mxEvent.getRoomId()!) });
|
return _t("%(name)s accepted", {
|
||||||
|
name: getNameForEventRoom(client, userId, this.props.mxEvent.getRoomId()!),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,14 +112,19 @@ export default class MKeyVerificationRequest extends React.Component<IProps> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (declined) {
|
if (declined) {
|
||||||
return _t("%(name)s declined", { name: getNameForEventRoom(userId, this.props.mxEvent.getRoomId()!) });
|
return _t("%(name)s declined", {
|
||||||
|
name: getNameForEventRoom(client, userId, this.props.mxEvent.getRoomId()!),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
return _t("%(name)s cancelled", { name: getNameForEventRoom(userId, this.props.mxEvent.getRoomId()!) });
|
return _t("%(name)s cancelled", {
|
||||||
|
name: getNameForEventRoom(client, userId, this.props.mxEvent.getRoomId()!),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
|
const client = MatrixClientPeg.get();
|
||||||
const { mxEvent } = this.props;
|
const { mxEvent } = this.props;
|
||||||
const request = mxEvent.verificationRequest;
|
const request = mxEvent.verificationRequest;
|
||||||
|
|
||||||
|
@ -149,9 +156,9 @@ export default class MKeyVerificationRequest extends React.Component<IProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!request.initiatedByMe) {
|
if (!request.initiatedByMe) {
|
||||||
const name = getNameForEventRoom(request.requestingUserId, mxEvent.getRoomId()!);
|
const name = getNameForEventRoom(client, request.requestingUserId, mxEvent.getRoomId()!);
|
||||||
title = _t("%(name)s wants to verify", { name });
|
title = _t("%(name)s wants to verify", { name });
|
||||||
subtitle = userLabelForEventRoom(request.requestingUserId, mxEvent.getRoomId()!);
|
subtitle = userLabelForEventRoom(client, request.requestingUserId, mxEvent.getRoomId()!);
|
||||||
if (request.canAccept) {
|
if (request.canAccept) {
|
||||||
stateNode = (
|
stateNode = (
|
||||||
<div className="mx_cryptoEvent_buttons">
|
<div className="mx_cryptoEvent_buttons">
|
||||||
|
@ -167,7 +174,7 @@ export default class MKeyVerificationRequest extends React.Component<IProps> {
|
||||||
} else {
|
} else {
|
||||||
// request sent by us
|
// request sent by us
|
||||||
title = _t("You sent a verification request");
|
title = _t("You sent a verification request");
|
||||||
subtitle = userLabelForEventRoom(request.receivingUserId, mxEvent.getRoomId()!);
|
subtitle = userLabelForEventRoom(client, request.receivingUserId, mxEvent.getRoomId()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title) {
|
if (title) {
|
||||||
|
|
|
@ -363,7 +363,12 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
editEvent(this.props.mxEvent, this.context.timelineRenderingType, this.props.getRelationsForEvent);
|
editEvent(
|
||||||
|
MatrixClientPeg.get(),
|
||||||
|
this.props.mxEvent,
|
||||||
|
this.context.timelineRenderingType,
|
||||||
|
this.props.getRelationsForEvent,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly forbiddenThreadHeadMsgType = [MsgType.KeyVerificationRequest];
|
private readonly forbiddenThreadHeadMsgType = [MsgType.KeyVerificationRequest];
|
||||||
|
@ -424,7 +429,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const toolbarOpts: JSX.Element[] = [];
|
const toolbarOpts: JSX.Element[] = [];
|
||||||
if (canEditContent(this.props.mxEvent)) {
|
if (canEditContent(MatrixClientPeg.get(), this.props.mxEvent)) {
|
||||||
toolbarOpts.push(
|
toolbarOpts.push(
|
||||||
<RovingAccessibleTooltipButton
|
<RovingAccessibleTooltipButton
|
||||||
className="mx_MessageActionBar_iconButton"
|
className="mx_MessageActionBar_iconButton"
|
||||||
|
|
|
@ -48,6 +48,7 @@ import { options as linkifyOpts } from "../../../linkify-matrix";
|
||||||
import { getParentEventId } from "../../../utils/Reply";
|
import { getParentEventId } from "../../../utils/Reply";
|
||||||
import { EditWysiwygComposer } from "../rooms/wysiwyg_composer";
|
import { EditWysiwygComposer } from "../rooms/wysiwyg_composer";
|
||||||
import { IEventTileOps } from "../rooms/EventTile";
|
import { IEventTileOps } from "../rooms/EventTile";
|
||||||
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
|
||||||
const MAX_HIGHLIGHT_LENGTH = 4096;
|
const MAX_HIGHLIGHT_LENGTH = 4096;
|
||||||
|
|
||||||
|
@ -92,7 +93,7 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
|
||||||
this.activateSpoilers([content]);
|
this.activateSpoilers([content]);
|
||||||
|
|
||||||
HtmlUtils.linkifyElement(content);
|
HtmlUtils.linkifyElement(content);
|
||||||
pillifyLinks([content], this.props.mxEvent, this.pills);
|
pillifyLinks(MatrixClientPeg.get(), [content], this.props.mxEvent, this.pills);
|
||||||
|
|
||||||
this.calculateUrlPreview();
|
this.calculateUrlPreview();
|
||||||
|
|
||||||
|
|
|
@ -108,8 +108,8 @@ const AppRow: React.FC<IAppRowProps> = ({ app, room }) => {
|
||||||
const [canModifyWidget, setCanModifyWidget] = useState<boolean>();
|
const [canModifyWidget, setCanModifyWidget] = useState<boolean>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCanModifyWidget(WidgetUtils.canUserModifyWidgets(room.roomId));
|
setCanModifyWidget(WidgetUtils.canUserModifyWidgets(room.client, room.roomId));
|
||||||
}, [room.roomId]);
|
}, [room.client, room.roomId]);
|
||||||
|
|
||||||
const onOpenWidgetClick = (): void => {
|
const onOpenWidgetClick = (): void => {
|
||||||
RightPanelStore.instance.pushCard({
|
RightPanelStore.instance.pushCard({
|
||||||
|
|
|
@ -456,7 +456,7 @@ export const UserOptionsSection: React.FC<{
|
||||||
const onInviteUserButton = async (ev: ButtonEvent): Promise<void> => {
|
const onInviteUserButton = async (ev: ButtonEvent): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
// We use a MultiInviter to re-use the invite logic, even though we're only inviting one user.
|
// We use a MultiInviter to re-use the invite logic, even though we're only inviting one user.
|
||||||
const inviter = new MultiInviter(roomId || "");
|
const inviter = new MultiInviter(cli, roomId || "");
|
||||||
await inviter.invite([member.userId]).then(() => {
|
await inviter.invite([member.userId]).then(() => {
|
||||||
if (inviter.getCompletionState(member.userId) !== "invited") {
|
if (inviter.getCompletionState(member.userId) !== "invited") {
|
||||||
const errorStringFromInviterUtility = inviter.getErrorText(member.userId);
|
const errorStringFromInviterUtility = inviter.getErrorText(member.userId);
|
||||||
|
|
|
@ -50,6 +50,7 @@ import { editorRoomKey, editorStateKey } from "../../../Editing";
|
||||||
import DocumentOffset from "../../../editor/offset";
|
import DocumentOffset from "../../../editor/offset";
|
||||||
import { attachMentions, attachRelation } from "./SendMessageComposer";
|
import { attachMentions, attachRelation } from "./SendMessageComposer";
|
||||||
import { filterBoolean } from "../../../utils/arrays";
|
import { filterBoolean } from "../../../utils/arrays";
|
||||||
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
|
||||||
function getHtmlReplyFallback(mxEvent: MatrixEvent): string {
|
function getHtmlReplyFallback(mxEvent: MatrixEvent): string {
|
||||||
const html = mxEvent.getContent().formatted_body;
|
const html = mxEvent.getContent().formatted_body;
|
||||||
|
@ -184,6 +185,7 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
|
||||||
events: this.events,
|
events: this.events,
|
||||||
isForward: false,
|
isForward: false,
|
||||||
fromEventId: this.props.editState.getEvent().getId(),
|
fromEventId: this.props.editState.getEvent().getId(),
|
||||||
|
matrixClient: MatrixClientPeg.get(),
|
||||||
});
|
});
|
||||||
if (previousEvent) {
|
if (previousEvent) {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
|
@ -203,6 +205,7 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
|
||||||
events: this.events,
|
events: this.events,
|
||||||
isForward: true,
|
isForward: true,
|
||||||
fromEventId: this.props.editState.getEvent().getId(),
|
fromEventId: this.props.editState.getEvent().getId(),
|
||||||
|
matrixClient: MatrixClientPeg.get(),
|
||||||
});
|
});
|
||||||
if (nextEvent) {
|
if (nextEvent) {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
|
|
|
@ -34,7 +34,6 @@ import dis from "../../../dispatcher/dispatcher";
|
||||||
import { Layout } from "../../../settings/enums/Layout";
|
import { Layout } from "../../../settings/enums/Layout";
|
||||||
import { formatTime } from "../../../DateUtils";
|
import { formatTime } from "../../../DateUtils";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
|
||||||
import { DecryptionFailureBody } from "../messages/DecryptionFailureBody";
|
import { DecryptionFailureBody } from "../messages/DecryptionFailureBody";
|
||||||
import { E2EState } from "./E2EIcon";
|
import { E2EState } from "./E2EIcon";
|
||||||
import RoomAvatar from "../avatars/RoomAvatar";
|
import RoomAvatar from "../avatars/RoomAvatar";
|
||||||
|
@ -267,7 +266,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
||||||
|
|
||||||
private unmounted = false;
|
private unmounted = false;
|
||||||
|
|
||||||
public constructor(props: EventTileProps, context: React.ContextType<typeof MatrixClientContext>) {
|
public constructor(props: EventTileProps, context: React.ContextType<typeof RoomContext>) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
const thread = this.thread;
|
const thread = this.thread;
|
||||||
|
@ -904,7 +903,12 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
||||||
isLeftAlignedBubbleMessage,
|
isLeftAlignedBubbleMessage,
|
||||||
noBubbleEvent,
|
noBubbleEvent,
|
||||||
isSeeingThroughMessageHiddenForModeration,
|
isSeeingThroughMessageHiddenForModeration,
|
||||||
} = getEventDisplayInfo(this.props.mxEvent, this.context.showHiddenEvents, this.shouldHideEvent());
|
} = getEventDisplayInfo(
|
||||||
|
MatrixClientPeg.get(),
|
||||||
|
this.props.mxEvent,
|
||||||
|
this.context.showHiddenEvents,
|
||||||
|
this.shouldHideEvent(),
|
||||||
|
);
|
||||||
const { isQuoteExpanded } = this.state;
|
const { isQuoteExpanded } = this.state;
|
||||||
// This shouldn't happen: the caller should check we support this type
|
// This shouldn't happen: the caller should check we support this type
|
||||||
// before trying to instantiate us
|
// before trying to instantiate us
|
||||||
|
|
|
@ -527,7 +527,7 @@ export class MessageComposer extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
const continuesLink = replacementRoomId ? (
|
const continuesLink = replacementRoomId ? (
|
||||||
<a
|
<a
|
||||||
href={makeRoomPermalink(replacementRoomId)}
|
href={makeRoomPermalink(MatrixClientPeg.get(), replacementRoomId)}
|
||||||
className="mx_MessageComposer_roomReplaced_link"
|
className="mx_MessageComposer_roomReplaced_link"
|
||||||
onClick={this.onTombstoneClick}
|
onClick={this.onTombstoneClick}
|
||||||
>
|
>
|
||||||
|
|
|
@ -44,7 +44,7 @@ import { shouldEncryptRoomWithSingle3rdPartyInvite } from "../../../utils/room/s
|
||||||
function hasExpectedEncryptionSettings(matrixClient: MatrixClient, room: Room): boolean {
|
function hasExpectedEncryptionSettings(matrixClient: MatrixClient, room: Room): boolean {
|
||||||
const isEncrypted: boolean = matrixClient.isRoomEncrypted(room.roomId);
|
const isEncrypted: boolean = matrixClient.isRoomEncrypted(room.roomId);
|
||||||
const isPublic: boolean = room.getJoinRule() === "public";
|
const isPublic: boolean = room.getJoinRule() === "public";
|
||||||
return isPublic || !privateShouldBeEncrypted() || isEncrypted;
|
return isPublic || !privateShouldBeEncrypted(matrixClient) || isEncrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
const determineIntroMessage = (room: Room, encryptedSingle3rdPartyInvite: boolean): string => {
|
const determineIntroMessage = (room: Room, encryptedSingle3rdPartyInvite: boolean): string => {
|
||||||
|
|
|
@ -34,6 +34,7 @@ import MVoiceMessageBody from "../messages/MVoiceMessageBody";
|
||||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||||
import { renderReplyTile } from "../../../events/EventTileFactory";
|
import { renderReplyTile } from "../../../events/EventTileFactory";
|
||||||
import { GetRelationsForEvent } from "../rooms/EventTile";
|
import { GetRelationsForEvent } from "../rooms/EventTile";
|
||||||
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
mxEvent: MatrixEvent;
|
mxEvent: MatrixEvent;
|
||||||
|
@ -110,6 +111,7 @@ export default class ReplyTile extends React.PureComponent<IProps> {
|
||||||
const evType = mxEvent.getType();
|
const evType = mxEvent.getType();
|
||||||
|
|
||||||
const { hasRenderer, isInfoMessage, isSeeingThroughMessageHiddenForModeration } = getEventDisplayInfo(
|
const { hasRenderer, isInfoMessage, isSeeingThroughMessageHiddenForModeration } = getEventDisplayInfo(
|
||||||
|
MatrixClientPeg.get(),
|
||||||
mxEvent,
|
mxEvent,
|
||||||
false /* Replies are never hidden, so this should be fine */,
|
false /* Replies are never hidden, so this should be fine */,
|
||||||
);
|
);
|
||||||
|
|
|
@ -335,6 +335,7 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
|
||||||
? findEditableEvent({
|
? findEditableEvent({
|
||||||
events,
|
events,
|
||||||
isForward: false,
|
isForward: false,
|
||||||
|
matrixClient: MatrixClientPeg.get(),
|
||||||
})
|
})
|
||||||
: undefined;
|
: undefined;
|
||||||
if (editEvent) {
|
if (editEvent) {
|
||||||
|
|
|
@ -123,7 +123,7 @@ export default class Stickerpicker extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.setStickerPickerOpen(false);
|
this.props.setStickerPickerOpen(false);
|
||||||
WidgetUtils.removeStickerpickerWidgets()
|
WidgetUtils.removeStickerpickerWidgets(this.props.room.client)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
})
|
})
|
||||||
|
@ -169,7 +169,7 @@ export default class Stickerpicker extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateWidget = (): void => {
|
private updateWidget = (): void => {
|
||||||
const stickerpickerWidget = WidgetUtils.getStickerpickerWidgets()[0];
|
const stickerpickerWidget = WidgetUtils.getStickerpickerWidgets(this.props.room.client)[0];
|
||||||
if (!stickerpickerWidget) {
|
if (!stickerpickerWidget) {
|
||||||
Stickerpicker.currentWidget = undefined;
|
Stickerpicker.currentWidget = undefined;
|
||||||
this.setState({ stickerpickerWidget: null, widgetId: null });
|
this.setState({ stickerpickerWidget: null, widgetId: null });
|
||||||
|
|
|
@ -146,8 +146,10 @@ export default class VoiceRecordComposerTile extends React.PureComponent<IProps,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
doMaybeLocalRoomAction(this.props.room.roomId, (actualRoomId: string) =>
|
doMaybeLocalRoomAction(
|
||||||
MatrixClientPeg.get().sendMessage(actualRoomId, content),
|
this.props.room.roomId,
|
||||||
|
(actualRoomId: string) => MatrixClientPeg.get().sendMessage(actualRoomId, content),
|
||||||
|
this.props.room.client,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("Error sending voice message:", e);
|
logger.error("Error sending voice message:", e);
|
||||||
|
|
|
@ -185,6 +185,7 @@ function dispatchEditEvent(
|
||||||
events: foundEvents,
|
events: foundEvents,
|
||||||
isForward,
|
isForward,
|
||||||
fromEventId: editorStateTransfer?.getEvent().getId(),
|
fromEventId: editorStateTransfer?.getEvent().getId(),
|
||||||
|
matrixClient: mxClient,
|
||||||
});
|
});
|
||||||
if (newEvent) {
|
if (newEvent) {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
|
|
|
@ -419,7 +419,7 @@ export default class SecureBackupPanel extends React.PureComponent<{}, IState> {
|
||||||
</AccessibleButton>,
|
</AccessibleButton>,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isSecureBackupRequired()) {
|
if (!isSecureBackupRequired(MatrixClientPeg.get())) {
|
||||||
actions.push(
|
actions.push(
|
||||||
<AccessibleButton key="delete" kind="danger" onClick={this.deleteBackup}>
|
<AccessibleButton key="delete" kind="danger" onClick={this.deleteBackup}>
|
||||||
{_t("Delete Backup")}
|
{_t("Delete Backup")}
|
||||||
|
|
|
@ -179,7 +179,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
|
||||||
let save = true;
|
let save = true;
|
||||||
|
|
||||||
// Double check that the identity server even has terms of service.
|
// Double check that the identity server even has terms of service.
|
||||||
const hasTerms = await doesIdentityServerHaveTerms(fullUrl);
|
const hasTerms = await doesIdentityServerHaveTerms(MatrixClientPeg.get(), fullUrl);
|
||||||
if (!hasTerms) {
|
if (!hasTerms) {
|
||||||
const [confirmed] = await this.showNoTermsWarning(fullUrl);
|
const [confirmed] = await this.showNoTermsWarning(fullUrl);
|
||||||
save = !!confirmed;
|
save = !!confirmed;
|
||||||
|
|
|
@ -316,7 +316,7 @@ export default class SecurityUserSettingsTab extends React.Component<IProps, ISt
|
||||||
);
|
);
|
||||||
|
|
||||||
let warning;
|
let warning;
|
||||||
if (!privateShouldBeEncrypted()) {
|
if (!privateShouldBeEncrypted(MatrixClientPeg.get())) {
|
||||||
warning = (
|
warning = (
|
||||||
<div className="mx_SecurityUserSettingsTab_warning">
|
<div className="mx_SecurityUserSettingsTab_warning">
|
||||||
{_t(
|
{_t(
|
||||||
|
|
|
@ -165,7 +165,7 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
|
||||||
} else {
|
} else {
|
||||||
const userId = request.otherUserId;
|
const userId = request.otherUserId;
|
||||||
const roomId = request.channel.roomId;
|
const roomId = request.channel.roomId;
|
||||||
description = roomId ? userLabelForEventRoom(userId, roomId) : userId;
|
description = roomId ? userLabelForEventRoom(MatrixClientPeg.get(), userId, roomId) : userId;
|
||||||
// for legacy to_device verification requests
|
// for legacy to_device verification requests
|
||||||
if (description === userId) {
|
if (description === userId) {
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
|
|
|
@ -30,6 +30,7 @@ import EmbeddedPage from "../../structures/EmbeddedPage";
|
||||||
import HomePage from "../../structures/HomePage";
|
import HomePage from "../../structures/HomePage";
|
||||||
import { UserOnboardingHeader } from "./UserOnboardingHeader";
|
import { UserOnboardingHeader } from "./UserOnboardingHeader";
|
||||||
import { UserOnboardingList } from "./UserOnboardingList";
|
import { UserOnboardingList } from "./UserOnboardingList";
|
||||||
|
import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
justRegistered?: boolean;
|
justRegistered?: boolean;
|
||||||
|
@ -44,8 +45,9 @@ export function showUserOnboardingPage(useCase: UseCase | null): boolean {
|
||||||
|
|
||||||
const ANIMATION_DURATION = 2800;
|
const ANIMATION_DURATION = 2800;
|
||||||
export function UserOnboardingPage({ justRegistered = false }: Props): JSX.Element {
|
export function UserOnboardingPage({ justRegistered = false }: Props): JSX.Element {
|
||||||
|
const cli = useMatrixClientContext();
|
||||||
const config = SdkConfig.get();
|
const config = SdkConfig.get();
|
||||||
const pageUrl = getHomePageUrl(config);
|
const pageUrl = getHomePageUrl(config, cli);
|
||||||
|
|
||||||
const useCase = useSettingValue<UseCase | null>("FTUE.useCaseSelection");
|
const useCase = useSettingValue<UseCase | null>("FTUE.useCaseSelection");
|
||||||
const context = useUserOnboardingContext();
|
const context = useUserOnboardingContext();
|
||||||
|
|
|
@ -36,7 +36,7 @@ export interface MatrixClientProps {
|
||||||
mxClient: MatrixClient;
|
mxClient: MatrixClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useMatrixClientContext(): MatrixClient | undefined {
|
export function useMatrixClientContext(): MatrixClient {
|
||||||
return useContext(MatrixClientContext);
|
return useContext(MatrixClientContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -462,7 +462,7 @@ export async function ensureDMExists(client: MatrixClient, userId: string): Prom
|
||||||
roomId = existingDMRoom.roomId;
|
roomId = existingDMRoom.roomId;
|
||||||
} else {
|
} else {
|
||||||
let encryption: boolean | undefined;
|
let encryption: boolean | undefined;
|
||||||
if (privateShouldBeEncrypted()) {
|
if (privateShouldBeEncrypted(client)) {
|
||||||
encryption = await canEncryptToAllUsers(client, [userId]);
|
encryption = await canEncryptToAllUsers(client, [userId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ export class IntegrationManagers {
|
||||||
|
|
||||||
private setupAccountManagers(): void {
|
private setupAccountManagers(): void {
|
||||||
if (!this.client || !this.client.getUserId()) return; // not logged in
|
if (!this.client || !this.client.getUserId()) return; // not logged in
|
||||||
const widgets = WidgetUtils.getIntegrationManagerWidgets();
|
const widgets = WidgetUtils.getIntegrationManagerWidgets(this.client);
|
||||||
widgets.forEach((w) => {
|
widgets.forEach((w) => {
|
||||||
const data = w.content["data"];
|
const data = w.content["data"];
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
@ -180,14 +180,6 @@ export class IntegrationManagers {
|
||||||
Modal.createDialog(IntegrationsDisabledDialog);
|
Modal.createDialog(IntegrationsDisabledDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async overwriteManagerOnAccount(manager: IntegrationManagerInstance): Promise<void> {
|
|
||||||
// TODO: TravisR - We should be logging out of scalar clients.
|
|
||||||
await WidgetUtils.removeIntegrationManagerWidgets();
|
|
||||||
|
|
||||||
// TODO: TravisR - We should actually be carrying over the discovery response verbatim.
|
|
||||||
await WidgetUtils.addIntegrationManagerWidget(manager.name, manager.uiUrl, manager.apiUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to discover an integration manager using only its name. This will not validate that
|
* Attempts to discover an integration manager using only its name. This will not validate that
|
||||||
* the integration manager is functional - that is the caller's responsibility.
|
* the integration manager is functional - that is the caller's responsibility.
|
||||||
|
|
|
@ -30,6 +30,7 @@ import dis from "./dispatcher/dispatcher";
|
||||||
import { Action } from "./dispatcher/actions";
|
import { Action } from "./dispatcher/actions";
|
||||||
import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload";
|
import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload";
|
||||||
import { ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload";
|
import { ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload";
|
||||||
|
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||||
|
|
||||||
export enum Type {
|
export enum Type {
|
||||||
URL = "url",
|
URL = "url",
|
||||||
|
@ -196,7 +197,7 @@ export const options: Opts = {
|
||||||
case Type.RoomAlias:
|
case Type.RoomAlias:
|
||||||
case Type.UserId:
|
case Type.UserId:
|
||||||
default: {
|
default: {
|
||||||
return tryTransformEntityToPermalink(href) ?? "";
|
return tryTransformEntityToPermalink(MatrixClientPeg.get(), href) ?? "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -342,7 +342,7 @@ export class JitsiCall extends Call {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async create(room: Room): Promise<void> {
|
public static async create(room: Room): Promise<void> {
|
||||||
await WidgetUtils.addJitsiWidget(room.roomId, CallType.Video, "Group call", true, room.name);
|
await WidgetUtils.addJitsiWidget(room.client, room.roomId, CallType.Video, "Group call", true, room.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateParticipants(): void {
|
private updateParticipants(): void {
|
||||||
|
|
|
@ -22,7 +22,6 @@ import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { Optional } from "matrix-events-sdk";
|
import { Optional } from "matrix-events-sdk";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import { filterValidMDirect } from "./dm/filterValidMDirect";
|
import { filterValidMDirect } from "./dm/filterValidMDirect";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,8 +52,8 @@ export default class DMRoomMap {
|
||||||
* Makes and returns a new shared instance that can then be accessed
|
* Makes and returns a new shared instance that can then be accessed
|
||||||
* with shared(). This returned instance is not automatically started.
|
* with shared(). This returned instance is not automatically started.
|
||||||
*/
|
*/
|
||||||
public static makeShared(): DMRoomMap {
|
public static makeShared(matrixClient: MatrixClient): DMRoomMap {
|
||||||
DMRoomMap.sharedInstance = new DMRoomMap(MatrixClientPeg.get());
|
DMRoomMap.sharedInstance = new DMRoomMap(matrixClient);
|
||||||
return DMRoomMap.sharedInstance;
|
return DMRoomMap.sharedInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +174,7 @@ export default class DMRoomMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
const joinedRooms = commonRooms
|
const joinedRooms = commonRooms
|
||||||
.map((r) => MatrixClientPeg.get().getRoom(r))
|
.map((r) => this.matrixClient.getRoom(r))
|
||||||
.filter((r) => r && r.getMyMembership() === "join");
|
.filter((r) => r && r.getMyMembership() === "join");
|
||||||
|
|
||||||
return joinedRooms[0];
|
return joinedRooms[0];
|
||||||
|
|
|
@ -16,13 +16,13 @@ limitations under the License.
|
||||||
|
|
||||||
import classnames from "classnames";
|
import classnames from "classnames";
|
||||||
import { ComponentProps } from "react";
|
import { ComponentProps } from "react";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import defaultDispatcher from "../dispatcher/dispatcher";
|
import defaultDispatcher from "../dispatcher/dispatcher";
|
||||||
import { ActionPayload } from "../dispatcher/payloads";
|
import { ActionPayload } from "../dispatcher/payloads";
|
||||||
import Modal from "../Modal";
|
import Modal from "../Modal";
|
||||||
import RoomSettingsDialog from "../components/views/dialogs/RoomSettingsDialog";
|
import RoomSettingsDialog from "../components/views/dialogs/RoomSettingsDialog";
|
||||||
import ForwardDialog from "../components/views/dialogs/ForwardDialog";
|
import ForwardDialog from "../components/views/dialogs/ForwardDialog";
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import { Action } from "../dispatcher/actions";
|
import { Action } from "../dispatcher/actions";
|
||||||
import ReportEventDialog from "../components/views/dialogs/ReportEventDialog";
|
import ReportEventDialog from "../components/views/dialogs/ReportEventDialog";
|
||||||
import SpacePreferencesDialog from "../components/views/dialogs/SpacePreferencesDialog";
|
import SpacePreferencesDialog from "../components/views/dialogs/SpacePreferencesDialog";
|
||||||
|
@ -43,18 +43,21 @@ export class DialogOpener {
|
||||||
public static readonly instance = new DialogOpener();
|
public static readonly instance = new DialogOpener();
|
||||||
|
|
||||||
private isRegistered = false;
|
private isRegistered = false;
|
||||||
|
private matrixClient?: MatrixClient;
|
||||||
|
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
// We could do this in the constructor, but then we wouldn't have
|
// We could do this in the constructor, but then we wouldn't have
|
||||||
// a function to call from Lifecycle to capture the class.
|
// a function to call from Lifecycle to capture the class.
|
||||||
public prepare(): void {
|
public prepare(matrixClient: MatrixClient): void {
|
||||||
|
this.matrixClient = matrixClient;
|
||||||
if (this.isRegistered) return;
|
if (this.isRegistered) return;
|
||||||
defaultDispatcher.register(this.onDispatch);
|
defaultDispatcher.register(this.onDispatch);
|
||||||
this.isRegistered = true;
|
this.isRegistered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDispatch = (payload: ActionPayload): void => {
|
private onDispatch = (payload: ActionPayload): void => {
|
||||||
|
if (!this.matrixClient) return;
|
||||||
switch (payload.action) {
|
switch (payload.action) {
|
||||||
case "open_room_settings":
|
case "open_room_settings":
|
||||||
Modal.createDialog(
|
Modal.createDialog(
|
||||||
|
@ -70,7 +73,7 @@ export class DialogOpener {
|
||||||
break;
|
break;
|
||||||
case Action.OpenForwardDialog:
|
case Action.OpenForwardDialog:
|
||||||
Modal.createDialog(ForwardDialog, {
|
Modal.createDialog(ForwardDialog, {
|
||||||
matrixClient: MatrixClientPeg.get(),
|
matrixClient: this.matrixClient,
|
||||||
event: payload.event,
|
event: payload.event,
|
||||||
permalinkCreator: payload.permalinkCreator,
|
permalinkCreator: payload.permalinkCreator,
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,11 +18,10 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { EventType, MsgType } from "matrix-js-sdk/src/@types/event";
|
import { EventType, MsgType } from "matrix-js-sdk/src/@types/event";
|
||||||
import { M_POLL_END, M_POLL_START } from "matrix-js-sdk/src/@types/polls";
|
import { M_POLL_END, M_POLL_START } from "matrix-js-sdk/src/@types/polls";
|
||||||
import { M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon";
|
import { M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon";
|
||||||
import { IContent } from "matrix-js-sdk/src/matrix";
|
import { IContent, MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import { haveRendererForEvent, JitsiEventFactory, JSONEventFactory, pickFactory } from "../events/EventTileFactory";
|
import { haveRendererForEvent, JitsiEventFactory, JSONEventFactory, pickFactory } from "../events/EventTileFactory";
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import { getMessageModerationState, isLocationEvent, MessageModerationState } from "./EventUtils";
|
import { getMessageModerationState, isLocationEvent, MessageModerationState } from "./EventUtils";
|
||||||
import { ElementCall } from "../models/Call";
|
import { ElementCall } from "../models/Call";
|
||||||
import { VoiceBroadcastInfoEventType, VoiceBroadcastInfoState } from "../voice-broadcast";
|
import { VoiceBroadcastInfoEventType, VoiceBroadcastInfoState } from "../voice-broadcast";
|
||||||
|
@ -48,6 +47,7 @@ const calcIsInfoMessage = (
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getEventDisplayInfo(
|
export function getEventDisplayInfo(
|
||||||
|
matrixClient: MatrixClient,
|
||||||
mxEvent: MatrixEvent,
|
mxEvent: MatrixEvent,
|
||||||
showHiddenEvents: boolean,
|
showHiddenEvents: boolean,
|
||||||
hideEvent?: boolean,
|
hideEvent?: boolean,
|
||||||
|
@ -65,7 +65,7 @@ export function getEventDisplayInfo(
|
||||||
|
|
||||||
let isSeeingThroughMessageHiddenForModeration = false;
|
let isSeeingThroughMessageHiddenForModeration = false;
|
||||||
if (SettingsStore.getValue("feature_msc3531_hide_messages_pending_moderation")) {
|
if (SettingsStore.getValue("feature_msc3531_hide_messages_pending_moderation")) {
|
||||||
switch (getMessageModerationState(mxEvent)) {
|
switch (getMessageModerationState(mxEvent, matrixClient)) {
|
||||||
case MessageModerationState.VISIBLE_FOR_ALL:
|
case MessageModerationState.VISIBLE_FOR_ALL:
|
||||||
case MessageModerationState.HIDDEN_TO_CURRENT_USER:
|
case MessageModerationState.HIDDEN_TO_CURRENT_USER:
|
||||||
// Nothing specific to do here
|
// Nothing specific to do here
|
||||||
|
@ -77,8 +77,7 @@ export function getEventDisplayInfo(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Thread a MatrixClient through to here
|
let factory = pickFactory(mxEvent, matrixClient, showHiddenEvents);
|
||||||
let factory = pickFactory(mxEvent, MatrixClientPeg.get(), showHiddenEvents);
|
|
||||||
|
|
||||||
// Info messages are basically information about commands processed on a room
|
// Info messages are basically information about commands processed on a room
|
||||||
let isBubbleMessage =
|
let isBubbleMessage =
|
||||||
|
@ -103,10 +102,8 @@ export function getEventDisplayInfo(
|
||||||
// replace relations (which otherwise would display as a confusing
|
// replace relations (which otherwise would display as a confusing
|
||||||
// duplicate of the thing they are replacing).
|
// duplicate of the thing they are replacing).
|
||||||
if (hideEvent || !haveRendererForEvent(mxEvent, showHiddenEvents)) {
|
if (hideEvent || !haveRendererForEvent(mxEvent, showHiddenEvents)) {
|
||||||
// forcefully ask for a factory for a hidden event (hidden event
|
// forcefully ask for a factory for a hidden event (hidden event setting is checked internally)
|
||||||
// setting is checked internally)
|
factory = pickFactory(mxEvent, matrixClient, showHiddenEvents, true);
|
||||||
// TODO: Thread a MatrixClient through to here
|
|
||||||
factory = pickFactory(mxEvent, MatrixClientPeg.get(), showHiddenEvents, true);
|
|
||||||
if (factory === JSONEventFactory) {
|
if (factory === JSONEventFactory) {
|
||||||
isBubbleMessage = false;
|
isBubbleMessage = false;
|
||||||
// Reuse info message avatar and sender profile styling
|
// Reuse info message avatar and sender profile styling
|
||||||
|
|
|
@ -23,7 +23,6 @@ import { M_LOCATION } from "matrix-js-sdk/src/@types/location";
|
||||||
import { M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon";
|
import { M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon";
|
||||||
import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread";
|
import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import shouldHideEvent from "../shouldHideEvent";
|
import shouldHideEvent from "../shouldHideEvent";
|
||||||
import { GetRelationsForEvent } from "../components/views/rooms/EventTile";
|
import { GetRelationsForEvent } from "../components/views/rooms/EventTile";
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
|
@ -69,7 +68,7 @@ export function isContentActionable(mxEvent: MatrixEvent): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canEditContent(mxEvent: MatrixEvent): boolean {
|
export function canEditContent(matrixClient: MatrixClient, mxEvent: MatrixEvent): boolean {
|
||||||
const isCancellable = mxEvent.getType() === EventType.RoomMessage || M_POLL_START.matches(mxEvent.getType());
|
const isCancellable = mxEvent.getType() === EventType.RoomMessage || M_POLL_START.matches(mxEvent.getType());
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -77,7 +76,7 @@ export function canEditContent(mxEvent: MatrixEvent): boolean {
|
||||||
mxEvent.status === EventStatus.CANCELLED ||
|
mxEvent.status === EventStatus.CANCELLED ||
|
||||||
mxEvent.isRedacted() ||
|
mxEvent.isRedacted() ||
|
||||||
mxEvent.isRelation(RelationType.Replace) ||
|
mxEvent.isRelation(RelationType.Replace) ||
|
||||||
mxEvent.getSender() !== MatrixClientPeg.get().getUserId()
|
mxEvent.getSender() !== matrixClient.getUserId()
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -89,22 +88,24 @@ export function canEditContent(mxEvent: MatrixEvent): boolean {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function canEditOwnEvent(mxEvent: MatrixEvent): boolean {
|
export function canEditOwnEvent(matrixClient: MatrixClient, mxEvent: MatrixEvent): boolean {
|
||||||
// for now we only allow editing
|
// for now we only allow editing
|
||||||
// your own events. So this just call through
|
// your own events. So this just call through
|
||||||
// In the future though, moderators will be able to
|
// In the future though, moderators will be able to
|
||||||
// edit other people's messages as well but we don't
|
// edit other people's messages as well but we don't
|
||||||
// want findEditableEvent to return other people's events
|
// want findEditableEvent to return other people's events
|
||||||
// hence this method.
|
// hence this method.
|
||||||
return canEditContent(mxEvent);
|
return canEditContent(matrixClient, mxEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_JUMP_DISTANCE = 100;
|
const MAX_JUMP_DISTANCE = 100;
|
||||||
export function findEditableEvent({
|
export function findEditableEvent({
|
||||||
|
matrixClient,
|
||||||
events,
|
events,
|
||||||
isForward,
|
isForward,
|
||||||
fromEventId,
|
fromEventId,
|
||||||
}: {
|
}: {
|
||||||
|
matrixClient: MatrixClient;
|
||||||
events: MatrixEvent[];
|
events: MatrixEvent[];
|
||||||
isForward: boolean;
|
isForward: boolean;
|
||||||
fromEventId?: string;
|
fromEventId?: string;
|
||||||
|
@ -126,7 +127,7 @@ export function findEditableEvent({
|
||||||
// don't look further than MAX_JUMP_DISTANCE events from `fromEventId`
|
// don't look further than MAX_JUMP_DISTANCE events from `fromEventId`
|
||||||
// to not iterate potentially 1000nds of events on key up/down
|
// to not iterate potentially 1000nds of events on key up/down
|
||||||
endIdx = Math.min(Math.max(0, i + inc * MAX_JUMP_DISTANCE), maxIdx);
|
endIdx = Math.min(Math.max(0, i + inc * MAX_JUMP_DISTANCE), maxIdx);
|
||||||
} else if (foundFromEventId && !shouldHideEvent(e) && canEditOwnEvent(e)) {
|
} else if (foundFromEventId && !shouldHideEvent(e) && canEditOwnEvent(matrixClient, e)) {
|
||||||
// otherwise look for editable event
|
// otherwise look for editable event
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -170,9 +171,7 @@ const getMsc3531Enabled = (): boolean => {
|
||||||
* If MSC3531 is deactivated in settings, all messages are considered visible
|
* If MSC3531 is deactivated in settings, all messages are considered visible
|
||||||
* to all.
|
* to all.
|
||||||
*/
|
*/
|
||||||
export function getMessageModerationState(mxEvent: MatrixEvent, client?: MatrixClient): MessageModerationState {
|
export function getMessageModerationState(mxEvent: MatrixEvent, client: MatrixClient): MessageModerationState {
|
||||||
client = client ?? MatrixClientPeg.get(); // because param defaults don't do the correct thing
|
|
||||||
|
|
||||||
if (!getMsc3531Enabled()) {
|
if (!getMsc3531Enabled()) {
|
||||||
return MessageModerationState.VISIBLE_FOR_ALL;
|
return MessageModerationState.VISIBLE_FOR_ALL;
|
||||||
}
|
}
|
||||||
|
@ -246,11 +245,12 @@ export async function fetchInitialEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editEvent(
|
export function editEvent(
|
||||||
|
matrixClient: MatrixClient,
|
||||||
mxEvent: MatrixEvent,
|
mxEvent: MatrixEvent,
|
||||||
timelineRenderingType: TimelineRenderingType,
|
timelineRenderingType: TimelineRenderingType,
|
||||||
getRelationsForEvent?: GetRelationsForEvent,
|
getRelationsForEvent?: GetRelationsForEvent,
|
||||||
): void {
|
): void {
|
||||||
if (!canEditContent(mxEvent)) return;
|
if (!canEditContent(matrixClient, mxEvent)) return;
|
||||||
|
|
||||||
if (M_POLL_START.matches(mxEvent.getType())) {
|
if (M_POLL_START.matches(mxEvent.getType())) {
|
||||||
launchPollEditor(mxEvent, getRelationsForEvent);
|
launchPollEditor(mxEvent, getRelationsForEvent);
|
||||||
|
|
|
@ -17,27 +17,27 @@ limitations under the License.
|
||||||
import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
|
import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { HTTPError } from "matrix-js-sdk/src/http-api";
|
import { HTTPError } from "matrix-js-sdk/src/http-api";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import SdkConfig from "../SdkConfig";
|
import SdkConfig from "../SdkConfig";
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import { Policies } from "../Terms";
|
import { Policies } from "../Terms";
|
||||||
|
|
||||||
export function getDefaultIdentityServerUrl(): string | undefined {
|
export function getDefaultIdentityServerUrl(): string | undefined {
|
||||||
return SdkConfig.get("validated_server_config")?.isUrl;
|
return SdkConfig.get("validated_server_config")?.isUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setToDefaultIdentityServer(): void {
|
export function setToDefaultIdentityServer(matrixClient: MatrixClient): void {
|
||||||
const url = getDefaultIdentityServerUrl();
|
const url = getDefaultIdentityServerUrl();
|
||||||
// Account data change will update localstorage, client, etc through dispatcher
|
// Account data change will update localstorage, client, etc through dispatcher
|
||||||
MatrixClientPeg.get().setAccountData("m.identity_server", {
|
matrixClient.setAccountData("m.identity_server", {
|
||||||
base_url: url,
|
base_url: url,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function doesIdentityServerHaveTerms(fullUrl: string): Promise<boolean> {
|
export async function doesIdentityServerHaveTerms(matrixClient: MatrixClient, fullUrl: string): Promise<boolean> {
|
||||||
let terms: { policies?: Policies } | null;
|
let terms: { policies?: Policies } | null;
|
||||||
try {
|
try {
|
||||||
terms = await MatrixClientPeg.get().getTerms(SERVICE_TYPES.IS, fullUrl);
|
terms = await matrixClient.getTerms(SERVICE_TYPES.IS, fullUrl);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
if (e.cors === "rejected" || (e instanceof HTTPError && e.httpStatus === 404)) {
|
if (e.cors === "rejected" || (e instanceof HTTPError && e.httpStatus === 404)) {
|
||||||
|
@ -50,7 +50,7 @@ export async function doesIdentityServerHaveTerms(fullUrl: string): Promise<bool
|
||||||
return !!terms?.["policies"] && Object.keys(terms["policies"]).length > 0;
|
return !!terms?.["policies"] && Object.keys(terms["policies"]).length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doesAccountDataHaveIdentityServer(): boolean {
|
export function doesAccountDataHaveIdentityServer(matrixClient: MatrixClient): boolean {
|
||||||
const event = MatrixClientPeg.get().getAccountData("m.identity_server");
|
const event = matrixClient.getAccountData("m.identity_server");
|
||||||
return event && event.getContent() && event.getContent()["base_url"];
|
return event?.getContent()["base_url"];
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,18 +14,18 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { _t } from "../languageHandler";
|
import { _t } from "../languageHandler";
|
||||||
|
|
||||||
export function getNameForEventRoom(userId: string, roomId: string): string {
|
export function getNameForEventRoom(matrixClient: MatrixClient, userId: string, roomId: string): string {
|
||||||
const client = MatrixClientPeg.get();
|
const room = matrixClient.getRoom(roomId);
|
||||||
const room = client.getRoom(roomId);
|
|
||||||
const member = room && room.getMember(userId);
|
const member = room && room.getMember(userId);
|
||||||
return member ? member.name : userId;
|
return member ? member.name : userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function userLabelForEventRoom(userId: string, roomId: string): string {
|
export function userLabelForEventRoom(matrixClient: MatrixClient, userId: string, roomId: string): string {
|
||||||
const name = getNameForEventRoom(userId, roomId);
|
const name = getNameForEventRoom(matrixClient, userId, roomId);
|
||||||
if (name !== userId) {
|
if (name !== userId) {
|
||||||
return _t("%(name)s (%(userId)s)", { name, userId });
|
return _t("%(name)s (%(userId)s)", { name, userId });
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -21,7 +21,6 @@ import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
import { HistoryVisibility } from "matrix-js-sdk/src/@types/partials";
|
import { HistoryVisibility } from "matrix-js-sdk/src/@types/partials";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import { AddressType, getAddressType } from "../UserAddress";
|
import { AddressType, getAddressType } from "../UserAddress";
|
||||||
import { _t } from "../languageHandler";
|
import { _t } from "../languageHandler";
|
||||||
import Modal from "../Modal";
|
import Modal from "../Modal";
|
||||||
|
@ -54,8 +53,6 @@ const USER_ALREADY_INVITED = "IO.ELEMENT.ALREADY_INVITED";
|
||||||
* Invites multiple addresses to a room, handling rate limiting from the server
|
* Invites multiple addresses to a room, handling rate limiting from the server
|
||||||
*/
|
*/
|
||||||
export default class MultiInviter {
|
export default class MultiInviter {
|
||||||
private readonly matrixClient: MatrixClient;
|
|
||||||
|
|
||||||
private canceled = false;
|
private canceled = false;
|
||||||
private addresses: string[] = [];
|
private addresses: string[] = [];
|
||||||
private busy = false;
|
private busy = false;
|
||||||
|
@ -66,12 +63,15 @@ export default class MultiInviter {
|
||||||
private reason: string | undefined;
|
private reason: string | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param matrixClient the client of the logged in user
|
||||||
* @param {string} roomId The ID of the room to invite to
|
* @param {string} roomId The ID of the room to invite to
|
||||||
* @param {function} progressCallback optional callback, fired after each invite.
|
* @param {function} progressCallback optional callback, fired after each invite.
|
||||||
*/
|
*/
|
||||||
public constructor(private roomId: string, private readonly progressCallback?: () => void) {
|
public constructor(
|
||||||
this.matrixClient = MatrixClientPeg.get();
|
private readonly matrixClient: MatrixClient,
|
||||||
}
|
private roomId: string,
|
||||||
|
private readonly progressCallback?: () => void,
|
||||||
|
) {}
|
||||||
|
|
||||||
public get fatal(): boolean {
|
public get fatal(): boolean {
|
||||||
return this._fatal;
|
return this._fatal;
|
||||||
|
|
|
@ -15,8 +15,8 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import zxcvbn, { ZXCVBNFeedbackWarning } from "zxcvbn";
|
import zxcvbn, { ZXCVBNFeedbackWarning } from "zxcvbn";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import { _t, _td } from "../languageHandler";
|
import { _t, _td } from "../languageHandler";
|
||||||
|
|
||||||
const ZXCVBN_USER_INPUTS = ["riot", "matrix"];
|
const ZXCVBN_USER_INPUTS = ["riot", "matrix"];
|
||||||
|
@ -58,14 +58,15 @@ _td("Short keyboard patterns are easy to guess");
|
||||||
* (obviously) which is large.
|
* (obviously) which is large.
|
||||||
*
|
*
|
||||||
* @param {string} password Password to score
|
* @param {string} password Password to score
|
||||||
|
* @param matrixClient the client of the logged in user, if any
|
||||||
* @returns {object} Score result with `score` and `feedback` properties
|
* @returns {object} Score result with `score` and `feedback` properties
|
||||||
*/
|
*/
|
||||||
export function scorePassword(password: string): zxcvbn.ZXCVBNResult | null {
|
export function scorePassword(matrixClient: MatrixClient | undefined, password: string): zxcvbn.ZXCVBNResult | null {
|
||||||
if (password.length === 0) return null;
|
if (password.length === 0) return null;
|
||||||
|
|
||||||
const userInputs = ZXCVBN_USER_INPUTS.slice();
|
const userInputs = ZXCVBN_USER_INPUTS.slice();
|
||||||
if (MatrixClientPeg.get()) {
|
if (matrixClient) {
|
||||||
userInputs.push(MatrixClientPeg.get().getUserIdLocalpart()!);
|
userInputs.push(matrixClient.getUserIdLocalpart()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
let zxcvbnResult = zxcvbn(password, userInputs);
|
let zxcvbnResult = zxcvbn(password, userInputs);
|
||||||
|
|
|
@ -118,7 +118,7 @@ export async function upgradeRoom(
|
||||||
|
|
||||||
if (toInvite.length > 0) {
|
if (toInvite.length > 0) {
|
||||||
// Errors are handled internally to this function
|
// Errors are handled internally to this function
|
||||||
await inviteUsersToRoom(newRoomId, toInvite, false, () => {
|
await inviteUsersToRoom(cli, newRoomId, toInvite, false, () => {
|
||||||
progress.inviteUsersProgress!++;
|
progress.inviteUsersProgress!++;
|
||||||
progressCallback?.(progress);
|
progressCallback?.(progress);
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,11 +14,9 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { IClientWellKnown } from "matrix-js-sdk/src/client";
|
import { IClientWellKnown, MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
import { UnstableValue } from "matrix-js-sdk/src/NamespacedValue";
|
import { UnstableValue } from "matrix-js-sdk/src/NamespacedValue";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
|
|
||||||
const CALL_BEHAVIOUR_WK_KEY = "io.element.call_behaviour";
|
const CALL_BEHAVIOUR_WK_KEY = "io.element.call_behaviour";
|
||||||
const E2EE_WK_KEY = "io.element.e2ee";
|
const E2EE_WK_KEY = "io.element.e2ee";
|
||||||
const E2EE_WK_KEY_DEPRECATED = "im.vector.riot.e2ee";
|
const E2EE_WK_KEY_DEPRECATED = "im.vector.riot.e2ee";
|
||||||
|
@ -45,13 +43,13 @@ export interface IEmbeddedPagesWellKnown {
|
||||||
}
|
}
|
||||||
/* eslint-enable camelcase */
|
/* eslint-enable camelcase */
|
||||||
|
|
||||||
export function getCallBehaviourWellKnown(): ICallBehaviourWellKnown {
|
export function getCallBehaviourWellKnown(matrixClient: MatrixClient): ICallBehaviourWellKnown {
|
||||||
const clientWellKnown = MatrixClientPeg.get().getClientWellKnown();
|
const clientWellKnown = matrixClient.getClientWellKnown();
|
||||||
return clientWellKnown?.[CALL_BEHAVIOUR_WK_KEY];
|
return clientWellKnown?.[CALL_BEHAVIOUR_WK_KEY];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getE2EEWellKnown(): IE2EEWellKnown | null {
|
export function getE2EEWellKnown(matrixClient: MatrixClient): IE2EEWellKnown | null {
|
||||||
const clientWellKnown = MatrixClientPeg.get().getClientWellKnown();
|
const clientWellKnown = matrixClient.getClientWellKnown();
|
||||||
if (clientWellKnown?.[E2EE_WK_KEY]) {
|
if (clientWellKnown?.[E2EE_WK_KEY]) {
|
||||||
return clientWellKnown[E2EE_WK_KEY];
|
return clientWellKnown[E2EE_WK_KEY];
|
||||||
}
|
}
|
||||||
|
@ -61,24 +59,24 @@ export function getE2EEWellKnown(): IE2EEWellKnown | null {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTileServerWellKnown(): ITileServerWellKnown | undefined {
|
export function getTileServerWellKnown(matrixClient: MatrixClient): ITileServerWellKnown | undefined {
|
||||||
return tileServerFromWellKnown(MatrixClientPeg.get().getClientWellKnown());
|
return tileServerFromWellKnown(matrixClient.getClientWellKnown());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tileServerFromWellKnown(clientWellKnown?: IClientWellKnown | undefined): ITileServerWellKnown {
|
export function tileServerFromWellKnown(clientWellKnown?: IClientWellKnown | undefined): ITileServerWellKnown {
|
||||||
return clientWellKnown?.[TILE_SERVER_WK_KEY.name] ?? clientWellKnown?.[TILE_SERVER_WK_KEY.altName];
|
return clientWellKnown?.[TILE_SERVER_WK_KEY.name] ?? clientWellKnown?.[TILE_SERVER_WK_KEY.altName];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEmbeddedPagesWellKnown(): IEmbeddedPagesWellKnown | undefined {
|
export function getEmbeddedPagesWellKnown(matrixClient: MatrixClient | undefined): IEmbeddedPagesWellKnown | undefined {
|
||||||
return embeddedPagesFromWellKnown(MatrixClientPeg.get()?.getClientWellKnown());
|
return embeddedPagesFromWellKnown(matrixClient?.getClientWellKnown());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function embeddedPagesFromWellKnown(clientWellKnown?: IClientWellKnown): IEmbeddedPagesWellKnown {
|
export function embeddedPagesFromWellKnown(clientWellKnown?: IClientWellKnown): IEmbeddedPagesWellKnown {
|
||||||
return clientWellKnown?.[EMBEDDED_PAGES_WK_PROPERTY];
|
return clientWellKnown?.[EMBEDDED_PAGES_WK_PROPERTY];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isSecureBackupRequired(): boolean {
|
export function isSecureBackupRequired(matrixClient: MatrixClient): boolean {
|
||||||
return getE2EEWellKnown()?.["secure_backup_required"] === true;
|
return getE2EEWellKnown(matrixClient)?.["secure_backup_required"] === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SecureBackupSetupMethod {
|
export enum SecureBackupSetupMethod {
|
||||||
|
@ -86,8 +84,8 @@ export enum SecureBackupSetupMethod {
|
||||||
Passphrase = "passphrase",
|
Passphrase = "passphrase",
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSecureBackupSetupMethods(): SecureBackupSetupMethod[] {
|
export function getSecureBackupSetupMethods(matrixClient: MatrixClient): SecureBackupSetupMethod[] {
|
||||||
const wellKnown = getE2EEWellKnown();
|
const wellKnown = getE2EEWellKnown(matrixClient);
|
||||||
if (
|
if (
|
||||||
!wellKnown ||
|
!wellKnown ||
|
||||||
!wellKnown["secure_backup_setup_methods"] ||
|
!wellKnown["secure_backup_setup_methods"] ||
|
||||||
|
|
|
@ -20,11 +20,10 @@ import { IWidget, IWidgetData } from "matrix-widget-api";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { ClientEvent, RoomStateEvent } from "matrix-js-sdk/src/matrix";
|
import { ClientEvent, MatrixClient, RoomStateEvent } from "matrix-js-sdk/src/matrix";
|
||||||
import { CallType } from "matrix-js-sdk/src/webrtc/call";
|
import { CallType } from "matrix-js-sdk/src/webrtc/call";
|
||||||
import { randomString, randomLowercaseString, randomUppercaseString } from "matrix-js-sdk/src/randomstring";
|
import { randomString, randomLowercaseString, randomUppercaseString } from "matrix-js-sdk/src/randomstring";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import PlatformPeg from "../PlatformPeg";
|
import PlatformPeg from "../PlatformPeg";
|
||||||
import SdkConfig from "../SdkConfig";
|
import SdkConfig from "../SdkConfig";
|
||||||
import dis from "../dispatcher/dispatcher";
|
import dis from "../dispatcher/dispatcher";
|
||||||
|
@ -55,19 +54,20 @@ export interface UserWidget extends Omit<IWidgetEvent, "content"> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class WidgetUtils {
|
export default class WidgetUtils {
|
||||||
/* Returns true if user is able to send state events to modify widgets in this room
|
/**
|
||||||
|
* Returns true if user is able to send state events to modify widgets in this room
|
||||||
* (Does not apply to non-room-based / user widgets)
|
* (Does not apply to non-room-based / user widgets)
|
||||||
|
* @param client The matrix client of the logged-in user
|
||||||
* @param roomId -- The ID of the room to check
|
* @param roomId -- The ID of the room to check
|
||||||
* @return Boolean -- true if the user can modify widgets in this room
|
* @return Boolean -- true if the user can modify widgets in this room
|
||||||
* @throws Error -- specifies the error reason
|
* @throws Error -- specifies the error reason
|
||||||
*/
|
*/
|
||||||
public static canUserModifyWidgets(roomId?: string): boolean {
|
public static canUserModifyWidgets(client: MatrixClient, roomId?: string): boolean {
|
||||||
if (!roomId) {
|
if (!roomId) {
|
||||||
logger.warn("No room ID specified");
|
logger.warn("No room ID specified");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
if (!client) {
|
if (!client) {
|
||||||
logger.warn("User must be be logged in");
|
logger.warn("User must be be logged in");
|
||||||
return false;
|
return false;
|
||||||
|
@ -79,7 +79,7 @@ export default class WidgetUtils {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const me = client.credentials.userId;
|
const me = client.getUserId();
|
||||||
if (!me) {
|
if (!me) {
|
||||||
logger.warn("Failed to get user ID");
|
logger.warn("Failed to get user ID");
|
||||||
return false;
|
return false;
|
||||||
|
@ -97,6 +97,7 @@ export default class WidgetUtils {
|
||||||
// TODO: Generify the name of this function. It's not just scalar.
|
// TODO: Generify the name of this function. It's not just scalar.
|
||||||
/**
|
/**
|
||||||
* Returns true if specified url is a scalar URL, typically https://scalar.vector.im/api
|
* Returns true if specified url is a scalar URL, typically https://scalar.vector.im/api
|
||||||
|
* @param matrixClient The matrix client of the logged-in user
|
||||||
* @param {[type]} testUrlString URL to check
|
* @param {[type]} testUrlString URL to check
|
||||||
* @return {Boolean} True if specified URL is a scalar URL
|
* @return {Boolean} True if specified URL is a scalar URL
|
||||||
*/
|
*/
|
||||||
|
@ -138,13 +139,14 @@ export default class WidgetUtils {
|
||||||
* ID has been added as a user widget (ie. the accountData event
|
* ID has been added as a user widget (ie. the accountData event
|
||||||
* arrives) or rejects after a timeout
|
* arrives) or rejects after a timeout
|
||||||
*
|
*
|
||||||
* @param {string} widgetId The ID of the widget to wait for
|
* @param client The matrix client of the logged-in user
|
||||||
* @param {boolean} add True to wait for the widget to be added,
|
* @param widgetId The ID of the widget to wait for
|
||||||
|
* @param add True to wait for the widget to be added,
|
||||||
* false to wait for it to be deleted.
|
* false to wait for it to be deleted.
|
||||||
* @returns {Promise} that resolves when the widget is in the
|
* @returns {Promise} that resolves when the widget is in the
|
||||||
* requested state according to the `add` param
|
* requested state according to the `add` param
|
||||||
*/
|
*/
|
||||||
public static waitForUserWidget(widgetId: string, add: boolean): Promise<void> {
|
public static waitForUserWidget(client: MatrixClient, widgetId: string, add: boolean): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// Tests an account data event, returning true if it's in the state
|
// Tests an account data event, returning true if it's in the state
|
||||||
// we're waiting for it to be in
|
// we're waiting for it to be in
|
||||||
|
@ -157,25 +159,25 @@ export default class WidgetUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const startingAccountDataEvent = MatrixClientPeg.get().getAccountData("m.widgets");
|
const startingAccountDataEvent = client.getAccountData("m.widgets");
|
||||||
if (eventInIntendedState(startingAccountDataEvent)) {
|
if (eventInIntendedState(startingAccountDataEvent)) {
|
||||||
resolve();
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAccountData(ev: MatrixEvent): void {
|
function onAccountData(ev: MatrixEvent): void {
|
||||||
const currentAccountDataEvent = MatrixClientPeg.get().getAccountData("m.widgets");
|
const currentAccountDataEvent = client.getAccountData("m.widgets");
|
||||||
if (eventInIntendedState(currentAccountDataEvent)) {
|
if (eventInIntendedState(currentAccountDataEvent)) {
|
||||||
MatrixClientPeg.get().removeListener(ClientEvent.AccountData, onAccountData);
|
client.removeListener(ClientEvent.AccountData, onAccountData);
|
||||||
clearTimeout(timerId);
|
clearTimeout(timerId);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const timerId = window.setTimeout(() => {
|
const timerId = window.setTimeout(() => {
|
||||||
MatrixClientPeg.get().removeListener(ClientEvent.AccountData, onAccountData);
|
client.removeListener(ClientEvent.AccountData, onAccountData);
|
||||||
reject(new Error("Timed out waiting for widget ID " + widgetId + " to appear"));
|
reject(new Error("Timed out waiting for widget ID " + widgetId + " to appear"));
|
||||||
}, WIDGET_WAIT_TIME);
|
}, WIDGET_WAIT_TIME);
|
||||||
MatrixClientPeg.get().on(ClientEvent.AccountData, onAccountData);
|
client.on(ClientEvent.AccountData, onAccountData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,6 +186,7 @@ export default class WidgetUtils {
|
||||||
* ID has been added as a room widget in the given room (ie. the
|
* ID has been added as a room widget in the given room (ie. the
|
||||||
* room state event arrives) or rejects after a timeout
|
* room state event arrives) or rejects after a timeout
|
||||||
*
|
*
|
||||||
|
* @param client The matrix client of the logged-in user
|
||||||
* @param {string} widgetId The ID of the widget to wait for
|
* @param {string} widgetId The ID of the widget to wait for
|
||||||
* @param {string} roomId The ID of the room to wait for the widget in
|
* @param {string} roomId The ID of the room to wait for the widget in
|
||||||
* @param {boolean} add True to wait for the widget to be added,
|
* @param {boolean} add True to wait for the widget to be added,
|
||||||
|
@ -191,7 +194,12 @@ export default class WidgetUtils {
|
||||||
* @returns {Promise} that resolves when the widget is in the
|
* @returns {Promise} that resolves when the widget is in the
|
||||||
* requested state according to the `add` param
|
* requested state according to the `add` param
|
||||||
*/
|
*/
|
||||||
public static waitForRoomWidget(widgetId: string, roomId: string, add: boolean): Promise<void> {
|
public static waitForRoomWidget(
|
||||||
|
client: MatrixClient,
|
||||||
|
widgetId: string,
|
||||||
|
roomId: string,
|
||||||
|
add: boolean,
|
||||||
|
): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// Tests a list of state events, returning true if it's in the state
|
// Tests a list of state events, returning true if it's in the state
|
||||||
// we're waiting for it to be in
|
// we're waiting for it to be in
|
||||||
|
@ -206,7 +214,7 @@ export default class WidgetUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const room = MatrixClientPeg.get().getRoom(roomId);
|
const room = client.getRoom(roomId);
|
||||||
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
||||||
const startingWidgetEvents = room?.currentState.getStateEvents("im.vector.modular.widgets");
|
const startingWidgetEvents = room?.currentState.getStateEvents("im.vector.modular.widgets");
|
||||||
if (eventsInIntendedState(startingWidgetEvents)) {
|
if (eventsInIntendedState(startingWidgetEvents)) {
|
||||||
|
@ -221,30 +229,30 @@ export default class WidgetUtils {
|
||||||
const currentWidgetEvents = room?.currentState.getStateEvents("im.vector.modular.widgets");
|
const currentWidgetEvents = room?.currentState.getStateEvents("im.vector.modular.widgets");
|
||||||
|
|
||||||
if (eventsInIntendedState(currentWidgetEvents)) {
|
if (eventsInIntendedState(currentWidgetEvents)) {
|
||||||
MatrixClientPeg.get().removeListener(RoomStateEvent.Events, onRoomStateEvents);
|
client.removeListener(RoomStateEvent.Events, onRoomStateEvents);
|
||||||
clearTimeout(timerId);
|
clearTimeout(timerId);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const timerId = window.setTimeout(() => {
|
const timerId = window.setTimeout(() => {
|
||||||
MatrixClientPeg.get().removeListener(RoomStateEvent.Events, onRoomStateEvents);
|
client.removeListener(RoomStateEvent.Events, onRoomStateEvents);
|
||||||
reject(new Error("Timed out waiting for widget ID " + widgetId + " to appear"));
|
reject(new Error("Timed out waiting for widget ID " + widgetId + " to appear"));
|
||||||
}, WIDGET_WAIT_TIME);
|
}, WIDGET_WAIT_TIME);
|
||||||
MatrixClientPeg.get().on(RoomStateEvent.Events, onRoomStateEvents);
|
client.on(RoomStateEvent.Events, onRoomStateEvents);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static setUserWidget(
|
public static setUserWidget(
|
||||||
|
client: MatrixClient,
|
||||||
widgetId: string,
|
widgetId: string,
|
||||||
widgetType: WidgetType,
|
widgetType: WidgetType,
|
||||||
widgetUrl: string,
|
widgetUrl: string,
|
||||||
widgetName: string,
|
widgetName: string,
|
||||||
widgetData: IWidgetData,
|
widgetData: IWidgetData,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
// Get the current widgets and clone them before we modify them, otherwise
|
// Get the current widgets and clone them before we modify them, otherwise
|
||||||
// we'll modify the content of the old event.
|
// we'll modify the content of the old event.
|
||||||
const userWidgets = objectClone(WidgetUtils.getUserWidgets());
|
const userWidgets = objectClone(WidgetUtils.getUserWidgets(client));
|
||||||
|
|
||||||
// Delete existing widget with ID
|
// Delete existing widget with ID
|
||||||
try {
|
try {
|
||||||
|
@ -284,7 +292,7 @@ export default class WidgetUtils {
|
||||||
return client
|
return client
|
||||||
.setAccountData("m.widgets", userWidgets)
|
.setAccountData("m.widgets", userWidgets)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return WidgetUtils.waitForUserWidget(widgetId, addingWidget);
|
return WidgetUtils.waitForUserWidget(client, widgetId, addingWidget);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
dis.dispatch({ action: "user_widget_updated" });
|
dis.dispatch({ action: "user_widget_updated" });
|
||||||
|
@ -292,6 +300,7 @@ export default class WidgetUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static setRoomWidget(
|
public static setRoomWidget(
|
||||||
|
client: MatrixClient,
|
||||||
roomId: string,
|
roomId: string,
|
||||||
widgetId: string,
|
widgetId: string,
|
||||||
widgetType?: WidgetType,
|
widgetType?: WidgetType,
|
||||||
|
@ -318,20 +327,24 @@ export default class WidgetUtils {
|
||||||
content = {};
|
content = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return WidgetUtils.setRoomWidgetContent(roomId, widgetId, content as IWidget);
|
return WidgetUtils.setRoomWidgetContent(client, roomId, widgetId, content as IWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static setRoomWidgetContent(roomId: string, widgetId: string, content: IWidget): Promise<void> {
|
public static setRoomWidgetContent(
|
||||||
|
client: MatrixClient,
|
||||||
|
roomId: string,
|
||||||
|
widgetId: string,
|
||||||
|
content: IWidget,
|
||||||
|
): Promise<void> {
|
||||||
const addingWidget = !!content.url;
|
const addingWidget = !!content.url;
|
||||||
|
|
||||||
WidgetEchoStore.setRoomWidgetEcho(roomId, widgetId, content);
|
WidgetEchoStore.setRoomWidgetEcho(roomId, widgetId, content);
|
||||||
|
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
||||||
return client
|
return client
|
||||||
.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId)
|
.sendStateEvent(roomId, "im.vector.modular.widgets", content, widgetId)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return WidgetUtils.waitForRoomWidget(widgetId, roomId, addingWidget);
|
return WidgetUtils.waitForRoomWidget(client, widgetId, roomId, addingWidget);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
WidgetEchoStore.removeRoomWidgetEcho(roomId, widgetId);
|
WidgetEchoStore.removeRoomWidgetEcho(roomId, widgetId);
|
||||||
|
@ -357,10 +370,10 @@ export default class WidgetUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get user specific widgets (not linked to a specific room)
|
* Get user specific widgets (not linked to a specific room)
|
||||||
|
* @param client The matrix client of the logged-in user
|
||||||
* @return {object} Event content object containing current / active user widgets
|
* @return {object} Event content object containing current / active user widgets
|
||||||
*/
|
*/
|
||||||
public static getUserWidgets(): Record<string, UserWidget> {
|
public static getUserWidgets(client: MatrixClient | undefined): Record<string, UserWidget> {
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
if (!client) {
|
if (!client) {
|
||||||
throw new Error("User not logged in");
|
throw new Error("User not logged in");
|
||||||
}
|
}
|
||||||
|
@ -373,27 +386,30 @@ export default class WidgetUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get user specific widgets (not linked to a specific room) as an array
|
* Get user specific widgets (not linked to a specific room) as an array
|
||||||
|
* @param client The matrix client of the logged-in user
|
||||||
* @return {[object]} Array containing current / active user widgets
|
* @return {[object]} Array containing current / active user widgets
|
||||||
*/
|
*/
|
||||||
public static getUserWidgetsArray(): UserWidget[] {
|
public static getUserWidgetsArray(client: MatrixClient | undefined): UserWidget[] {
|
||||||
return Object.values(WidgetUtils.getUserWidgets());
|
return Object.values(WidgetUtils.getUserWidgets(client));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get active stickerpicker widgets (stickerpickers are user widgets by nature)
|
* Get active stickerpicker widgets (stickerpickers are user widgets by nature)
|
||||||
|
* @param client The matrix client of the logged-in user
|
||||||
* @return {[object]} Array containing current / active stickerpicker widgets
|
* @return {[object]} Array containing current / active stickerpicker widgets
|
||||||
*/
|
*/
|
||||||
public static getStickerpickerWidgets(): UserWidget[] {
|
public static getStickerpickerWidgets(client: MatrixClient | undefined): UserWidget[] {
|
||||||
const widgets = WidgetUtils.getUserWidgetsArray();
|
const widgets = WidgetUtils.getUserWidgetsArray(client);
|
||||||
return widgets.filter((widget) => widget.content?.type === "m.stickerpicker");
|
return widgets.filter((widget) => widget.content?.type === "m.stickerpicker");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all integration manager widgets for this user.
|
* Get all integration manager widgets for this user.
|
||||||
|
* @param client The matrix client of the logged-in user
|
||||||
* @returns {Object[]} An array of integration manager user widgets.
|
* @returns {Object[]} An array of integration manager user widgets.
|
||||||
*/
|
*/
|
||||||
public static getIntegrationManagerWidgets(): UserWidget[] {
|
public static getIntegrationManagerWidgets(client: MatrixClient | undefined): UserWidget[] {
|
||||||
const widgets = WidgetUtils.getUserWidgetsArray();
|
const widgets = WidgetUtils.getUserWidgetsArray(client);
|
||||||
return widgets.filter((w) => w.content?.type === "m.integration_manager");
|
return widgets.filter((w) => w.content?.type === "m.integration_manager");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,8 +421,7 @@ export default class WidgetUtils {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async removeIntegrationManagerWidgets(): Promise<void> {
|
public static async removeIntegrationManagerWidgets(client: MatrixClient | undefined): Promise<void> {
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
if (!client) {
|
if (!client) {
|
||||||
throw new Error("User not logged in");
|
throw new Error("User not logged in");
|
||||||
}
|
}
|
||||||
|
@ -421,8 +436,14 @@ export default class WidgetUtils {
|
||||||
await client.setAccountData("m.widgets", userWidgets);
|
await client.setAccountData("m.widgets", userWidgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static addIntegrationManagerWidget(name: string, uiUrl: string, apiUrl: string): Promise<void> {
|
public static addIntegrationManagerWidget(
|
||||||
|
client: MatrixClient,
|
||||||
|
name: string,
|
||||||
|
uiUrl: string,
|
||||||
|
apiUrl: string,
|
||||||
|
): Promise<void> {
|
||||||
return WidgetUtils.setUserWidget(
|
return WidgetUtils.setUserWidget(
|
||||||
|
client,
|
||||||
"integration_manager_" + new Date().getTime(),
|
"integration_manager_" + new Date().getTime(),
|
||||||
WidgetType.INTEGRATION_MANAGER,
|
WidgetType.INTEGRATION_MANAGER,
|
||||||
uiUrl,
|
uiUrl,
|
||||||
|
@ -433,10 +454,10 @@ export default class WidgetUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all stickerpicker widgets (stickerpickers are user widgets by nature)
|
* Remove all stickerpicker widgets (stickerpickers are user widgets by nature)
|
||||||
|
* @param client The matrix client of the logged-in user
|
||||||
* @return {Promise} Resolves on account data updated
|
* @return {Promise} Resolves on account data updated
|
||||||
*/
|
*/
|
||||||
public static async removeStickerpickerWidgets(): Promise<void> {
|
public static async removeStickerpickerWidgets(client: MatrixClient | undefined): Promise<void> {
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
if (!client) {
|
if (!client) {
|
||||||
throw new Error("User not logged in");
|
throw new Error("User not logged in");
|
||||||
}
|
}
|
||||||
|
@ -452,6 +473,7 @@ export default class WidgetUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async addJitsiWidget(
|
public static async addJitsiWidget(
|
||||||
|
client: MatrixClient,
|
||||||
roomId: string,
|
roomId: string,
|
||||||
type: CallType,
|
type: CallType,
|
||||||
name: string,
|
name: string,
|
||||||
|
@ -462,7 +484,7 @@ export default class WidgetUtils {
|
||||||
const auth = (await Jitsi.getInstance().getJitsiAuth()) ?? undefined;
|
const auth = (await Jitsi.getInstance().getJitsiAuth()) ?? undefined;
|
||||||
const widgetId = randomString(24); // Must be globally unique
|
const widgetId = randomString(24); // Must be globally unique
|
||||||
|
|
||||||
let confId;
|
let confId: string;
|
||||||
if (auth === "openidtoken-jwt") {
|
if (auth === "openidtoken-jwt") {
|
||||||
// Create conference ID from room ID
|
// Create conference ID from room ID
|
||||||
// For compatibility with Jitsi, use base32 without padding.
|
// For compatibility with Jitsi, use base32 without padding.
|
||||||
|
@ -479,9 +501,9 @@ export default class WidgetUtils {
|
||||||
widgetUrl.search = ""; // Causes the URL class use searchParams instead
|
widgetUrl.search = ""; // Causes the URL class use searchParams instead
|
||||||
widgetUrl.searchParams.set("confId", confId);
|
widgetUrl.searchParams.set("confId", confId);
|
||||||
|
|
||||||
await WidgetUtils.setRoomWidget(roomId, widgetId, WidgetType.JITSI, widgetUrl.toString(), name, {
|
await WidgetUtils.setRoomWidget(client, roomId, widgetId, WidgetType.JITSI, widgetUrl.toString(), name, {
|
||||||
conferenceId: confId,
|
conferenceId: confId,
|
||||||
roomName: oobRoomName ?? MatrixClientPeg.get().getRoom(roomId)?.name,
|
roomName: oobRoomName ?? client.getRoom(roomId)?.name,
|
||||||
isAudioOnly: type === CallType.Voice,
|
isAudioOnly: type === CallType.Voice,
|
||||||
isVideoChannel,
|
isVideoChannel,
|
||||||
domain,
|
domain,
|
||||||
|
|
|
@ -51,7 +51,7 @@ export async function startDmOnFirstMessage(client: MatrixClient, targets: Membe
|
||||||
return existingRoom.roomId;
|
return existingRoom.roomId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targets.length === 1 && targets[0] instanceof ThreepidMember && privateShouldBeEncrypted()) {
|
if (targets.length === 1 && targets[0] instanceof ThreepidMember && privateShouldBeEncrypted(client)) {
|
||||||
// Single 3rd-party invite and well-known promotes encryption:
|
// Single 3rd-party invite and well-known promotes encryption:
|
||||||
// Directly create a room and invite the other.
|
// Directly create a room and invite the other.
|
||||||
return await startDm(client, targets);
|
return await startDm(client, targets);
|
||||||
|
@ -192,7 +192,7 @@ export interface IDMUserTileProps {
|
||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
export async function determineCreateRoomEncryptionOption(client: MatrixClient, targets: Member[]): Promise<boolean> {
|
export async function determineCreateRoomEncryptionOption(client: MatrixClient, targets: Member[]): Promise<boolean> {
|
||||||
if (privateShouldBeEncrypted()) {
|
if (privateShouldBeEncrypted(client)) {
|
||||||
// Enable encryption for a single 3rd party invite.
|
// Enable encryption for a single 3rd party invite.
|
||||||
if (targets.length === 1 && targets[0] instanceof ThreepidMember) return true;
|
if (targets.length === 1 && targets[0] instanceof ThreepidMember) return true;
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,11 @@ limitations under the License.
|
||||||
|
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } 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";
|
||||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
|
||||||
import { Direction } from "matrix-js-sdk/src/models/event-timeline";
|
import { Direction } from "matrix-js-sdk/src/models/event-timeline";
|
||||||
import { saveAs } from "file-saver";
|
import { saveAs } from "file-saver";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import sanitizeFilename from "sanitize-filename";
|
import sanitizeFilename from "sanitize-filename";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
|
||||||
import { ExportType, IExportOptions } from "./exportUtils";
|
import { ExportType, IExportOptions } from "./exportUtils";
|
||||||
import { decryptFile } from "../DecryptFile";
|
import { decryptFile } from "../DecryptFile";
|
||||||
import { mediaFromContent } from "../../customisations/Media";
|
import { mediaFromContent } from "../../customisations/Media";
|
||||||
|
@ -39,7 +37,6 @@ type BlobFile = {
|
||||||
|
|
||||||
export default abstract class Exporter {
|
export default abstract class Exporter {
|
||||||
protected files: BlobFile[] = [];
|
protected files: BlobFile[] = [];
|
||||||
protected client: MatrixClient;
|
|
||||||
protected cancelled = false;
|
protected cancelled = false;
|
||||||
|
|
||||||
protected constructor(
|
protected constructor(
|
||||||
|
@ -56,7 +53,6 @@ export default abstract class Exporter {
|
||||||
) {
|
) {
|
||||||
throw new Error("Invalid export options");
|
throw new Error("Invalid export options");
|
||||||
}
|
}
|
||||||
this.client = MatrixClientPeg.get();
|
|
||||||
window.addEventListener("beforeunload", this.onBeforeUnload);
|
window.addEventListener("beforeunload", this.onBeforeUnload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +120,7 @@ export default abstract class Exporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setEventMetadata(event: MatrixEvent): MatrixEvent {
|
protected setEventMetadata(event: MatrixEvent): MatrixEvent {
|
||||||
const roomState = this.client.getRoom(this.room.roomId)?.currentState;
|
const roomState = this.room.currentState;
|
||||||
const sender = event.getSender();
|
const sender = event.getSender();
|
||||||
event.sender = (!!sender && roomState?.getSentinelMember(sender)) || null;
|
event.sender = (!!sender && roomState?.getSentinelMember(sender)) || null;
|
||||||
if (event.getType() === "m.room.member") {
|
if (event.getType() === "m.room.member") {
|
||||||
|
@ -151,7 +147,7 @@ export default abstract class Exporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getRequiredEvents(): Promise<MatrixEvent[]> {
|
protected async getRequiredEvents(): Promise<MatrixEvent[]> {
|
||||||
const eventMapper = this.client.getEventMapper();
|
const eventMapper = this.room.client.getEventMapper();
|
||||||
|
|
||||||
let prevToken: string | null = null;
|
let prevToken: string | null = null;
|
||||||
let limit = this.getLimit();
|
let limit = this.getLimit();
|
||||||
|
@ -159,7 +155,7 @@ export default abstract class Exporter {
|
||||||
|
|
||||||
while (limit) {
|
while (limit) {
|
||||||
const eventsPerCrawl = Math.min(limit, 1000);
|
const eventsPerCrawl = Math.min(limit, 1000);
|
||||||
const res = await this.client.createMessagesRequest(
|
const res = await this.room.client.createMessagesRequest(
|
||||||
this.room.roomId,
|
this.room.roomId,
|
||||||
prevToken,
|
prevToken,
|
||||||
eventsPerCrawl,
|
eventsPerCrawl,
|
||||||
|
@ -211,7 +207,7 @@ export default abstract class Exporter {
|
||||||
const decryptionPromises = events
|
const decryptionPromises = events
|
||||||
.filter((event) => event.isEncrypted())
|
.filter((event) => event.isEncrypted())
|
||||||
.map((event) => {
|
.map((event) => {
|
||||||
return this.client.decryptEventIfNeeded(event, {
|
return this.room.client.decryptEventIfNeeded(event, {
|
||||||
isRetry: true,
|
isRetry: true,
|
||||||
emit: false,
|
emit: false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -94,7 +94,7 @@ export default class HTMLExporter extends Exporter {
|
||||||
const exportDate = formatFullDateNoDayNoTime(new Date());
|
const exportDate = formatFullDateNoDayNoTime(new Date());
|
||||||
const creator = this.room.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender();
|
const creator = this.room.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender();
|
||||||
const creatorName = (creator ? this.room.getMember(creator)?.rawDisplayName : creator) || creator;
|
const creatorName = (creator ? this.room.getMember(creator)?.rawDisplayName : creator) || creator;
|
||||||
const exporter = this.client.getUserId()!;
|
const exporter = this.room.client.getSafeUserId();
|
||||||
const exporterName = this.room.getMember(exporter)?.rawDisplayName;
|
const exporterName = this.room.getMember(exporter)?.rawDisplayName;
|
||||||
const topic = this.room.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent()?.topic || "";
|
const topic = this.room.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent()?.topic || "";
|
||||||
const createdText = _t("%(creatorName)s created this room.", {
|
const createdText = _t("%(creatorName)s created this room.", {
|
||||||
|
@ -282,7 +282,7 @@ export default class HTMLExporter extends Exporter {
|
||||||
public getEventTile(mxEv: MatrixEvent, continuation: boolean): JSX.Element {
|
public getEventTile(mxEv: MatrixEvent, continuation: boolean): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="mx_Export_EventWrapper" id={mxEv.getId()}>
|
<div className="mx_Export_EventWrapper" id={mxEv.getId()}>
|
||||||
<MatrixClientContext.Provider value={this.client}>
|
<MatrixClientContext.Provider value={this.room.client}>
|
||||||
<EventTile
|
<EventTile
|
||||||
mxEvent={mxEv}
|
mxEvent={mxEv}
|
||||||
continuation={continuation}
|
continuation={continuation}
|
||||||
|
|
|
@ -47,7 +47,7 @@ export default class JSONExporter extends Exporter {
|
||||||
const creator = this.room.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender();
|
const creator = this.room.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender();
|
||||||
const creatorName = (creator && this.room?.getMember(creator)?.rawDisplayName) || creator;
|
const creatorName = (creator && this.room?.getMember(creator)?.rawDisplayName) || creator;
|
||||||
const topic = this.room.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent()?.topic || "";
|
const topic = this.room.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent()?.topic || "";
|
||||||
const exporter = this.client.getUserId()!;
|
const exporter = this.room.client.getUserId()!;
|
||||||
const exporterName = this.room?.getMember(exporter)?.rawDisplayName || exporter;
|
const exporterName = this.room?.getMember(exporter)?.rawDisplayName || exporter;
|
||||||
const jsonObject = {
|
const jsonObject = {
|
||||||
room_name: this.room.name,
|
room_name: this.room.name,
|
||||||
|
|
|
@ -19,11 +19,10 @@ import React, { ReactNode } from "react";
|
||||||
import { EventStatus } from "matrix-js-sdk/src/models/event-status";
|
import { EventStatus } from "matrix-js-sdk/src/models/event-status";
|
||||||
import { MatrixEventEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEventEvent } 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";
|
||||||
import { MatrixError } from "matrix-js-sdk/src/matrix";
|
import { MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import Modal, { IHandle } from "../Modal";
|
import Modal, { IHandle } from "../Modal";
|
||||||
import Spinner from "../components/views/elements/Spinner";
|
import Spinner from "../components/views/elements/Spinner";
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import { _t } from "../languageHandler";
|
import { _t } from "../languageHandler";
|
||||||
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
|
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
|
||||||
import { isMetaSpace } from "../stores/spaces";
|
import { isMetaSpace } from "../stores/spaces";
|
||||||
|
@ -38,15 +37,19 @@ import { bulkSpaceBehaviour } from "./space";
|
||||||
import { SdkContextClass } from "../contexts/SDKContext";
|
import { SdkContextClass } from "../contexts/SDKContext";
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
|
|
||||||
export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = true): Promise<void> {
|
export async function leaveRoomBehaviour(
|
||||||
|
matrixClient: MatrixClient,
|
||||||
|
roomId: string,
|
||||||
|
retry = true,
|
||||||
|
spinner = true,
|
||||||
|
): Promise<void> {
|
||||||
let spinnerModal: IHandle<any> | undefined;
|
let spinnerModal: IHandle<any> | undefined;
|
||||||
if (spinner) {
|
if (spinner) {
|
||||||
spinnerModal = Modal.createDialog(Spinner, undefined, "mx_Dialog_spinner");
|
spinnerModal = Modal.createDialog(Spinner, undefined, "mx_Dialog_spinner");
|
||||||
}
|
}
|
||||||
|
|
||||||
const cli = MatrixClientPeg.get();
|
|
||||||
let leavingAllVersions = true;
|
let leavingAllVersions = true;
|
||||||
const history = cli.getRoomUpgradeHistory(
|
const history = matrixClient.getRoomUpgradeHistory(
|
||||||
roomId,
|
roomId,
|
||||||
false,
|
false,
|
||||||
SettingsStore.getValue("feature_dynamic_room_predecessors"),
|
SettingsStore.getValue("feature_dynamic_room_predecessors"),
|
||||||
|
@ -60,7 +63,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const room = cli.getRoom(roomId);
|
const room = matrixClient.getRoom(roomId);
|
||||||
|
|
||||||
// should not encounter this
|
// should not encounter this
|
||||||
if (!room) {
|
if (!room) {
|
||||||
|
@ -97,9 +100,9 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
|
||||||
let results: { [roomId: string]: Error | MatrixError | null } = {};
|
let results: { [roomId: string]: Error | MatrixError | null } = {};
|
||||||
if (!leavingAllVersions) {
|
if (!leavingAllVersions) {
|
||||||
try {
|
try {
|
||||||
await cli.leave(roomId);
|
await matrixClient.leave(roomId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e?.data?.errcode) {
|
if (e instanceof MatrixError) {
|
||||||
const message = e.data.error || _t("Unexpected server error trying to leave the room");
|
const message = e.data.error || _t("Unexpected server error trying to leave the room");
|
||||||
results[roomId] = Object.assign(new Error(message), { errcode: e.data.errcode, data: e.data });
|
results[roomId] = Object.assign(new Error(message), { errcode: e.data.errcode, data: e.data });
|
||||||
} else {
|
} else {
|
||||||
|
@ -107,7 +110,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
results = await cli.leaveRoomChain(roomId, retry);
|
results = await matrixClient.leaveRoomChain(roomId, retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
|
@ -116,7 +119,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
|
||||||
) as MatrixError;
|
) as MatrixError;
|
||||||
if (limitExceededError) {
|
if (limitExceededError) {
|
||||||
await sleep(limitExceededError.data.retry_after_ms ?? 100);
|
await sleep(limitExceededError.data.retry_after_ms ?? 100);
|
||||||
return leaveRoomBehaviour(roomId, false, false);
|
return leaveRoomBehaviour(matrixClient, roomId, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +189,7 @@ export const leaveSpace = (space: Room): void => {
|
||||||
space,
|
space,
|
||||||
onFinished: async (leave: boolean, rooms: Room[]): Promise<void> => {
|
onFinished: async (leave: boolean, rooms: Room[]): Promise<void> => {
|
||||||
if (!leave) return;
|
if (!leave) return;
|
||||||
await bulkSpaceBehaviour(space, rooms, (room) => leaveRoomBehaviour(room.roomId));
|
await bulkSpaceBehaviour(space, rooms, (room) => leaveRoomBehaviour(space.client, room.roomId));
|
||||||
|
|
||||||
dis.dispatch<AfterLeaveRoomPayload>({
|
dis.dispatch<AfterLeaveRoomPayload>({
|
||||||
action: Action.AfterLeaveRoom,
|
action: Action.AfterLeaveRoom,
|
||||||
|
|
|
@ -18,7 +18,6 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/matrix";
|
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import defaultDispatcher from "../dispatcher/dispatcher";
|
import defaultDispatcher from "../dispatcher/dispatcher";
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import { LocalRoom, LocalRoomState } from "../models/LocalRoom";
|
import { LocalRoom, LocalRoomState } from "../models/LocalRoom";
|
||||||
import { isLocalRoom } from "./localRoom/isLocalRoom";
|
import { isLocalRoom } from "./localRoom/isLocalRoom";
|
||||||
import { isRoomReady } from "./localRoom/isRoomReady";
|
import { isRoomReady } from "./localRoom/isRoomReady";
|
||||||
|
@ -39,10 +38,9 @@ import { isRoomReady } from "./localRoom/isRoomReady";
|
||||||
export async function doMaybeLocalRoomAction<T>(
|
export async function doMaybeLocalRoomAction<T>(
|
||||||
roomId: string,
|
roomId: string,
|
||||||
fn: (actualRoomId: string) => Promise<T>,
|
fn: (actualRoomId: string) => Promise<T>,
|
||||||
client?: MatrixClient,
|
client: MatrixClient,
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
if (isLocalRoom(roomId)) {
|
if (isLocalRoom(roomId)) {
|
||||||
client = client ?? MatrixClientPeg.get();
|
|
||||||
const room = client.getRoom(roomId) as LocalRoom;
|
const room = client.getRoom(roomId) as LocalRoom;
|
||||||
|
|
||||||
if (room.isCreated) {
|
if (room.isCreated) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import SdkConfig from "../../SdkConfig";
|
import SdkConfig from "../../SdkConfig";
|
||||||
import { getTileServerWellKnown } from "../WellKnownUtils";
|
import { getTileServerWellKnown } from "../WellKnownUtils";
|
||||||
|
@ -25,8 +26,8 @@ import { LocationShareError } from "./LocationShareErrors";
|
||||||
* .well-known location, or, failing that, in our local config, or, failing
|
* .well-known location, or, failing that, in our local config, or, failing
|
||||||
* that, defaults to the same tile server listed by matrix.org.
|
* that, defaults to the same tile server listed by matrix.org.
|
||||||
*/
|
*/
|
||||||
export function findMapStyleUrl(): string {
|
export function findMapStyleUrl(matrixClient: MatrixClient): string {
|
||||||
const mapStyleUrl = getTileServerWellKnown()?.map_style_url ?? SdkConfig.get().map_style_url;
|
const mapStyleUrl = getTileServerWellKnown(matrixClient)?.map_style_url ?? SdkConfig.get().map_style_url;
|
||||||
|
|
||||||
if (!mapStyleUrl) {
|
if (!mapStyleUrl) {
|
||||||
logger.error("'map_style_url' missing from homeserver .well-known area, and missing from from config.json.");
|
logger.error("'map_style_url' missing from homeserver .well-known area, and missing from from config.json.");
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as maplibregl from "maplibre-gl";
|
import * as maplibregl from "maplibre-gl";
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
|
import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||||
import { M_LOCATION } from "matrix-js-sdk/src/@types/location";
|
import { M_LOCATION } from "matrix-js-sdk/src/@types/location";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
@ -24,9 +24,14 @@ import { parseGeoUri } from "./parseGeoUri";
|
||||||
import { findMapStyleUrl } from "./findMapStyleUrl";
|
import { findMapStyleUrl } from "./findMapStyleUrl";
|
||||||
import { LocationShareError } from "./LocationShareErrors";
|
import { LocationShareError } from "./LocationShareErrors";
|
||||||
|
|
||||||
export const createMap = (interactive: boolean, bodyId: string, onError?: (error: Error) => void): maplibregl.Map => {
|
export const createMap = (
|
||||||
|
client: MatrixClient,
|
||||||
|
interactive: boolean,
|
||||||
|
bodyId: string,
|
||||||
|
onError?: (error: Error) => void,
|
||||||
|
): maplibregl.Map => {
|
||||||
try {
|
try {
|
||||||
const styleUrl = findMapStyleUrl();
|
const styleUrl = findMapStyleUrl(client);
|
||||||
|
|
||||||
const map = new maplibregl.Map({
|
const map = new maplibregl.Map({
|
||||||
container: bodyId,
|
container: bodyId,
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { useEffect, useState } from "react";
|
||||||
import { Map as MapLibreMap } from "maplibre-gl";
|
import { Map as MapLibreMap } from "maplibre-gl";
|
||||||
|
|
||||||
import { createMap } from "./map";
|
import { createMap } from "./map";
|
||||||
|
import { useMatrixClientContext } from "../../contexts/MatrixClientContext";
|
||||||
|
|
||||||
interface UseMapProps {
|
interface UseMapProps {
|
||||||
bodyId: string;
|
bodyId: string;
|
||||||
|
@ -32,12 +33,13 @@ interface UseMapProps {
|
||||||
* As map is recreated on changes to it
|
* As map is recreated on changes to it
|
||||||
*/
|
*/
|
||||||
export const useMap = ({ interactive, bodyId, onError }: UseMapProps): MapLibreMap | undefined => {
|
export const useMap = ({ interactive, bodyId, onError }: UseMapProps): MapLibreMap | undefined => {
|
||||||
|
const cli = useMatrixClientContext();
|
||||||
const [map, setMap] = useState<MapLibreMap>();
|
const [map, setMap] = useState<MapLibreMap>();
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() => {
|
() => {
|
||||||
try {
|
try {
|
||||||
setMap(createMap(!!interactive, bodyId, onError));
|
setMap(createMap(cli, !!interactive, bodyId, onError));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
onError?.(error);
|
onError?.(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,13 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { IConfigOptions } from "../IConfigOptions";
|
import { IConfigOptions } from "../IConfigOptions";
|
||||||
import { getEmbeddedPagesWellKnown } from "../utils/WellKnownUtils";
|
import { getEmbeddedPagesWellKnown } from "../utils/WellKnownUtils";
|
||||||
import { SnakedObject } from "./SnakedObject";
|
import { SnakedObject } from "./SnakedObject";
|
||||||
|
|
||||||
export function getHomePageUrl(appConfig: IConfigOptions): string | undefined {
|
export function getHomePageUrl(appConfig: IConfigOptions, matrixClient: MatrixClient): string | undefined {
|
||||||
const config = new SnakedObject(appConfig);
|
const config = new SnakedObject(appConfig);
|
||||||
|
|
||||||
const pagesConfig = config.get("embedded_pages");
|
const pagesConfig = config.get("embedded_pages");
|
||||||
|
@ -40,7 +41,7 @@ export function getHomePageUrl(appConfig: IConfigOptions): string | undefined {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pageUrl) {
|
if (!pageUrl) {
|
||||||
pageUrl = getEmbeddedPagesWellKnown()?.home_url;
|
pageUrl = getEmbeddedPagesWellKnown(matrixClient)?.home_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageUrl;
|
return pageUrl;
|
||||||
|
|
|
@ -20,8 +20,8 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
||||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
|
||||||
import MatrixToPermalinkConstructor, {
|
import MatrixToPermalinkConstructor, {
|
||||||
baseUrl as matrixtoBaseUrl,
|
baseUrl as matrixtoBaseUrl,
|
||||||
baseUrlPattern as matrixToBaseUrlPattern,
|
baseUrlPattern as matrixToBaseUrlPattern,
|
||||||
|
@ -284,7 +284,7 @@ export function makeUserPermalink(userId: string): string {
|
||||||
return getPermalinkConstructor().forUser(userId);
|
return getPermalinkConstructor().forUser(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeRoomPermalink(roomId: string): string {
|
export function makeRoomPermalink(matrixClient: MatrixClient, roomId: string): string {
|
||||||
if (!roomId) {
|
if (!roomId) {
|
||||||
throw new Error("can't permalink a falsy roomId");
|
throw new Error("can't permalink a falsy roomId");
|
||||||
}
|
}
|
||||||
|
@ -293,8 +293,7 @@ export function makeRoomPermalink(roomId: string): string {
|
||||||
// Aliases are already routable, and don't need extra information.
|
// Aliases are already routable, and don't need extra information.
|
||||||
if (roomId[0] !== "!") return getPermalinkConstructor().forRoom(roomId, []);
|
if (roomId[0] !== "!") return getPermalinkConstructor().forRoom(roomId, []);
|
||||||
|
|
||||||
const client = MatrixClientPeg.get();
|
const room = matrixClient.getRoom(roomId);
|
||||||
const room = client.getRoom(roomId);
|
|
||||||
if (!room) {
|
if (!room) {
|
||||||
return getPermalinkConstructor().forRoom(roomId, []);
|
return getPermalinkConstructor().forRoom(roomId, []);
|
||||||
}
|
}
|
||||||
|
@ -317,11 +316,11 @@ export function isPermalinkHost(host: string): boolean {
|
||||||
* @param {string} entity The entity to transform.
|
* @param {string} entity The entity to transform.
|
||||||
* @returns {string|null} The transformed permalink or null if unable.
|
* @returns {string|null} The transformed permalink or null if unable.
|
||||||
*/
|
*/
|
||||||
export function tryTransformEntityToPermalink(entity: string): string | null {
|
export function tryTransformEntityToPermalink(matrixClient: MatrixClient, entity: string): string | null {
|
||||||
if (!entity) return null;
|
if (!entity) return null;
|
||||||
|
|
||||||
// Check to see if it is a bare entity for starters
|
// Check to see if it is a bare entity for starters
|
||||||
if (entity[0] === "#" || entity[0] === "!") return makeRoomPermalink(entity);
|
if (entity[0] === "#" || entity[0] === "!") return makeRoomPermalink(matrixClient, entity);
|
||||||
if (entity[0] === "@") return makeUserPermalink(entity);
|
if (entity[0] === "@") return makeUserPermalink(entity);
|
||||||
|
|
||||||
if (entity.slice(0, 7) === "matrix:") {
|
if (entity.slice(0, 7) === "matrix:") {
|
||||||
|
|
|
@ -18,8 +18,8 @@ import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import { PushProcessor } from "matrix-js-sdk/src/pushprocessor";
|
import { PushProcessor } from "matrix-js-sdk/src/pushprocessor";
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import { Pill, PillType, pillRoomNotifLen, pillRoomNotifPos } from "../components/views/elements/Pill";
|
import { Pill, PillType, pillRoomNotifLen, pillRoomNotifPos } from "../components/views/elements/Pill";
|
||||||
import { parsePermalink } from "./permalinks/Permalinks";
|
import { parsePermalink } from "./permalinks/Permalinks";
|
||||||
|
@ -51,6 +51,7 @@ const shouldBePillified = (node: Element, href: string, parts: PermalinkParts |
|
||||||
* into pills based on the context of a given room. Returns a list of
|
* into pills based on the context of a given room. Returns a list of
|
||||||
* the resulting React nodes so they can be unmounted rather than leaking.
|
* the resulting React nodes so they can be unmounted rather than leaking.
|
||||||
*
|
*
|
||||||
|
* @param matrixClient the client of the logged-in user
|
||||||
* @param {Element[]} nodes - a list of sibling DOM nodes to traverse to try
|
* @param {Element[]} nodes - a list of sibling DOM nodes to traverse to try
|
||||||
* to turn into pills.
|
* to turn into pills.
|
||||||
* @param {MatrixEvent} mxEvent - the matrix event which the DOM nodes are
|
* @param {MatrixEvent} mxEvent - the matrix event which the DOM nodes are
|
||||||
|
@ -59,8 +60,13 @@ const shouldBePillified = (node: Element, href: string, parts: PermalinkParts |
|
||||||
* React components which have been mounted as part of this.
|
* React components which have been mounted as part of this.
|
||||||
* The initial caller should pass in an empty array to seed the accumulator.
|
* The initial caller should pass in an empty array to seed the accumulator.
|
||||||
*/
|
*/
|
||||||
export function pillifyLinks(nodes: ArrayLike<Element>, mxEvent: MatrixEvent, pills: Element[]): void {
|
export function pillifyLinks(
|
||||||
const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId()) ?? undefined;
|
matrixClient: MatrixClient,
|
||||||
|
nodes: ArrayLike<Element>,
|
||||||
|
mxEvent: MatrixEvent,
|
||||||
|
pills: Element[],
|
||||||
|
): void {
|
||||||
|
const room = matrixClient.getRoom(mxEvent.getRoomId()) ?? undefined;
|
||||||
const shouldShowPillAvatar = SettingsStore.getValue("Pill.shouldShowPillAvatar");
|
const shouldShowPillAvatar = SettingsStore.getValue("Pill.shouldShowPillAvatar");
|
||||||
let node = nodes[0];
|
let node = nodes[0];
|
||||||
while (node) {
|
while (node) {
|
||||||
|
@ -118,7 +124,7 @@ export function pillifyLinks(nodes: ArrayLike<Element>, mxEvent: MatrixEvent, pi
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roomNotifTextNodes.length > 0) {
|
if (roomNotifTextNodes.length > 0) {
|
||||||
const pushProcessor = new PushProcessor(MatrixClientPeg.get());
|
const pushProcessor = new PushProcessor(matrixClient);
|
||||||
const atRoomRule = pushProcessor.getPushRuleById(".m.rule.roomnotif");
|
const atRoomRule = pushProcessor.getPushRuleById(".m.rule.roomnotif");
|
||||||
if (atRoomRule && pushProcessor.ruleMatchesEvent(atRoomRule, mxEvent)) {
|
if (atRoomRule && pushProcessor.ruleMatchesEvent(atRoomRule, mxEvent)) {
|
||||||
// Now replace all those nodes with Pills
|
// Now replace all those nodes with Pills
|
||||||
|
@ -151,7 +157,7 @@ export function pillifyLinks(nodes: ArrayLike<Element>, mxEvent: MatrixEvent, pi
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.childNodes && node.childNodes.length && !pillified) {
|
if (node.childNodes && node.childNodes.length && !pillified) {
|
||||||
pillifyLinks(node.childNodes as NodeListOf<Element>, mxEvent, pills);
|
pillifyLinks(matrixClient, node.childNodes as NodeListOf<Element>, mxEvent, pills);
|
||||||
}
|
}
|
||||||
|
|
||||||
node = node.nextSibling as Element;
|
node = node.nextSibling as Element;
|
||||||
|
|
|
@ -14,11 +14,12 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import SdkConfig from "../SdkConfig";
|
import SdkConfig from "../SdkConfig";
|
||||||
|
|
||||||
export function isPresenceEnabled(): boolean {
|
export function isPresenceEnabled(matrixClient: MatrixClient): boolean {
|
||||||
const hsUrl = MatrixClientPeg.get().baseUrl;
|
const hsUrl = matrixClient.baseUrl;
|
||||||
const urls = SdkConfig.get("enable_presence_by_hs_url");
|
const urls = SdkConfig.get("enable_presence_by_hs_url");
|
||||||
if (!urls) return true;
|
if (!urls) return true;
|
||||||
if (urls[hsUrl] || urls[hsUrl] === undefined) return true;
|
if (urls[hsUrl] || urls[hsUrl] === undefined) return true;
|
||||||
|
|
|
@ -27,7 +27,7 @@ export const shouldEncryptRoomWithSingle3rdPartyInvite = (
|
||||||
room: Room,
|
room: Room,
|
||||||
): { shouldEncrypt: true; inviteEvent: MatrixEvent } | { shouldEncrypt: false; inviteEvent?: undefined } => {
|
): { shouldEncrypt: true; inviteEvent: MatrixEvent } | { shouldEncrypt: false; inviteEvent?: undefined } => {
|
||||||
// encryption not promoted via .well-known
|
// encryption not promoted via .well-known
|
||||||
if (!privateShouldBeEncrypted()) return { shouldEncrypt: false };
|
if (!privateShouldBeEncrypted(room.client)) return { shouldEncrypt: false };
|
||||||
|
|
||||||
// not a DM room
|
// not a DM room
|
||||||
if (!DMRoomMap.shared().getRoomIds().has(room.roomId)) return { shouldEncrypt: false };
|
if (!DMRoomMap.shared().getRoomIds().has(room.roomId)) return { shouldEncrypt: false };
|
||||||
|
|
|
@ -14,10 +14,12 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { getE2EEWellKnown } from "./WellKnownUtils";
|
import { getE2EEWellKnown } from "./WellKnownUtils";
|
||||||
|
|
||||||
export function privateShouldBeEncrypted(): boolean {
|
export function privateShouldBeEncrypted(client: MatrixClient): boolean {
|
||||||
const e2eeWellKnown = getE2EEWellKnown();
|
const e2eeWellKnown = getE2EEWellKnown(client);
|
||||||
if (e2eeWellKnown) {
|
if (e2eeWellKnown) {
|
||||||
const defaultDisabled = e2eeWellKnown["default"] === false;
|
const defaultDisabled = e2eeWellKnown["default"] === false;
|
||||||
return !defaultDisabled;
|
return !defaultDisabled;
|
||||||
|
|
|
@ -38,7 +38,7 @@ function getWidgetBuildUrl(): string | undefined {
|
||||||
return SdkConfig.get().widget_build_url;
|
return SdkConfig.get().widget_build_url;
|
||||||
}
|
}
|
||||||
/* eslint-disable-next-line camelcase */
|
/* eslint-disable-next-line camelcase */
|
||||||
return getCallBehaviourWellKnown()?.widget_build_url;
|
return getCallBehaviourWellKnown(MatrixClientPeg.get())?.widget_build_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isManagedHybridWidgetEnabled(): boolean {
|
export function isManagedHybridWidgetEnabled(): boolean {
|
||||||
|
@ -53,7 +53,7 @@ export async function addManagedHybridWidget(roomId: string): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for permission
|
// Check for permission
|
||||||
if (!WidgetUtils.canUserModifyWidgets(roomId)) {
|
if (!WidgetUtils.canUserModifyWidgets(cli, roomId)) {
|
||||||
logger.error(`User not allowed to modify widgets in ${roomId}`);
|
logger.error(`User not allowed to modify widgets in ${roomId}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ export async function addManagedHybridWidget(roomId: string): Promise<void> {
|
||||||
|
|
||||||
// Add the widget
|
// Add the widget
|
||||||
try {
|
try {
|
||||||
await WidgetUtils.setRoomWidgetContent(roomId, widgetId, widgetContent);
|
await WidgetUtils.setRoomWidgetContent(cli, roomId, widgetId, widgetContent);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(`Unable to add managed hybrid widget in room ${roomId}`, e);
|
logger.error(`Unable to add managed hybrid widget in room ${roomId}`, e);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -112,7 +112,7 @@ describe("MessagePanel", function () {
|
||||||
return arg === "showDisplaynameChanges";
|
return arg === "showDisplaynameChanges";
|
||||||
});
|
});
|
||||||
|
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
|
|
@ -91,7 +91,7 @@ describe("PipContainer", () => {
|
||||||
|
|
||||||
stubClient();
|
stubClient();
|
||||||
client = mocked(MatrixClientPeg.get());
|
client = mocked(MatrixClientPeg.get());
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
|
|
||||||
room = new Room("!1:example.org", client, "@alice:example.org", {
|
room = new Room("!1:example.org", client, "@alice:example.org", {
|
||||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||||
|
|
|
@ -48,7 +48,7 @@ describe("RightPanel", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
stubClient();
|
stubClient();
|
||||||
cli = mocked(MatrixClientPeg.get());
|
cli = mocked(MatrixClientPeg.get());
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(cli);
|
||||||
context = new SdkContextClass();
|
context = new SdkContextClass();
|
||||||
context.client = cli;
|
context.client = cli;
|
||||||
RightPanel = wrapInSdkContext(RightPanelBase, context);
|
RightPanel = wrapInSdkContext(RightPanelBase, context);
|
||||||
|
|
|
@ -83,7 +83,7 @@ describe("RoomView", () => {
|
||||||
room.on(RoomEvent.Timeline, (...args) => cli.emit(RoomEvent.Timeline, ...args));
|
room.on(RoomEvent.Timeline, (...args) => cli.emit(RoomEvent.Timeline, ...args));
|
||||||
room.on(RoomEvent.TimelineReset, (...args) => cli.emit(RoomEvent.TimelineReset, ...args));
|
room.on(RoomEvent.TimelineReset, (...args) => cli.emit(RoomEvent.TimelineReset, ...args));
|
||||||
|
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(cli);
|
||||||
stores = new SdkContextClass();
|
stores = new SdkContextClass();
|
||||||
stores.client = cli;
|
stores.client = cli;
|
||||||
stores.rightPanelStore.useUnitTestClient(cli);
|
stores.rightPanelStore.useUnitTestClient(cli);
|
||||||
|
@ -457,7 +457,7 @@ describe("RoomView", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("the last Jitsi widget should be removed", () => {
|
it("the last Jitsi widget should be removed", () => {
|
||||||
expect(WidgetUtils.setRoomWidget).toHaveBeenCalledWith(room.roomId, widget2Id);
|
expect(WidgetUtils.setRoomWidget).toHaveBeenCalledWith(cli, room.roomId, widget2Id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ describe("ThreadView", () => {
|
||||||
|
|
||||||
rootEvent = res.rootEvent;
|
rootEvent = res.rootEvent;
|
||||||
|
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(mockClient);
|
||||||
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(SENDER);
|
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(SENDER);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ describe("ForwardDialog", () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(mockClient);
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
mockClient.getUserId.mockReturnValue("@bob:example.org");
|
mockClient.getUserId.mockReturnValue("@bob:example.org");
|
||||||
mockClient.getSafeUserId.mockReturnValue("@bob:example.org");
|
mockClient.getSafeUserId.mockReturnValue("@bob:example.org");
|
||||||
|
|
|
@ -143,7 +143,7 @@ describe("InviteDialog", () => {
|
||||||
getClientWellKnown: jest.fn().mockResolvedValue({}),
|
getClientWellKnown: jest.fn().mockResolvedValue({}),
|
||||||
});
|
});
|
||||||
SdkConfig.put({ validated_server_config: {} as ValidatedServerConfig } as IConfigOptions);
|
SdkConfig.put({ validated_server_config: {} as ValidatedServerConfig } as IConfigOptions);
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(mockClient);
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
|
||||||
room = new Room(roomId, mockClient, mockClient.getSafeUserId());
|
room = new Room(roomId, mockClient, mockClient.getSafeUserId());
|
||||||
|
|
|
@ -86,7 +86,7 @@ describe("AppTile", () => {
|
||||||
cli.hasLazyLoadMembersEnabled = () => false;
|
cli.hasLazyLoadMembersEnabled = () => false;
|
||||||
|
|
||||||
// Init misc. startup deps
|
// Init misc. startup deps
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(cli);
|
||||||
|
|
||||||
r1 = new Room("r1", cli, "@name:example.com");
|
r1 = new Room("r1", cli, "@name:example.com");
|
||||||
r2 = new Room("r2", cli, "@name:example.com");
|
r2 = new Room("r2", cli, "@name:example.com");
|
||||||
|
|
|
@ -75,7 +75,7 @@ describe("<Pill>", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
client = mocked(stubClient());
|
client = mocked(stubClient());
|
||||||
SdkContextClass.instance.client = client;
|
SdkContextClass.instance.client = client;
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
room1 = new Room(room1Id, client, user1Id);
|
room1 = new Room(room1Id, client, user1Id);
|
||||||
room1.name = "Room 1";
|
room1.name = "Room 1";
|
||||||
const user1JoinRoom1Event = mkRoomMemberJoinEvent(user1Id, room1Id, {
|
const user1JoinRoom1Event = mkRoomMemberJoinEvent(user1Id, room1Id, {
|
||||||
|
|
|
@ -120,7 +120,7 @@ describe("<TextualBody />", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
it("renders m.emote correctly", () => {
|
it("renders m.emote correctly", () => {
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(defaultMatrixClient);
|
||||||
|
|
||||||
const ev = mkEvent({
|
const ev = mkEvent({
|
||||||
type: "m.room.message",
|
type: "m.room.message",
|
||||||
|
@ -140,7 +140,7 @@ describe("<TextualBody />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders m.notice correctly", () => {
|
it("renders m.notice correctly", () => {
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(defaultMatrixClient);
|
||||||
|
|
||||||
const ev = mkEvent({
|
const ev = mkEvent({
|
||||||
type: "m.room.message",
|
type: "m.room.message",
|
||||||
|
@ -161,7 +161,7 @@ describe("<TextualBody />", () => {
|
||||||
|
|
||||||
describe("renders plain-text m.text correctly", () => {
|
describe("renders plain-text m.text correctly", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(defaultMatrixClient);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("simple message renders as expected", () => {
|
it("simple message renders as expected", () => {
|
||||||
|
@ -264,7 +264,7 @@ describe("<TextualBody />", () => {
|
||||||
isGuest: () => false,
|
isGuest: () => false,
|
||||||
mxcUrlToHttp: (s: string) => s,
|
mxcUrlToHttp: (s: string) => s,
|
||||||
});
|
});
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(defaultMatrixClient);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("italics, bold, underline and strikethrough render as expected", () => {
|
it("italics, bold, underline and strikethrough render as expected", () => {
|
||||||
|
@ -408,7 +408,7 @@ describe("<TextualBody />", () => {
|
||||||
isGuest: () => false,
|
isGuest: () => false,
|
||||||
mxcUrlToHttp: (s: string) => s,
|
mxcUrlToHttp: (s: string) => s,
|
||||||
});
|
});
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(defaultMatrixClient);
|
||||||
|
|
||||||
const ev = mkRoomTextMessage("Visit https://matrix.org/");
|
const ev = mkRoomTextMessage("Visit https://matrix.org/");
|
||||||
const { container, rerender } = getComponent(
|
const { container, rerender } = getComponent(
|
||||||
|
|
|
@ -71,7 +71,7 @@ describe("<RoomSummaryCard />", () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(mockClient);
|
||||||
|
|
||||||
mockClient.getRoom.mockReturnValue(room);
|
mockClient.getRoom.mockReturnValue(room);
|
||||||
jest.spyOn(room, "isElementVideoRoom").mockRestore();
|
jest.spyOn(room, "isElementVideoRoom").mockRestore();
|
||||||
|
|
|
@ -97,7 +97,7 @@ describe("<EditMessageComposer/>", () => {
|
||||||
|
|
||||||
userEvent.setup();
|
userEvent.setup();
|
||||||
|
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(mockClient);
|
||||||
|
|
||||||
jest.spyOn(Autocompleter.prototype, "getCompletions").mockResolvedValue([
|
jest.spyOn(Autocompleter.prototype, "getCompletions").mockResolvedValue([
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,7 @@ describe("NewRoomIntro", () => {
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
client = stubClient();
|
client = stubClient();
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("for a DM Room", () => {
|
describe("for a DM Room", () => {
|
||||||
|
|
|
@ -112,7 +112,7 @@ describe("RoomHeader", () => {
|
||||||
[MediaDeviceKindEnum.AudioOutput]: [],
|
[MediaDeviceKindEnum.AudioOutput]: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(carol.userId);
|
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(carol.userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -761,7 +761,7 @@ function createRoom(info: IRoomCreationInfo) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
DMRoomMap.makeShared().start();
|
DMRoomMap.makeShared(client).start();
|
||||||
|
|
||||||
const room = new Room(roomId, client, userId, {
|
const room = new Room(roomId, client, userId, {
|
||||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||||
|
|
|
@ -33,8 +33,9 @@ jest.mock("../../../../src/IdentityAuthClient", () => {
|
||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
|
|
||||||
const createRoom = (roomId: string, userId: string): Room => {
|
const createRoom = (roomId: string, userId: string): Room => {
|
||||||
const newRoom = new Room(roomId, MatrixClientPeg.get(), userId, {});
|
const cli = MatrixClientPeg.get();
|
||||||
DMRoomMap.makeShared().start();
|
const newRoom = new Room(roomId, cli, userId, {});
|
||||||
|
DMRoomMap.makeShared(cli).start();
|
||||||
return newRoom;
|
return newRoom;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ describe("RoomPreviewCard", () => {
|
||||||
stubClient();
|
stubClient();
|
||||||
client = mocked(MatrixClientPeg.get());
|
client = mocked(MatrixClientPeg.get());
|
||||||
client.getUserId.mockReturnValue("@alice:example.org");
|
client.getUserId.mockReturnValue("@alice:example.org");
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
|
|
||||||
room = new Room("!1:example.org", client, "@alice:example.org", {
|
room = new Room("!1:example.org", client, "@alice:example.org", {
|
||||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||||
|
|
|
@ -90,7 +90,7 @@ describe("RoomTile", () => {
|
||||||
|
|
||||||
client = mocked(stubClient());
|
client = mocked(stubClient());
|
||||||
sdkContext.client = client;
|
sdkContext.client = client;
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
|
|
||||||
room = new Room("!1:example.org", client, "@alice:example.org", {
|
room = new Room("!1:example.org", client, "@alice:example.org", {
|
||||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||||
|
|
|
@ -159,7 +159,7 @@ describe("<SpacePanel />", () => {
|
||||||
mkStubRoom("!room2:server", "Room 2", mockClient),
|
mkStubRoom("!room2:server", "Room 2", mockClient),
|
||||||
mkStubRoom("!room3:server", "Room 3", mockClient),
|
mkStubRoom("!room3:server", "Room 3", mockClient),
|
||||||
];
|
];
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(mockClient);
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
const { getByLabelText } = render(<SpacePanel />);
|
const { getByLabelText } = render(<SpacePanel />);
|
||||||
|
|
|
@ -40,7 +40,7 @@ jest.mock("../../../../src/stores/spaces/SpaceStore", () => {
|
||||||
describe("SpaceButton", () => {
|
describe("SpaceButton", () => {
|
||||||
stubClient();
|
stubClient();
|
||||||
const space = mkRoom(MatrixClientPeg.get(), "!1:example.org");
|
const space = mkRoom(MatrixClientPeg.get(), "!1:example.org");
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(MatrixClientPeg.get());
|
||||||
|
|
||||||
const dispatchSpy = jest.spyOn(defaultDispatcher, "dispatch");
|
const dispatchSpy = jest.spyOn(defaultDispatcher, "dispatch");
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ describe("RightPanelStore", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
stubClient();
|
stubClient();
|
||||||
cli = mocked(MatrixClientPeg.get());
|
cli = mocked(MatrixClientPeg.get());
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(cli);
|
||||||
|
|
||||||
// Make sure we start with a clean store
|
// Make sure we start with a clean store
|
||||||
store.reset();
|
store.reset();
|
||||||
|
|
|
@ -162,7 +162,7 @@ describe("RoomListStore", () => {
|
||||||
room1.updateMyMembership("join");
|
room1.updateMyMembership("join");
|
||||||
room2.updateMyMembership("join");
|
room2.updateMyMembership("join");
|
||||||
room3.updateMyMembership("join");
|
room3.updateMyMembership("join");
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
const { store } = createStore();
|
const { store } = createStore();
|
||||||
client.getVisibleRooms = jest.fn().mockReturnValue([room1, room2, room3]);
|
client.getVisibleRooms = jest.fn().mockReturnValue([room1, room2, room3]);
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ describe("RoomListStore", () => {
|
||||||
|
|
||||||
it("Passes the feature flag on to the client when asking for visible rooms", () => {
|
it("Passes the feature flag on to the client when asking for visible rooms", () => {
|
||||||
// Given a store that we can ask for a room list
|
// Given a store that we can ask for a room list
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
const { store } = createStore();
|
const { store } = createStore();
|
||||||
client.getVisibleRooms = jest.fn().mockReturnValue([]);
|
client.getVisibleRooms = jest.fn().mockReturnValue([]);
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ describe("Algorithm", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
stubClient();
|
stubClient();
|
||||||
client = mocked(MatrixClientPeg.get());
|
client = mocked(MatrixClientPeg.get());
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared(client);
|
||||||
|
|
||||||
algorithm = new Algorithm();
|
algorithm = new Algorithm();
|
||||||
algorithm.start();
|
algorithm.start();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue