Pass around MatrixClients instead of using MatrixClientPeg (#11000)

This commit is contained in:
Michael Telatynski 2023-05-30 10:36:34 +01:00 committed by GitHub
parent aa5a2e1363
commit 938aefc51c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 176 additions and 141 deletions

View file

@ -16,18 +16,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { IAuthData, IRequestMsisdnTokenResponse, IRequestTokenResponse } from "matrix-js-sdk/src/matrix";
import { IAuthData, IRequestMsisdnTokenResponse, IRequestTokenResponse, MatrixClient } from "matrix-js-sdk/src/matrix";
import { MatrixError, HTTPError } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "./MatrixClientPeg";
import Modal from "./Modal";
import { _t, UserFriendlyError } from "./languageHandler";
import IdentityAuthClient from "./IdentityAuthClient";
import { SSOAuthEntry } from "./components/views/auth/InteractiveAuthEntryComponents";
import InteractiveAuthDialog from "./components/views/dialogs/InteractiveAuthDialog";
function getIdServerDomain(): string {
const idBaseUrl = MatrixClientPeg.get().getIdentityServerUrl(true);
function getIdServerDomain(matrixClient: MatrixClient): string {
const idBaseUrl = matrixClient.getIdentityServerUrl(true);
if (!idBaseUrl) {
throw new UserFriendlyError("Identity server not set");
}
@ -55,11 +54,11 @@ export type Binding = {
export default class AddThreepid {
private sessionId: string;
private submitUrl?: string;
private clientSecret: string;
private bind = false;
private readonly clientSecret: string;
public constructor() {
this.clientSecret = MatrixClientPeg.get().generateClientSecret();
public constructor(private readonly matrixClient: MatrixClient) {
this.clientSecret = matrixClient.generateClientSecret();
}
/**
@ -70,7 +69,7 @@ export default class AddThreepid {
*/
public async addEmailAddress(emailAddress: string): Promise<IRequestTokenResponse> {
try {
const res = await MatrixClientPeg.get().requestAdd3pidEmailToken(emailAddress, this.clientSecret, 1);
const res = await this.matrixClient.requestAdd3pidEmailToken(emailAddress, this.clientSecret, 1);
this.sessionId = res.sid;
return res;
} catch (err) {
@ -90,12 +89,12 @@ export default class AddThreepid {
*/
public async bindEmailAddress(emailAddress: string): Promise<IRequestTokenResponse> {
this.bind = true;
if (await MatrixClientPeg.get().doesServerSupportSeparateAddAndBind()) {
if (await this.matrixClient.doesServerSupportSeparateAddAndBind()) {
// For separate bind, request a token directly from the IS.
const authClient = new IdentityAuthClient();
const identityAccessToken = (await authClient.getAccessToken()) ?? undefined;
try {
const res = await MatrixClientPeg.get().requestEmailToken(
const res = await this.matrixClient.requestEmailToken(
emailAddress,
this.clientSecret,
1,
@ -126,7 +125,7 @@ export default class AddThreepid {
*/
public async addMsisdn(phoneCountry: string, phoneNumber: string): Promise<IRequestMsisdnTokenResponse> {
try {
const res = await MatrixClientPeg.get().requestAdd3pidMsisdnToken(
const res = await this.matrixClient.requestAdd3pidMsisdnToken(
phoneCountry,
phoneNumber,
this.clientSecret,
@ -153,12 +152,12 @@ export default class AddThreepid {
*/
public async bindMsisdn(phoneCountry: string, phoneNumber: string): Promise<IRequestMsisdnTokenResponse> {
this.bind = true;
if (await MatrixClientPeg.get().doesServerSupportSeparateAddAndBind()) {
if (await this.matrixClient.doesServerSupportSeparateAddAndBind()) {
// For separate bind, request a token directly from the IS.
const authClient = new IdentityAuthClient();
const identityAccessToken = (await authClient.getAccessToken()) ?? undefined;
try {
const res = await MatrixClientPeg.get().requestMsisdnToken(
const res = await this.matrixClient.requestMsisdnToken(
phoneCountry,
phoneNumber,
this.clientSecret,
@ -189,17 +188,17 @@ export default class AddThreepid {
*/
public async checkEmailLinkClicked(): Promise<[success?: boolean, result?: IAuthData | Error | null]> {
try {
if (await MatrixClientPeg.get().doesServerSupportSeparateAddAndBind()) {
if (await this.matrixClient.doesServerSupportSeparateAddAndBind()) {
if (this.bind) {
const authClient = new IdentityAuthClient();
const identityAccessToken = await authClient.getAccessToken();
if (!identityAccessToken) {
throw new UserFriendlyError("No identity access token found");
}
await MatrixClientPeg.get().bindThreePid({
await this.matrixClient.bindThreePid({
sid: this.sessionId,
client_secret: this.clientSecret,
id_server: getIdServerDomain(),
id_server: getIdServerDomain(this.matrixClient),
id_access_token: identityAccessToken,
});
} else {
@ -233,7 +232,7 @@ export default class AddThreepid {
};
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
title: _t("Add Email Address"),
matrixClient: MatrixClientPeg.get(),
matrixClient: this.matrixClient,
authData: err.data,
makeRequest: this.makeAddThreepidOnlyRequest,
aestheticsForStagePhases: {
@ -245,11 +244,11 @@ export default class AddThreepid {
}
}
} else {
await MatrixClientPeg.get().addThreePid(
await this.matrixClient.addThreePid(
{
sid: this.sessionId,
client_secret: this.clientSecret,
id_server: getIdServerDomain(),
id_server: getIdServerDomain(this.matrixClient),
},
this.bind,
);
@ -272,7 +271,7 @@ export default class AddThreepid {
* @return {Promise<Object>} Response from /3pid/add call (in current spec, an empty object)
*/
private makeAddThreepidOnlyRequest = (auth?: { type: string; session?: string }): Promise<{}> => {
return MatrixClientPeg.get().addThreePidOnly({
return this.matrixClient.addThreePidOnly({
sid: this.sessionId,
client_secret: this.clientSecret,
auth,
@ -291,18 +290,18 @@ export default class AddThreepid {
msisdnToken: string,
): Promise<[success?: boolean, result?: IAuthData | Error | null] | undefined> {
const authClient = new IdentityAuthClient();
const supportsSeparateAddAndBind = await MatrixClientPeg.get().doesServerSupportSeparateAddAndBind();
const supportsSeparateAddAndBind = await this.matrixClient.doesServerSupportSeparateAddAndBind();
let result: { success: boolean } | MatrixError;
if (this.submitUrl) {
result = await MatrixClientPeg.get().submitMsisdnTokenOtherUrl(
result = await this.matrixClient.submitMsisdnTokenOtherUrl(
this.submitUrl,
this.sessionId,
this.clientSecret,
msisdnToken,
);
} else if (this.bind || !supportsSeparateAddAndBind) {
result = await MatrixClientPeg.get().submitMsisdnToken(
result = await this.matrixClient.submitMsisdnToken(
this.sessionId,
this.clientSecret,
msisdnToken,
@ -317,10 +316,10 @@ export default class AddThreepid {
if (supportsSeparateAddAndBind) {
if (this.bind) {
await MatrixClientPeg.get().bindThreePid({
await this.matrixClient.bindThreePid({
sid: this.sessionId,
client_secret: this.clientSecret,
id_server: getIdServerDomain(),
id_server: getIdServerDomain(this.matrixClient),
id_access_token: await authClient.getAccessToken(),
});
} else {
@ -354,7 +353,7 @@ export default class AddThreepid {
};
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
title: _t("Add Phone Number"),
matrixClient: MatrixClientPeg.get(),
matrixClient: this.matrixClient,
authData: err.data,
makeRequest: this.makeAddThreepidOnlyRequest,
aestheticsForStagePhases: {
@ -366,11 +365,11 @@ export default class AddThreepid {
}
}
} else {
await MatrixClientPeg.get().addThreePid(
await this.matrixClient.addThreePid(
{
sid: this.sessionId,
client_secret: this.clientSecret,
id_server: getIdServerDomain(),
id_server: getIdServerDomain(this.matrixClient),
},
this.bind,
);

View file

@ -17,8 +17,8 @@ limitations under the License.
import { MatrixEvent, EventStatus } from "matrix-js-sdk/src/models/event";
import { Room } from "matrix-js-sdk/src/models/room";
import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "./MatrixClientPeg";
import dis from "./dispatcher/dispatcher";
export default class Resend {
@ -30,7 +30,7 @@ export default class Resend {
return ev.status === EventStatus.NOT_SENT;
})
.map(function (event: MatrixEvent) {
return Resend.resend(event);
return Resend.resend(room.client, event);
}),
);
}
@ -41,30 +41,28 @@ export default class Resend {
return ev.status === EventStatus.NOT_SENT;
})
.forEach(function (event: MatrixEvent) {
Resend.removeFromQueue(event);
Resend.removeFromQueue(room.client, event);
});
}
public static resend(event: MatrixEvent): Promise<void> {
const room = MatrixClientPeg.get().getRoom(event.getRoomId())!;
return MatrixClientPeg.get()
.resendEvent(event, room)
.then(
function (res) {
dis.dispatch({
action: "message_sent",
event: event,
});
},
function (err: Error) {
// XXX: temporary logging to try to diagnose
// https://github.com/vector-im/element-web/issues/3148
logger.log("Resend got send failure: " + err.name + "(" + err + ")");
},
);
public static resend(client: MatrixClient, event: MatrixEvent): Promise<void> {
const room = client.getRoom(event.getRoomId())!;
return client.resendEvent(event, room).then(
function (res) {
dis.dispatch({
action: "message_sent",
event: event,
});
},
function (err: Error) {
// XXX: temporary logging to try to diagnose
// https://github.com/vector-im/element-web/issues/3148
logger.log("Resend got send failure: " + err.name + "(" + err + ")");
},
);
}
public static removeFromQueue(event: MatrixEvent): void {
MatrixClientPeg.get().cancelPendingEvent(event);
public static removeFromQueue(client: MatrixClient, event: MatrixEvent): void {
client.cancelPendingEvent(event);
}
}

View file

@ -22,7 +22,6 @@ import { logger } from "matrix-js-sdk/src/logger";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "./MatrixClientPeg";
import MultiInviter, { CompletionStates } from "./utils/MultiInviter";
import Modal from "./Modal";
import { _t } from "./languageHandler";
@ -115,7 +114,7 @@ export function inviteUsersToRoom(
): Promise<void> {
return inviteMultipleToRoom(client, roomId, userIds, sendSharedHistoryKeys, progressCallback)
.then((result) => {
const room = MatrixClientPeg.get().getRoom(roomId)!;
const room = client.getRoom(roomId)!;
showAnyInviteErrors(result.states, room, result.inviter);
})
.catch((err) => {
@ -153,7 +152,7 @@ export function showAnyInviteErrors(
}
}
const cli = MatrixClientPeg.get();
const cli = room.client;
if (errorList.length > 0) {
// React 16 doesn't let us use `errorList.join(<br />)` anymore, so this is our solution
const description = (

View file

@ -46,7 +46,7 @@ export function getDisplayAliasForAliasSet(canonicalAlias: string | null, altAli
export function guessAndSetDMRoom(room: Room, isDirect: boolean): Promise<void> {
let newTarget;
if (isDirect) {
const guessedUserId = guessDMRoomTargetId(room, MatrixClientPeg.get().getUserId()!);
const guessedUserId = guessDMRoomTargetId(room, room.client.getSafeUserId());
newTarget = guessedUserId;
} else {
newTarget = null;

View file

@ -25,20 +25,19 @@ import {
import { IRoomEventFilter } from "matrix-js-sdk/src/filter";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { SearchResult } from "matrix-js-sdk/src/models/search-result";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { ISearchArgs } from "./indexing/BaseEventIndexManager";
import EventIndexPeg from "./indexing/EventIndexPeg";
import { MatrixClientPeg } from "./MatrixClientPeg";
const SEARCH_LIMIT = 10;
async function serverSideSearch(
client: MatrixClient,
term: string,
roomId?: string,
abortSignal?: AbortSignal,
): Promise<{ response: ISearchResponse; query: ISearchRequestBody }> {
const client = MatrixClientPeg.get();
const filter: IRoomEventFilter = {
limit: SEARCH_LIMIT,
};
@ -66,12 +65,12 @@ async function serverSideSearch(
}
async function serverSideSearchProcess(
client: MatrixClient,
term: string,
roomId?: string,
abortSignal?: AbortSignal,
): Promise<ISearchResults> {
const client = MatrixClientPeg.get();
const result = await serverSideSearch(term, roomId, abortSignal);
const result = await serverSideSearch(client, term, roomId, abortSignal);
// The js-sdk method backPaginateRoomEventsSearch() uses _query internally
// so we're reusing the concept here since we want to delegate the
@ -96,12 +95,14 @@ function compareEvents(a: ISearchResult, b: ISearchResult): number {
return 0;
}
async function combinedSearch(searchTerm: string, abortSignal?: AbortSignal): Promise<ISearchResults> {
const client = MatrixClientPeg.get();
async function combinedSearch(
client: MatrixClient,
searchTerm: string,
abortSignal?: AbortSignal,
): Promise<ISearchResults> {
// Create two promises, one for the local search, one for the
// server-side search.
const serverSidePromise = serverSideSearch(searchTerm, undefined, abortSignal);
const serverSidePromise = serverSideSearch(client, searchTerm, undefined, abortSignal);
const localPromise = localSearch(searchTerm);
// Wait for both promises to resolve.
@ -198,7 +199,11 @@ export interface ISeshatSearchResults extends ISearchResults {
serverSideNextBatch?: string;
}
async function localSearchProcess(searchTerm: string, roomId?: string): Promise<ISeshatSearchResults> {
async function localSearchProcess(
client: MatrixClient,
searchTerm: string,
roomId?: string,
): Promise<ISeshatSearchResults> {
const emptyResult = {
results: [],
highlights: [],
@ -216,14 +221,17 @@ async function localSearchProcess(searchTerm: string, roomId?: string): Promise<
},
};
const processedResult = MatrixClientPeg.get().processRoomEventsSearch(emptyResult, response);
const processedResult = client.processRoomEventsSearch(emptyResult, response);
// Restore our encryption info so we can properly re-verify the events.
restoreEncryptionInfo(processedResult.results);
return processedResult;
}
async function localPagination(searchResult: ISeshatSearchResults): Promise<ISeshatSearchResults> {
async function localPagination(
client: MatrixClient,
searchResult: ISeshatSearchResults,
): Promise<ISeshatSearchResults> {
const eventIndex = EventIndexPeg.get();
const searchArgs = searchResult.seshatQuery;
@ -245,7 +253,7 @@ async function localPagination(searchResult: ISeshatSearchResults): Promise<ISes
},
};
const result = MatrixClientPeg.get().processRoomEventsSearch(searchResult, response);
const result = client.processRoomEventsSearch(searchResult, response);
// Restore our encryption info so we can properly re-verify the events.
const newSlice = result.results.slice(Math.max(result.results.length - newResultCount, 0));
@ -535,9 +543,11 @@ function restoreEncryptionInfo(searchResultSlice: SearchResult[] = []): void {
}
}
async function combinedPagination(searchResult: ISeshatSearchResults): Promise<ISeshatSearchResults> {
async function combinedPagination(
client: MatrixClient,
searchResult: ISeshatSearchResults,
): Promise<ISeshatSearchResults> {
const eventIndex = EventIndexPeg.get();
const client = MatrixClientPeg.get();
const searchArgs = searchResult.seshatQuery;
const oldestEventFrom = searchResult.oldestEventFrom;
@ -588,31 +598,37 @@ async function combinedPagination(searchResult: ISeshatSearchResults): Promise<I
return result;
}
function eventIndexSearch(term: string, roomId?: string, abortSignal?: AbortSignal): Promise<ISearchResults> {
function eventIndexSearch(
client: MatrixClient,
term: string,
roomId?: string,
abortSignal?: AbortSignal,
): Promise<ISearchResults> {
let searchPromise: Promise<ISearchResults>;
if (roomId !== undefined) {
if (MatrixClientPeg.get().isRoomEncrypted(roomId)) {
if (client.isRoomEncrypted(roomId)) {
// The search is for a single encrypted room, use our local
// search method.
searchPromise = localSearchProcess(term, roomId);
searchPromise = localSearchProcess(client, term, roomId);
} else {
// The search is for a single non-encrypted room, use the
// server-side search.
searchPromise = serverSideSearchProcess(term, roomId, abortSignal);
searchPromise = serverSideSearchProcess(client, term, roomId, abortSignal);
}
} else {
// Search across all rooms, combine a server side search and a
// local search.
searchPromise = combinedSearch(term, abortSignal);
searchPromise = combinedSearch(client, term, abortSignal);
}
return searchPromise;
}
function eventIndexSearchPagination(searchResult: ISeshatSearchResults): Promise<ISeshatSearchResults> {
const client = MatrixClientPeg.get();
function eventIndexSearchPagination(
client: MatrixClient,
searchResult: ISeshatSearchResults,
): Promise<ISeshatSearchResults> {
const seshatQuery = searchResult.seshatQuery;
const serverQuery = searchResult._query;
@ -622,36 +638,40 @@ function eventIndexSearchPagination(searchResult: ISeshatSearchResults): Promise
return client.backPaginateRoomEventsSearch(searchResult);
} else if (!serverQuery) {
// This is a search in a encrypted room. Do a local pagination.
const promise = localPagination(searchResult);
const promise = localPagination(client, searchResult);
searchResult.pendingRequest = promise;
return promise;
} else {
// We have both queries around, this is a search across all rooms so a
// combined pagination needs to be done.
const promise = combinedPagination(searchResult);
const promise = combinedPagination(client, searchResult);
searchResult.pendingRequest = promise;
return promise;
}
}
export function searchPagination(searchResult: ISearchResults): Promise<ISearchResults> {
export function searchPagination(client: MatrixClient, searchResult: ISearchResults): Promise<ISearchResults> {
const eventIndex = EventIndexPeg.get();
const client = MatrixClientPeg.get();
if (searchResult.pendingRequest) return searchResult.pendingRequest;
if (eventIndex === null) return client.backPaginateRoomEventsSearch(searchResult);
else return eventIndexSearchPagination(searchResult);
else return eventIndexSearchPagination(client, searchResult);
}
export default function eventSearch(term: string, roomId?: string, abortSignal?: AbortSignal): Promise<ISearchResults> {
export default function eventSearch(
client: MatrixClient,
term: string,
roomId?: string,
abortSignal?: AbortSignal,
): Promise<ISearchResults> {
const eventIndex = EventIndexPeg.get();
if (eventIndex === null) {
return serverSideSearchProcess(term, roomId, abortSignal);
return serverSideSearchProcess(client, term, roomId, abortSignal);
} else {
return eventIndexSearch(term, roomId, abortSignal);
return eventIndexSearch(client, term, roomId, abortSignal);
}
}

View file

@ -20,8 +20,8 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { M_BEACON } from "matrix-js-sdk/src/@types/beacon";
import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "./MatrixClientPeg";
import shouldHideEvent from "./shouldHideEvent";
import { haveRendererForEvent } from "./events/EventTileFactory";
import SettingsStore from "./settings/SettingsStore";
@ -30,11 +30,12 @@ import SettingsStore from "./settings/SettingsStore";
* Returns true if this event arriving in a room should affect the room's
* count of unread messages
*
* @param client The Matrix Client instance of the logged-in user
* @param {Object} ev The event
* @returns {boolean} True if the given event should affect the unread message count
*/
export function eventTriggersUnreadCount(ev: MatrixEvent): boolean {
if (ev.getSender() === MatrixClientPeg.get().credentials.userId) {
export function eventTriggersUnreadCount(client: MatrixClient, ev: MatrixEvent): boolean {
if (ev.getSender() === client.getSafeUserId()) {
return false;
}
@ -83,7 +84,7 @@ export function doesRoomOrThreadHaveUnreadMessages(roomOrThread: Room | Thread):
return false;
}
const myUserId = MatrixClientPeg.get().getUserId()!;
const myUserId = roomOrThread.client.getSafeUserId();
// as we don't send RRs for our own messages, make sure we special case that
// if *we* sent the last message into the room, we consider it not unread!
@ -107,7 +108,7 @@ export function doesRoomOrThreadHaveUnreadMessages(roomOrThread: Room | Thread):
// that counts and we can stop looking because the user's read
// this and everything before.
return false;
} else if (isImportantEvent(ev)) {
} else if (isImportantEvent(roomOrThread.client, ev)) {
// We've found a message that counts before we hit
// the user's read receipt, so this room is definitely unread.
return true;
@ -129,8 +130,8 @@ export function doesRoomOrThreadHaveUnreadMessages(roomOrThread: Room | Thread):
* Given this event does not have a receipt, is it important enough to make
* this room unread?
*/
function isImportantEvent(event: MatrixEvent): boolean {
return !shouldHideEvent(event) && eventTriggersUnreadCount(event);
function isImportantEvent(client: MatrixClient, event: MatrixEvent): boolean {
return !shouldHideEvent(event) && eventTriggersUnreadCount(client, event);
}
/**

View file

@ -17,15 +17,14 @@ limitations under the License.
import { Room } from "matrix-js-sdk/src/models/room";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { MatrixClientPeg } from "./MatrixClientPeg";
import { _t } from "./languageHandler";
export function usersTypingApartFromMeAndIgnored(room: Room): RoomMember[] {
return usersTyping(room, [MatrixClientPeg.get().getUserId()!].concat(MatrixClientPeg.get().getIgnoredUsers()));
return usersTyping(room, [room.client.getSafeUserId()].concat(room.client.getIgnoredUsers()));
}
export function usersTypingApartFromMe(room: Room): RoomMember[] {
return usersTyping(room, [MatrixClientPeg.get().getUserId()!]);
return usersTyping(room, [room.client.getSafeUserId()]);
}
/**

View file

@ -625,7 +625,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.notifyNewScreen("forgot_password");
break;
case "start_chat":
createRoom({
createRoom(MatrixClientPeg.get(), {
dmUserId: payload.user_id,
});
break;
@ -1062,7 +1062,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
const [shouldCreate, opts] = await modal.finished;
if (shouldCreate) {
createRoom(opts!);
createRoom(MatrixClientPeg.get(), opts!);
}
}
@ -1246,7 +1246,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
const welcomeUserRooms = DMRoomMap.shared().getDMRoomsForUserId(welcomeUserId);
if (welcomeUserRooms.length === 0) {
const roomId = await createRoom({
const roomId = await createRoom(MatrixClientPeg.get(), {
dmUserId: snakedConfig.get("welcome_user_id"),
// Only view the welcome user if we're NOT looking at a room
andView: !this.state.currentRoomId,

View file

@ -181,7 +181,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(
}
debuglog("requesting more search results");
const searchPromise = searchPagination(results);
const searchPromise = searchPagination(client, results);
return handleSearchResult(searchPromise);
};

View file

@ -1621,7 +1621,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
const roomId = scope === SearchScope.Room ? this.getRoomId() : undefined;
debuglog("sending search request");
const abortController = new AbortController();
const promise = eventSearch(term, roomId, abortController.signal);
const promise = eventSearch(this.context.client!, term, roomId, abortController.signal);
this.setState({
search: {

View file

@ -336,7 +336,7 @@ const SpaceSetupFirstRooms: React.FC<{
const filteredRoomNames = roomNames.map((name) => name.trim()).filter(Boolean);
const roomIds = await Promise.all(
filteredRoomNames.map((name) => {
return createRoom({
return createRoom(space.client, {
createOpts: {
preset: isPublic ? Preset.PublicChat : Preset.PrivateChat,
name,

View file

@ -201,7 +201,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
private onResendReactionsClick = (): void => {
for (const reaction of this.getUnsentReactions()) {
Resend.resend(reaction);
Resend.resend(MatrixClientPeg.get(), reaction);
}
this.closeMenu();
};

View file

@ -79,7 +79,16 @@ const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick
}
try {
await createSpace(name, joinRule === JoinRule.Public, alias, topic, avatar, {}, { parentSpace, joinRule });
await createSpace(
space.client,
name,
joinRule === JoinRule.Public,
alias,
topic,
avatar,
{},
{ parentSpace, joinRule },
);
onFinished(true);
} catch (e) {

View file

@ -28,6 +28,7 @@ import ErrorDialog, { extractErrorMessageFromError } from "./ErrorDialog";
import QuestionDialog from "./QuestionDialog";
import BaseDialog from "./BaseDialog";
import EditableText from "../elements/EditableText";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
interface IProps {
title: string;
@ -71,7 +72,7 @@ export default class SetEmailDialog extends React.Component<IProps, IState> {
});
return;
}
this.addThreepid = new AddThreepid();
this.addThreepid = new AddThreepid(MatrixClientPeg.get());
this.addThreepid.addEmailAddress(emailAddress).then(
() => {
Modal.createDialog(QuestionDialog, {

View file

@ -417,12 +417,12 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
ev.preventDefault();
ev.stopPropagation();
this.runActionOnFailedEv((tarEv) => Resend.resend(tarEv));
this.runActionOnFailedEv((tarEv) => Resend.resend(MatrixClientPeg.get(), tarEv));
};
private onCancelClick = (ev: ButtonEvent): void => {
this.runActionOnFailedEv(
(tarEv) => Resend.removeFromQueue(tarEv),
(tarEv) => Resend.removeFromQueue(MatrixClientPeg.get(), tarEv),
(testEv) => canCancel(testEv.status),
);
};

View file

@ -181,7 +181,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
return;
}
const task = new AddThreepid();
const task = new AddThreepid(MatrixClientPeg.get());
this.setState({ verifying: true, continueDisabled: true, addTask: task });
task.addEmailAddress(email)

View file

@ -182,7 +182,7 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
const phoneNumber = this.state.newPhoneNumber;
const phoneCountry = this.state.phoneCountry;
const task = new AddThreepid();
const task = new AddThreepid(MatrixClientPeg.get());
this.setState({ verifying: true, continueDisabled: true, addTask: task });
task.addMsisdn(phoneCountry, phoneNumber)

View file

@ -86,7 +86,7 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
try {
if (bind) {
const task = new AddThreepid();
const task = new AddThreepid(MatrixClientPeg.get());
this.setState({
verifying: true,
continueDisabled: true,
@ -117,7 +117,7 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
private async changeBindingTangledAddBind({ bind, label, errorTitle }: Binding): Promise<void> {
const { medium, address } = this.props.email;
const task = new AddThreepid();
const task = new AddThreepid(MatrixClientPeg.get());
this.setState({
verifying: true,
continueDisabled: true,

View file

@ -82,7 +82,7 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
try {
if (bind) {
const task = new AddThreepid();
const task = new AddThreepid(MatrixClientPeg.get());
this.setState({
verifying: true,
continueDisabled: true,
@ -118,7 +118,7 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
private async changeBindingTangledAddBind({ bind, label, errorTitle }: Binding): Promise<void> {
const { medium, address } = this.props.msisdn;
const task = new AddThreepid();
const task = new AddThreepid(MatrixClientPeg.get());
this.setState({
verifying: true,
continueDisabled: true,

View file

@ -215,7 +215,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
const [shouldCreate, opts] = await modal.finished;
if (shouldCreate) {
await createRoom(opts);
await createRoom(this.context, opts);
}
return shouldCreate;
};

View file

@ -35,6 +35,7 @@ import SettingsTab from "../SettingsTab";
import { SettingsSection } from "../../shared/SettingsSection";
import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection";
import ExternalLink from "../../../elements/ExternalLink";
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
interface IProps {
closeSettingsFn: () => void;
@ -46,6 +47,9 @@ interface IState {
}
export default class HelpUserSettingsTab extends React.Component<IProps, IState> {
public static contextType = MatrixClientContext;
public context!: React.ContextType<typeof MatrixClientContext>;
public constructor(props: IProps) {
super(props);
@ -104,7 +108,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
private onStartBotChat = (): void => {
this.props.closeSettingsFn();
createRoom({
createRoom(this.context, {
dmUserId: SdkConfig.get("welcome_user_id"),
andView: true,
});

View file

@ -30,12 +30,13 @@ import { RoomType } from "matrix-js-sdk/src/@types/event";
import { ICreateRoomOpts } from "matrix-js-sdk/src/@types/requests";
import { HistoryVisibility, Preset, Visibility } from "matrix-js-sdk/src/@types/partials";
import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { _t } from "../../../languageHandler";
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import ContextMenu, { ChevronFace } from "../../structures/ContextMenu";
import createRoom, { IOpts as ICreateOpts } from "../../../createRoom";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import MatrixClientContext, { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
import SpaceBasicSettings, { SpaceAvatar } from "./SpaceBasicSettings";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import Field from "../elements/Field";
@ -43,8 +44,9 @@ import withValidation from "../elements/Validation";
import RoomAliasField from "../elements/RoomAliasField";
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
export const createSpace = async (
client: MatrixClient,
name: string,
isPublic: boolean,
alias?: string,
@ -53,12 +55,12 @@ export const createSpace = async (
createOpts: Partial<ICreateRoomOpts> = {},
otherOpts: Partial<Omit<ICreateOpts, "createOpts">> = {},
): Promise<string | null> => {
return createRoom({
return createRoom(client, {
createOpts: {
name,
preset: isPublic ? Preset.PublicChat : Preset.PrivateChat,
visibility:
isPublic && (await MatrixClientPeg.get().doesServerSupportUnstableFeature("org.matrix.msc3827.stable"))
isPublic && (await client.doesServerSupportUnstableFeature("org.matrix.msc3827.stable"))
? Visibility.Public
: Visibility.Private,
power_level_content_override: {
@ -208,6 +210,7 @@ export const SpaceCreateForm: React.FC<ISpaceCreateFormProps> = ({
const SpaceCreateMenu: React.FC<{
onFinished(): void;
}> = ({ onFinished }) => {
const cli = useMatrixClientContext();
const [visibility, setVisibility] = useState<Visibility | null>(null);
const [busy, setBusy] = useState<boolean>(false);
@ -243,7 +246,7 @@ const SpaceCreateMenu: React.FC<{
}
try {
await createSpace(name, visibility === Visibility.Public, alias, topic, avatar);
await createSpace(cli, name, visibility === Visibility.Public, alias, topic, avatar);
onFinished();
} catch (e) {

View file

@ -28,7 +28,6 @@ import {
} from "matrix-js-sdk/src/@types/partials";
import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClientPeg } from "./MatrixClientPeg";
import Modal, { IHandle } from "./Modal";
import { _t, UserFriendlyError } from "./languageHandler";
import dis from "./dispatcher/dispatcher";
@ -82,6 +81,7 @@ const DEFAULT_EVENT_POWER_LEVELS = {
/**
* Create a new room, and switch to it.
*
* @param client The Matrix Client instance to create the room with
* @param {object=} opts parameters for creating the room
* @param {string=} opts.dmUserId If specified, make this a DM room for this user and invite them
* @param {object=} opts.createOpts set of options to pass to createRoom call.
@ -98,13 +98,12 @@ const DEFAULT_EVENT_POWER_LEVELS = {
* @returns {Promise} which resolves to the room id, or null if the
* action was aborted or failed.
*/
export default async function createRoom(opts: IOpts): Promise<string | null> {
export default async function createRoom(client: MatrixClient, opts: IOpts): Promise<string | null> {
opts = opts || {};
if (opts.spinner === undefined) opts.spinner = true;
if (opts.guestAccess === undefined) opts.guestAccess = true;
if (opts.encryption === undefined) opts.encryption = false;
const client = MatrixClientPeg.get();
if (client.isGuest()) {
dis.dispatch({ action: "require_registration" });
return null;
@ -122,7 +121,7 @@ export default async function createRoom(opts: IOpts): Promise<string | null> {
createOpts.invite = [opts.dmUserId];
break;
case "email": {
const isUrl = MatrixClientPeg.get().getIdentityServerUrl(true);
const isUrl = client.getIdentityServerUrl(true);
if (!isUrl) {
throw new UserFriendlyError(
"Cannot invite user by email without an identity server. " +
@ -162,7 +161,7 @@ export default async function createRoom(opts: IOpts): Promise<string | null> {
},
users: {
// Temporarily give ourselves the power to set up a widget
[client.getUserId()!]: 200,
[client.getSafeUserId()]: 200,
},
};
} else if (opts.roomType === RoomType.UnstableCall) {
@ -176,7 +175,7 @@ export default async function createRoom(opts: IOpts): Promise<string | null> {
},
users: {
// Temporarily give ourselves the power to set up a call
[client.getUserId()!]: 200,
[client.getSafeUserId()]: 200,
},
};
}
@ -438,7 +437,7 @@ export async function ensureVirtualRoomExists(
if (existingDMRoom) {
roomId = existingDMRoom.roomId;
} else {
roomId = await createRoom({
roomId = await createRoom(client, {
dmUserId: userId,
spinner: false,
andView: false,
@ -466,7 +465,7 @@ export async function ensureDMExists(client: MatrixClient, userId: string): Prom
encryption = await canEncryptToAllUsers(client, [userId]);
}
roomId = await createRoom({ encryption, dmUserId: userId, spinner: false, andView: false });
roomId = await createRoom(client, { encryption, dmUserId: userId, spinner: false, andView: false });
if (!roomId) return null;
await waitForMember(client, roomId, userId);
}

View file

@ -95,7 +95,10 @@ const getLastTs = (r: Room, userId: string): number => {
const ev = r.timeline[i];
if (!ev.getTs()) continue; // skip events that don't have timestamps (tests only?)
if ((ev.getSender() === userId && shouldCauseReorder(ev)) || Unread.eventTriggersUnreadCount(ev)) {
if (
(ev.getSender() === userId && shouldCauseReorder(ev)) ||
Unread.eventTriggersUnreadCount(r.client, ev)
) {
return ev.getTs();
}
}

View file

@ -90,5 +90,5 @@ export async function startDm(client: MatrixClient, targets: Member[], showSpinn
}
createRoomOptions.spinner = showSpinner;
return createRoom(createRoomOptions);
return createRoom(client, createRoomOptions);
}

View file

@ -82,7 +82,7 @@ export const showCreateNewRoom = async (space: Room, type?: RoomType): Promise<b
});
const [shouldCreate, opts] = await modal.finished;
if (shouldCreate) {
await createRoom(opts);
await createRoom(space.client, opts);
}
return !!shouldCreate;
};

View file

@ -67,32 +67,32 @@ describe("Unread", () => {
});
it("returns false when the event was sent by the current user", () => {
expect(eventTriggersUnreadCount(ourMessage)).toBe(false);
expect(eventTriggersUnreadCount(client, ourMessage)).toBe(false);
// returned early before checking renderer
expect(haveRendererForEvent).not.toHaveBeenCalled();
});
it("returns false for a redacted event", () => {
expect(eventTriggersUnreadCount(redactedEvent)).toBe(false);
expect(eventTriggersUnreadCount(client, redactedEvent)).toBe(false);
// returned early before checking renderer
expect(haveRendererForEvent).not.toHaveBeenCalled();
});
it("returns false for an event without a renderer", () => {
mocked(haveRendererForEvent).mockReturnValue(false);
expect(eventTriggersUnreadCount(alicesMessage)).toBe(false);
expect(eventTriggersUnreadCount(client, alicesMessage)).toBe(false);
expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, false);
});
it("returns true for an event with a renderer", () => {
mocked(haveRendererForEvent).mockReturnValue(true);
expect(eventTriggersUnreadCount(alicesMessage)).toBe(true);
expect(eventTriggersUnreadCount(client, alicesMessage)).toBe(true);
expect(haveRendererForEvent).toHaveBeenCalledWith(alicesMessage, false);
});
it("returns false for beacon locations", () => {
const beaconLocationEvent = makeBeaconEvent(aliceId);
expect(eventTriggersUnreadCount(beaconLocationEvent)).toBe(false);
expect(eventTriggersUnreadCount(client, beaconLocationEvent)).toBe(false);
expect(haveRendererForEvent).not.toHaveBeenCalled();
});
@ -112,7 +112,7 @@ describe("Unread", () => {
type: eventType,
sender: aliceId,
});
expect(eventTriggersUnreadCount(event)).toBe(false);
expect(eventTriggersUnreadCount(client, event)).toBe(false);
expect(haveRendererForEvent).not.toHaveBeenCalled();
},
);

View file

@ -43,7 +43,7 @@ describe("createRoom", () => {
const createCallSpy = jest.spyOn(JitsiCall, "create");
const userId = client.getUserId()!;
const roomId = await createRoom({ roomType: RoomType.ElementVideo });
const roomId = await createRoom(client, { roomType: RoomType.ElementVideo });
const [
[
@ -75,7 +75,7 @@ describe("createRoom", () => {
it("sets up Element video rooms correctly", async () => {
const userId = client.getUserId()!;
const createCallSpy = jest.spyOn(ElementCall, "create");
const roomId = await createRoom({ roomType: RoomType.UnstableCall });
const roomId = await createRoom(client, { roomType: RoomType.UnstableCall });
const userPower = client.createRoom.mock.calls[0][0].power_level_content_override?.users?.[userId];
const callPower =
@ -102,7 +102,7 @@ describe("createRoom", () => {
const createJitsiCallSpy = jest.spyOn(JitsiCall, "create");
const createElementCallSpy = jest.spyOn(ElementCall, "create");
await createRoom({});
await createRoom(client, {});
expect(createJitsiCallSpy).not.toHaveBeenCalled();
expect(createElementCallSpy).not.toHaveBeenCalled();
@ -113,7 +113,7 @@ describe("createRoom", () => {
if (name === "feature_group_calls") return true;
});
await createRoom({});
await createRoom(client, {});
const callPower =
client.createRoom.mock.calls[0][0].power_level_content_override?.events?.[ElementCall.CALL_EVENT_TYPE.name];
@ -129,7 +129,7 @@ describe("createRoom", () => {
it("should upload avatar if one is passed", async () => {
client.uploadContent.mockResolvedValue({ content_uri: "mxc://foobar" });
const avatar = new File([], "avatar.png");
await createRoom({ avatar });
await createRoom(client, { avatar });
expect(client.createRoom).toHaveBeenCalledWith(
expect.objectContaining({
initial_state: expect.arrayContaining([