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

View file

@ -17,8 +17,8 @@ limitations under the License.
import { MatrixEvent, EventStatus } from "matrix-js-sdk/src/models/event"; import { MatrixEvent, EventStatus } 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 { logger } from "matrix-js-sdk/src/logger"; 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"; import dis from "./dispatcher/dispatcher";
export default class Resend { export default class Resend {
@ -30,7 +30,7 @@ export default class Resend {
return ev.status === EventStatus.NOT_SENT; return ev.status === EventStatus.NOT_SENT;
}) })
.map(function (event: MatrixEvent) { .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; return ev.status === EventStatus.NOT_SENT;
}) })
.forEach(function (event: MatrixEvent) { .forEach(function (event: MatrixEvent) {
Resend.removeFromQueue(event); Resend.removeFromQueue(room.client, event);
}); });
} }
public static resend(event: MatrixEvent): Promise<void> { public static resend(client: MatrixClient, event: MatrixEvent): Promise<void> {
const room = MatrixClientPeg.get().getRoom(event.getRoomId())!; const room = client.getRoom(event.getRoomId())!;
return MatrixClientPeg.get() return client.resendEvent(event, room).then(
.resendEvent(event, room) function (res) {
.then( dis.dispatch({
function (res) { action: "message_sent",
dis.dispatch({ event: event,
action: "message_sent", });
event: event, },
}); function (err: Error) {
}, // XXX: temporary logging to try to diagnose
function (err: Error) { // https://github.com/vector-im/element-web/issues/3148
// XXX: temporary logging to try to diagnose logger.log("Resend got send failure: " + err.name + "(" + err + ")");
// https://github.com/vector-im/element-web/issues/3148 },
logger.log("Resend got send failure: " + err.name + "(" + err + ")"); );
},
);
} }
public static removeFromQueue(event: MatrixEvent): void { public static removeFromQueue(client: MatrixClient, event: MatrixEvent): void {
MatrixClientPeg.get().cancelPendingEvent(event); 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 { EventType } from "matrix-js-sdk/src/@types/event";
import { MatrixClient } from "matrix-js-sdk/src/matrix"; import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "./MatrixClientPeg";
import MultiInviter, { CompletionStates } from "./utils/MultiInviter"; import MultiInviter, { CompletionStates } from "./utils/MultiInviter";
import Modal from "./Modal"; import Modal from "./Modal";
import { _t } from "./languageHandler"; import { _t } from "./languageHandler";
@ -115,7 +114,7 @@ export function inviteUsersToRoom(
): Promise<void> { ): Promise<void> {
return inviteMultipleToRoom(client, roomId, userIds, sendSharedHistoryKeys, progressCallback) return inviteMultipleToRoom(client, roomId, userIds, sendSharedHistoryKeys, progressCallback)
.then((result) => { .then((result) => {
const room = MatrixClientPeg.get().getRoom(roomId)!; const room = client.getRoom(roomId)!;
showAnyInviteErrors(result.states, room, result.inviter); showAnyInviteErrors(result.states, room, result.inviter);
}) })
.catch((err) => { .catch((err) => {
@ -153,7 +152,7 @@ export function showAnyInviteErrors(
} }
} }
const cli = MatrixClientPeg.get(); const cli = room.client;
if (errorList.length > 0) { if (errorList.length > 0) {
// React 16 doesn't let us use `errorList.join(<br />)` anymore, so this is our solution // React 16 doesn't let us use `errorList.join(<br />)` anymore, so this is our solution
const description = ( const description = (

View file

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

View file

@ -25,20 +25,19 @@ import {
import { IRoomEventFilter } from "matrix-js-sdk/src/filter"; import { IRoomEventFilter } from "matrix-js-sdk/src/filter";
import { EventType } from "matrix-js-sdk/src/@types/event"; import { EventType } from "matrix-js-sdk/src/@types/event";
import { SearchResult } from "matrix-js-sdk/src/models/search-result"; import { SearchResult } from "matrix-js-sdk/src/models/search-result";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { ISearchArgs } from "./indexing/BaseEventIndexManager"; import { ISearchArgs } from "./indexing/BaseEventIndexManager";
import EventIndexPeg from "./indexing/EventIndexPeg"; import EventIndexPeg from "./indexing/EventIndexPeg";
import { MatrixClientPeg } from "./MatrixClientPeg";
const SEARCH_LIMIT = 10; const SEARCH_LIMIT = 10;
async function serverSideSearch( async function serverSideSearch(
client: MatrixClient,
term: string, term: string,
roomId?: string, roomId?: string,
abortSignal?: AbortSignal, abortSignal?: AbortSignal,
): Promise<{ response: ISearchResponse; query: ISearchRequestBody }> { ): Promise<{ response: ISearchResponse; query: ISearchRequestBody }> {
const client = MatrixClientPeg.get();
const filter: IRoomEventFilter = { const filter: IRoomEventFilter = {
limit: SEARCH_LIMIT, limit: SEARCH_LIMIT,
}; };
@ -66,12 +65,12 @@ async function serverSideSearch(
} }
async function serverSideSearchProcess( async function serverSideSearchProcess(
client: MatrixClient,
term: string, term: string,
roomId?: string, roomId?: string,
abortSignal?: AbortSignal, abortSignal?: AbortSignal,
): Promise<ISearchResults> { ): Promise<ISearchResults> {
const client = MatrixClientPeg.get(); const result = await serverSideSearch(client, term, roomId, abortSignal);
const result = await serverSideSearch(term, roomId, abortSignal);
// The js-sdk method backPaginateRoomEventsSearch() uses _query internally // The js-sdk method backPaginateRoomEventsSearch() uses _query internally
// so we're reusing the concept here since we want to delegate the // 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; return 0;
} }
async function combinedSearch(searchTerm: string, abortSignal?: AbortSignal): Promise<ISearchResults> { async function combinedSearch(
const client = MatrixClientPeg.get(); client: MatrixClient,
searchTerm: string,
abortSignal?: AbortSignal,
): Promise<ISearchResults> {
// Create two promises, one for the local search, one for the // Create two promises, one for the local search, one for the
// server-side search. // server-side search.
const serverSidePromise = serverSideSearch(searchTerm, undefined, abortSignal); const serverSidePromise = serverSideSearch(client, searchTerm, undefined, abortSignal);
const localPromise = localSearch(searchTerm); const localPromise = localSearch(searchTerm);
// Wait for both promises to resolve. // Wait for both promises to resolve.
@ -198,7 +199,11 @@ export interface ISeshatSearchResults extends ISearchResults {
serverSideNextBatch?: string; serverSideNextBatch?: string;
} }
async function localSearchProcess(searchTerm: string, roomId?: string): Promise<ISeshatSearchResults> { async function localSearchProcess(
client: MatrixClient,
searchTerm: string,
roomId?: string,
): Promise<ISeshatSearchResults> {
const emptyResult = { const emptyResult = {
results: [], results: [],
highlights: [], 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. // Restore our encryption info so we can properly re-verify the events.
restoreEncryptionInfo(processedResult.results); restoreEncryptionInfo(processedResult.results);
return processedResult; return processedResult;
} }
async function localPagination(searchResult: ISeshatSearchResults): Promise<ISeshatSearchResults> { async function localPagination(
client: MatrixClient,
searchResult: ISeshatSearchResults,
): Promise<ISeshatSearchResults> {
const eventIndex = EventIndexPeg.get(); const eventIndex = EventIndexPeg.get();
const searchArgs = searchResult.seshatQuery; 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. // Restore our encryption info so we can properly re-verify the events.
const newSlice = result.results.slice(Math.max(result.results.length - newResultCount, 0)); 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 eventIndex = EventIndexPeg.get();
const client = MatrixClientPeg.get();
const searchArgs = searchResult.seshatQuery; const searchArgs = searchResult.seshatQuery;
const oldestEventFrom = searchResult.oldestEventFrom; const oldestEventFrom = searchResult.oldestEventFrom;
@ -588,31 +598,37 @@ async function combinedPagination(searchResult: ISeshatSearchResults): Promise<I
return result; 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>; let searchPromise: Promise<ISearchResults>;
if (roomId !== undefined) { if (roomId !== undefined) {
if (MatrixClientPeg.get().isRoomEncrypted(roomId)) { if (client.isRoomEncrypted(roomId)) {
// The search is for a single encrypted room, use our local // The search is for a single encrypted room, use our local
// search method. // search method.
searchPromise = localSearchProcess(term, roomId); searchPromise = localSearchProcess(client, term, roomId);
} else { } else {
// The search is for a single non-encrypted room, use the // The search is for a single non-encrypted room, use the
// server-side search. // server-side search.
searchPromise = serverSideSearchProcess(term, roomId, abortSignal); searchPromise = serverSideSearchProcess(client, term, roomId, abortSignal);
} }
} else { } else {
// Search across all rooms, combine a server side search and a // Search across all rooms, combine a server side search and a
// local search. // local search.
searchPromise = combinedSearch(term, abortSignal); searchPromise = combinedSearch(client, term, abortSignal);
} }
return searchPromise; return searchPromise;
} }
function eventIndexSearchPagination(searchResult: ISeshatSearchResults): Promise<ISeshatSearchResults> { function eventIndexSearchPagination(
const client = MatrixClientPeg.get(); client: MatrixClient,
searchResult: ISeshatSearchResults,
): Promise<ISeshatSearchResults> {
const seshatQuery = searchResult.seshatQuery; const seshatQuery = searchResult.seshatQuery;
const serverQuery = searchResult._query; const serverQuery = searchResult._query;
@ -622,36 +638,40 @@ function eventIndexSearchPagination(searchResult: ISeshatSearchResults): Promise
return client.backPaginateRoomEventsSearch(searchResult); return client.backPaginateRoomEventsSearch(searchResult);
} else if (!serverQuery) { } else if (!serverQuery) {
// This is a search in a encrypted room. Do a local pagination. // This is a search in a encrypted room. Do a local pagination.
const promise = localPagination(searchResult); const promise = localPagination(client, searchResult);
searchResult.pendingRequest = promise; searchResult.pendingRequest = promise;
return promise; return promise;
} else { } else {
// We have both queries around, this is a search across all rooms so a // We have both queries around, this is a search across all rooms so a
// combined pagination needs to be done. // combined pagination needs to be done.
const promise = combinedPagination(searchResult); const promise = combinedPagination(client, searchResult);
searchResult.pendingRequest = promise; searchResult.pendingRequest = promise;
return promise; return promise;
} }
} }
export function searchPagination(searchResult: ISearchResults): Promise<ISearchResults> { export function searchPagination(client: MatrixClient, searchResult: ISearchResults): Promise<ISearchResults> {
const eventIndex = EventIndexPeg.get(); const eventIndex = EventIndexPeg.get();
const client = MatrixClientPeg.get();
if (searchResult.pendingRequest) return searchResult.pendingRequest; if (searchResult.pendingRequest) return searchResult.pendingRequest;
if (eventIndex === null) return client.backPaginateRoomEventsSearch(searchResult); 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(); const eventIndex = EventIndexPeg.get();
if (eventIndex === null) { if (eventIndex === null) {
return serverSideSearchProcess(term, roomId, abortSignal); return serverSideSearchProcess(client, term, roomId, abortSignal);
} else { } 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 { EventType } from "matrix-js-sdk/src/@types/event";
import { M_BEACON } from "matrix-js-sdk/src/@types/beacon"; import { M_BEACON } from "matrix-js-sdk/src/@types/beacon";
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 { MatrixClientPeg } from "./MatrixClientPeg";
import shouldHideEvent from "./shouldHideEvent"; import shouldHideEvent from "./shouldHideEvent";
import { haveRendererForEvent } from "./events/EventTileFactory"; import { haveRendererForEvent } from "./events/EventTileFactory";
import SettingsStore from "./settings/SettingsStore"; 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 * Returns true if this event arriving in a room should affect the room's
* count of unread messages * count of unread messages
* *
* @param client The Matrix Client instance of the logged-in user
* @param {Object} ev The event * @param {Object} ev The event
* @returns {boolean} True if the given event should affect the unread message count * @returns {boolean} True if the given event should affect the unread message count
*/ */
export function eventTriggersUnreadCount(ev: MatrixEvent): boolean { export function eventTriggersUnreadCount(client: MatrixClient, ev: MatrixEvent): boolean {
if (ev.getSender() === MatrixClientPeg.get().credentials.userId) { if (ev.getSender() === client.getSafeUserId()) {
return false; return false;
} }
@ -83,7 +84,7 @@ export function doesRoomOrThreadHaveUnreadMessages(roomOrThread: Room | Thread):
return false; 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 // 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! // 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 // that counts and we can stop looking because the user's read
// this and everything before. // this and everything before.
return false; return false;
} else if (isImportantEvent(ev)) { } else if (isImportantEvent(roomOrThread.client, ev)) {
// We've found a message that counts before we hit // We've found a message that counts before we hit
// the user's read receipt, so this room is definitely unread. // the user's read receipt, so this room is definitely unread.
return true; 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 * Given this event does not have a receipt, is it important enough to make
* this room unread? * this room unread?
*/ */
function isImportantEvent(event: MatrixEvent): boolean { function isImportantEvent(client: MatrixClient, event: MatrixEvent): boolean {
return !shouldHideEvent(event) && eventTriggersUnreadCount(event); 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 { Room } from "matrix-js-sdk/src/models/room";
import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { MatrixClientPeg } from "./MatrixClientPeg";
import { _t } from "./languageHandler"; import { _t } from "./languageHandler";
export function usersTypingApartFromMeAndIgnored(room: Room): RoomMember[] { 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[] { 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"); this.notifyNewScreen("forgot_password");
break; break;
case "start_chat": case "start_chat":
createRoom({ createRoom(MatrixClientPeg.get(), {
dmUserId: payload.user_id, dmUserId: payload.user_id,
}); });
break; break;
@ -1062,7 +1062,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
const [shouldCreate, opts] = await modal.finished; const [shouldCreate, opts] = await modal.finished;
if (shouldCreate) { 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); const welcomeUserRooms = DMRoomMap.shared().getDMRoomsForUserId(welcomeUserId);
if (welcomeUserRooms.length === 0) { if (welcomeUserRooms.length === 0) {
const roomId = await createRoom({ const roomId = await createRoom(MatrixClientPeg.get(), {
dmUserId: snakedConfig.get("welcome_user_id"), dmUserId: snakedConfig.get("welcome_user_id"),
// Only view the welcome user if we're NOT looking at a room // Only view the welcome user if we're NOT looking at a room
andView: !this.state.currentRoomId, andView: !this.state.currentRoomId,

View file

@ -181,7 +181,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(
} }
debuglog("requesting more search results"); debuglog("requesting more search results");
const searchPromise = searchPagination(results); const searchPromise = searchPagination(client, results);
return handleSearchResult(searchPromise); 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; const roomId = scope === SearchScope.Room ? this.getRoomId() : undefined;
debuglog("sending search request"); debuglog("sending search request");
const abortController = new AbortController(); const abortController = new AbortController();
const promise = eventSearch(term, roomId, abortController.signal); const promise = eventSearch(this.context.client!, term, roomId, abortController.signal);
this.setState({ this.setState({
search: { search: {

View file

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

View file

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

View file

@ -79,7 +79,16 @@ const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick
} }
try { 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); onFinished(true);
} catch (e) { } catch (e) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -35,6 +35,7 @@ import SettingsTab from "../SettingsTab";
import { SettingsSection } from "../../shared/SettingsSection"; import { SettingsSection } from "../../shared/SettingsSection";
import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection"; import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection";
import ExternalLink from "../../../elements/ExternalLink"; import ExternalLink from "../../../elements/ExternalLink";
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
interface IProps { interface IProps {
closeSettingsFn: () => void; closeSettingsFn: () => void;
@ -46,6 +47,9 @@ interface IState {
} }
export default class HelpUserSettingsTab extends React.Component<IProps, IState> { export default class HelpUserSettingsTab extends React.Component<IProps, IState> {
public static contextType = MatrixClientContext;
public context!: React.ContextType<typeof MatrixClientContext>;
public constructor(props: IProps) { public constructor(props: IProps) {
super(props); super(props);
@ -104,7 +108,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
private onStartBotChat = (): void => { private onStartBotChat = (): void => {
this.props.closeSettingsFn(); this.props.closeSettingsFn();
createRoom({ createRoom(this.context, {
dmUserId: SdkConfig.get("welcome_user_id"), dmUserId: SdkConfig.get("welcome_user_id"),
andView: true, 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 { ICreateRoomOpts } from "matrix-js-sdk/src/@types/requests";
import { HistoryVisibility, Preset, Visibility } from "matrix-js-sdk/src/@types/partials"; import { HistoryVisibility, Preset, Visibility } from "matrix-js-sdk/src/@types/partials";
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 { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import ContextMenu, { ChevronFace } from "../../structures/ContextMenu"; import ContextMenu, { ChevronFace } from "../../structures/ContextMenu";
import createRoom, { IOpts as ICreateOpts } from "../../../createRoom"; import createRoom, { IOpts as ICreateOpts } from "../../../createRoom";
import MatrixClientContext from "../../../contexts/MatrixClientContext"; import MatrixClientContext, { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
import SpaceBasicSettings, { SpaceAvatar } from "./SpaceBasicSettings"; import SpaceBasicSettings, { SpaceAvatar } from "./SpaceBasicSettings";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import Field from "../elements/Field"; import Field from "../elements/Field";
@ -43,8 +44,9 @@ import withValidation from "../elements/Validation";
import RoomAliasField from "../elements/RoomAliasField"; import RoomAliasField from "../elements/RoomAliasField";
import { getKeyBindingsManager } from "../../../KeyBindingsManager"; import { getKeyBindingsManager } from "../../../KeyBindingsManager";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
export const createSpace = async ( export const createSpace = async (
client: MatrixClient,
name: string, name: string,
isPublic: boolean, isPublic: boolean,
alias?: string, alias?: string,
@ -53,12 +55,12 @@ export const createSpace = async (
createOpts: Partial<ICreateRoomOpts> = {}, createOpts: Partial<ICreateRoomOpts> = {},
otherOpts: Partial<Omit<ICreateOpts, "createOpts">> = {}, otherOpts: Partial<Omit<ICreateOpts, "createOpts">> = {},
): Promise<string | null> => { ): Promise<string | null> => {
return createRoom({ return createRoom(client, {
createOpts: { createOpts: {
name, name,
preset: isPublic ? Preset.PublicChat : Preset.PrivateChat, preset: isPublic ? Preset.PublicChat : Preset.PrivateChat,
visibility: visibility:
isPublic && (await MatrixClientPeg.get().doesServerSupportUnstableFeature("org.matrix.msc3827.stable")) isPublic && (await client.doesServerSupportUnstableFeature("org.matrix.msc3827.stable"))
? Visibility.Public ? Visibility.Public
: Visibility.Private, : Visibility.Private,
power_level_content_override: { power_level_content_override: {
@ -208,6 +210,7 @@ export const SpaceCreateForm: React.FC<ISpaceCreateFormProps> = ({
const SpaceCreateMenu: React.FC<{ const SpaceCreateMenu: React.FC<{
onFinished(): void; onFinished(): void;
}> = ({ onFinished }) => { }> = ({ onFinished }) => {
const cli = useMatrixClientContext();
const [visibility, setVisibility] = useState<Visibility | null>(null); const [visibility, setVisibility] = useState<Visibility | null>(null);
const [busy, setBusy] = useState<boolean>(false); const [busy, setBusy] = useState<boolean>(false);
@ -243,7 +246,7 @@ const SpaceCreateMenu: React.FC<{
} }
try { try {
await createSpace(name, visibility === Visibility.Public, alias, topic, avatar); await createSpace(cli, name, visibility === Visibility.Public, alias, topic, avatar);
onFinished(); onFinished();
} catch (e) { } catch (e) {

View file

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

View file

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

View file

@ -90,5 +90,5 @@ export async function startDm(client: MatrixClient, targets: Member[], showSpinn
} }
createRoomOptions.spinner = showSpinner; 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; const [shouldCreate, opts] = await modal.finished;
if (shouldCreate) { if (shouldCreate) {
await createRoom(opts); await createRoom(space.client, opts);
} }
return !!shouldCreate; return !!shouldCreate;
}; };

View file

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

View file

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