Enable more oxlint rules (#34189)
* Fix type imports * Fix jsdoc * Fixup types * Fix stray awaits on non-thenables * Fixup imports * Fix splats * Fix this-context on callbacks * Memoise react contexts * Prefer find/flatMap * Make oxlint happier about our React keys * Avoid unsafe default function params * Fixup jsdoc * Fixup contexts * Switch from eslint to oxlint * Some oxlint-related tweaks * Iterate * Partial revert to defer some changes and shrink diff * Iterate * Add eslint-plugin-element-call and enable the copyright rule * Set strictStorePkgContentCheck * Iterate * Enable forwardRef oxlint rule * Enable no-unused-vars oxlint rule * Enable no-implied-eval oxlint rule * Enable no-duplicate-type-constituents oxlint rule * Enable explicit-length-check oxlint rule * Enable prefer-number-properties oxlint rule * Enable no-callback-in-promise oxlint rule * Enable no-require-imports oxlint rule * Remove disablement of most unicorn oxlint rules * Enable no-conditional-tests oxlint rule * Enable promise-valid-params oxlint rule * Enable require-unicode-regexp oxlint rule * Remove max-len comments as we use oxfmt for formatting * Enable majority of oxlint `suspicious` rules * Iterate * Fix oxlint type-aware lint running without dependencies built
This commit is contained in:
@@ -75,7 +75,7 @@ if (process.env.VARIANT_PATH) {
|
|||||||
console.log(`Using variant configuration from '${process.env.VARIANT_PATH}':`);
|
console.log(`Using variant configuration from '${process.env.VARIANT_PATH}':`);
|
||||||
variant = {
|
variant = {
|
||||||
...variant,
|
...variant,
|
||||||
...JSON.parse(fs.readFileSync(`${process.env.VARIANT_PATH}`, "utf8")),
|
...JSON.parse(fs.readFileSync(process.env.VARIANT_PATH, "utf8")),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
console.warn(`No VARIANT_PATH specified, using default variant configuration '${DEFAULT_VARIANT}':`);
|
console.warn(`No VARIANT_PATH specified, using default variant configuration '${DEFAULT_VARIANT}':`);
|
||||||
|
|||||||
@@ -48,8 +48,9 @@ export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Prom
|
|||||||
"` " +
|
"` " +
|
||||||
"or your package manager if not using `rustup`",
|
"or your package manager if not using `rustup`",
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
fsProm.unlink("tmp").then(resolve);
|
resolve(fsProm.unlink("tmp"));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
rustc.stdin!.write("fn main() {}");
|
rustc.stdin!.write("fn main() {}");
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo):
|
|||||||
if (moduleInfo.moduleBuildDirs.length > 1) {
|
if (moduleInfo.moduleBuildDirs.length > 1) {
|
||||||
if (!hakEnv.isMac()) {
|
if (!hakEnv.isMac()) {
|
||||||
console.error(
|
console.error(
|
||||||
"You asked me to copy multiple targets but I've only been taught " + "how to do that on macOS.",
|
"You asked me to copy multiple targets but I've only been taught how to do that on macOS.",
|
||||||
);
|
);
|
||||||
throw new Error("Can't copy multiple targets on this platform");
|
throw new Error("Can't copy multiple targets on this platform");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ async function main(): Promise<void> {
|
|||||||
for (const mod of modules) {
|
for (const mod of modules) {
|
||||||
const depInfo = deps[mod];
|
const depInfo = deps[mod];
|
||||||
if (depInfo === undefined) {
|
if (depInfo === undefined) {
|
||||||
console.log("Module " + mod + " not found - is it in hakDependencies " + "in your package.json?");
|
console.log(`Module ${mod} not found - is it in hakDependencies in your package.json?`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
console.log("hak " + cmd + ": " + mod);
|
console.log("hak " + cmd + ": " + mod);
|
||||||
|
|||||||
@@ -42,12 +42,10 @@ describe("buildMenuTemplate", () => {
|
|||||||
({ buildMenuTemplate } = await import("./vectormenu.js"));
|
({ buildMenuTemplate } = await import("./vectormenu.js"));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (platform === "darwin") {
|
it.runIf(platform === "darwin")("should have an app-named item first", () => {
|
||||||
it("should have an app-named item first", () => {
|
const menu = buildMenuTemplate();
|
||||||
const menu = buildMenuTemplate();
|
expect(menu.items[0].label).toBe("ChatApp");
|
||||||
expect(menu.items[0].label).toBe("ChatApp");
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
it("should include expected `help` menu", () => {
|
it("should include expected `help` menu", () => {
|
||||||
const menu = buildMenuTemplate();
|
const menu = buildMenuTemplate();
|
||||||
@@ -55,8 +53,8 @@ describe("buildMenuTemplate", () => {
|
|||||||
const helpMenu = menu.items.at(-1)!;
|
const helpMenu = menu.items.at(-1)!;
|
||||||
expect(helpMenu.label).toBe("common|help");
|
expect(helpMenu.label).toBe("common|help");
|
||||||
const helpSubmenu = helpMenu.submenu as unknown as MenuItemConstructorOptions[];
|
const helpSubmenu = helpMenu.submenu as unknown as MenuItemConstructorOptions[];
|
||||||
expect(helpSubmenu[0]!.label).toBe("common|brand_help");
|
expect(helpSubmenu[0].label).toBe("common|brand_help");
|
||||||
helpSubmenu[0]!.click!(menu.items.at(-1)!, undefined, new Event("click") as KeyboardEvent);
|
helpSubmenu[0].click!(menu.items.at(-1)!, undefined, new Event("click") as KeyboardEvent);
|
||||||
expect(shell.openExternal).toHaveBeenCalledWith("https://i.need.help");
|
expect(shell.openExternal).toHaveBeenCalledWith("https://i.need.help");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ declare module "webpack-version-file-plugin" {
|
|||||||
extras?: Record<string, string>;
|
extras?: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export default class VersionFilePlugin {
|
export default class VersionFilePlugin {
|
||||||
public constructor(opts: Opts);
|
public constructor(opts: Opts);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -609,7 +609,7 @@ class Helpers {
|
|||||||
const roomListContainer = this.page.getByTestId("room-list");
|
const roomListContainer = this.page.getByTestId("room-list");
|
||||||
const roomTiles = roomListContainer.getByRole("option");
|
const roomTiles = roomListContainer.getByRole("option");
|
||||||
for (const [i, room] of rooms.entries()) {
|
for (const [i, room] of rooms.entries()) {
|
||||||
await expect(roomTiles.nth(i)).toHaveAccessibleName(new RegExp(`${room.name}`));
|
await expect(roomTiles.nth(i)).toHaveAccessibleName(new RegExp(room.name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,11 +120,11 @@ test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
|||||||
await sendUnthreadedReadReceipt(app, main2);
|
await sendUnthreadedReadReceipt(app, main2);
|
||||||
|
|
||||||
// (So the room has no unreads)
|
// (So the room has no unreads)
|
||||||
await expect(page.getByLabel(`${otherRoomName}`)).toBeVisible();
|
await expect(page.getByLabel(otherRoomName)).toBeVisible();
|
||||||
|
|
||||||
// And we persuade the app to persist its state to indexeddb by reloading and waiting
|
// And we persuade the app to persist its state to indexeddb by reloading and waiting
|
||||||
await page.reload();
|
await page.reload();
|
||||||
await expect(page.getByLabel(`${selectedRoomName}`)).toBeVisible();
|
await expect(page.getByLabel(selectedRoomName)).toBeVisible();
|
||||||
|
|
||||||
// And we reload again, fetching the persisted state FROM indexeddb
|
// And we reload again, fetching the persisted state FROM indexeddb
|
||||||
await page.reload();
|
await page.reload();
|
||||||
@@ -132,7 +132,7 @@ test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
|||||||
// Then the room is read, because the persisted state correctly remembers both
|
// Then the room is read, because the persisted state correctly remembers both
|
||||||
// receipts. (In #24629, the unthreaded receipt overwrote the main thread one,
|
// receipts. (In #24629, the unthreaded receipt overwrote the main thread one,
|
||||||
// meaning that the room still said it had unread messages.)
|
// meaning that the room still said it had unread messages.)
|
||||||
await expect(page.getByLabel(`${otherRoomName}`)).toBeVisible();
|
await expect(page.getByLabel(otherRoomName)).toBeVisible();
|
||||||
await expect(page.getByLabel(`${otherRoomName} Unread messages.`)).not.toBeVisible();
|
await expect(page.getByLabel(`${otherRoomName} Unread messages.`)).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
|||||||
await sendThreadedReadReceipt(app, main3);
|
await sendThreadedReadReceipt(app, main3);
|
||||||
|
|
||||||
// Then the room has no unreads
|
// Then the room has no unreads
|
||||||
await expect(page.getByLabel(`${otherRoomName}`)).toBeVisible();
|
await expect(page.getByLabel(otherRoomName)).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Recognises unread messages on other thread after receiving a receipt for earlier ones", async ({
|
test("Recognises unread messages on other thread after receiving a receipt for earlier ones", async ({
|
||||||
@@ -210,7 +210,7 @@ test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
|||||||
await sendThreadedReadReceipt(app, thread1b, main1);
|
await sendThreadedReadReceipt(app, thread1b, main1);
|
||||||
|
|
||||||
// Then the room has no unreads
|
// Then the room has no unreads
|
||||||
await expect(page.getByLabel(`${otherRoomName}`)).toBeVisible();
|
await expect(page.getByLabel(otherRoomName)).toBeVisible();
|
||||||
await util.goTo({ name: otherRoomName, roomId: otherRoomId });
|
await util.goTo({ name: otherRoomName, roomId: otherRoomId });
|
||||||
await util.assertReadThread("Message 1");
|
await util.assertReadThread("Message 1");
|
||||||
});
|
});
|
||||||
@@ -235,7 +235,7 @@ test.describe("Read receipts", { tag: "@mergequeue" }, () => {
|
|||||||
// thread. The one in main is read because the unthreaded
|
// thread. The one in main is read because the unthreaded
|
||||||
// receipt is for a later event. The room should therefore be
|
// receipt is for a later event. The room should therefore be
|
||||||
// read, and the thread unread.
|
// read, and the thread unread.
|
||||||
await expect(page.getByLabel(`${otherRoomName}`)).toBeVisible();
|
await expect(page.getByLabel(otherRoomName)).toBeVisible();
|
||||||
await util.goTo({ name: otherRoomName, roomId: otherRoomId });
|
await util.goTo({ name: otherRoomName, roomId: otherRoomId });
|
||||||
await util.assertUnreadThread("Message 1");
|
await util.assertUnreadThread("Message 1");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,6 +46,10 @@
|
|||||||
},
|
},
|
||||||
"dependsOn": ["^build", "^build:playwright"]
|
"dependsOn": ["^build", "^build:playwright"]
|
||||||
},
|
},
|
||||||
|
"lint:prepare": {
|
||||||
|
"executor": "nx:noop",
|
||||||
|
"dependsOn": ["^build"]
|
||||||
|
},
|
||||||
"test:unit:prepare": {
|
"test:unit:prepare": {
|
||||||
"executor": "nx:noop",
|
"executor": "nx:noop",
|
||||||
"dependsOn": ["^build"]
|
"dependsOn": ["^build"]
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ export function bodyToNode(content: IContent, highlights?: string[], opts: Event
|
|||||||
// This has to be done after the emojiBody check as to not break big emoji on replies
|
// This has to be done after the emojiBody check as to not break big emoji on replies
|
||||||
formattedBody = formatEmojis(eventInfo.safeBody, true).join("");
|
formattedBody = formatEmojis(eventInfo.safeBody, true).join("");
|
||||||
} else {
|
} else {
|
||||||
emojiBodyElements = formatEmojis(eventInfo.strippedBody, false) as JSX.Element[];
|
emojiBodyElements = formatEmojis(eventInfo.strippedBody, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ export default class Notifier extends TypedEventEmitter<keyof EmittedEvents, Emi
|
|||||||
avatarUrl = Avatar.avatarUrlForMember(ev.sender, 40, 40, "crop");
|
avatarUrl = Avatar.avatarUrlForMember(ev.sender, 40, 40, "crop");
|
||||||
}
|
}
|
||||||
|
|
||||||
const notif = plaf.displayNotification(title, msg!, avatarUrl, room, ev);
|
const notif = plaf.displayNotification(title, msg, avatarUrl, room, ev);
|
||||||
|
|
||||||
// if displayNotification returns non-null, the platform supports
|
// if displayNotification returns non-null, the platform supports
|
||||||
// clearing notifications later, so keep track of this.
|
// clearing notifications later, so keep track of this.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { logger } from "matrix-js-sdk/src/logger";
|
|||||||
|
|
||||||
import dis from "./dispatcher/dispatcher";
|
import dis from "./dispatcher/dispatcher";
|
||||||
|
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export default class Resend {
|
export default class Resend {
|
||||||
public static resendUnsentEvents(room: Room): Promise<void[]> {
|
public static resendUnsentEvents(room: Room): Promise<void[]> {
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ export function showAnyInviteErrors(
|
|||||||
(avatarUrl && mediaFromMxc(avatarUrl).getSquareThumbnailHttp(24)) ??
|
(avatarUrl && mediaFromMxc(avatarUrl).getSquareThumbnailHttp(24)) ??
|
||||||
undefined
|
undefined
|
||||||
}
|
}
|
||||||
name={name!}
|
name={name}
|
||||||
idName={user?.userId}
|
idName={user?.userId}
|
||||||
size="36px"
|
size="36px"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ function isRuleRoomMuteRuleForRoomId(roomId: string, rule: IPushRule): boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// isRuleMaybeRoomMuteRule checks this condition exists
|
// isRuleMaybeRoomMuteRule checks this condition exists
|
||||||
const cond = rule.conditions![0]!;
|
const cond = rule.conditions![0];
|
||||||
return cond.pattern === roomId;
|
return cond.pattern === roomId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -316,14 +316,14 @@ enum Action {
|
|||||||
ReadEvents = "read_events",
|
ReadEvents = "read_events",
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendResponse(event: MessageEvent<any>, res: any): void {
|
function sendResponse(event: MessageEvent, res: any): void {
|
||||||
const data = objectClone(event.data);
|
const data = objectClone(event.data);
|
||||||
data.response = res;
|
data.response = res;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
event.source.postMessage(data, event.origin);
|
event.source.postMessage(data, event.origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendError(event: MessageEvent<any>, msg: string, nestedError?: Error): void {
|
function sendError(event: MessageEvent, msg: string, nestedError?: Error): void {
|
||||||
logger.error("Action:" + event.data.action + " failed with message: " + msg);
|
logger.error("Action:" + event.data.action + " failed with message: " + msg);
|
||||||
const data = objectClone(event.data);
|
const data = objectClone(event.data);
|
||||||
data.response = {
|
data.response = {
|
||||||
@@ -338,7 +338,7 @@ function sendError(event: MessageEvent<any>, msg: string, nestedError?: Error):
|
|||||||
event.source.postMessage(data, event.origin);
|
event.source.postMessage(data, event.origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
function inviteUser(event: MessageEvent<any>, roomId: string, userId: string): void {
|
function inviteUser(event: MessageEvent, roomId: string, userId: string): void {
|
||||||
logger.log(`Received request to invite ${userId} into room ${roomId}`);
|
logger.log(`Received request to invite ${userId} into room ${roomId}`);
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
if (!client) {
|
if (!client) {
|
||||||
@@ -372,7 +372,7 @@ function inviteUser(event: MessageEvent<any>, roomId: string, userId: string): v
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function kickUser(event: MessageEvent<any>, roomId: string, userId: string): void {
|
function kickUser(event: MessageEvent, roomId: string, userId: string): void {
|
||||||
logger.log(`Received request to kick ${userId} from room ${roomId}`);
|
logger.log(`Received request to kick ${userId} from room ${roomId}`);
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
if (!client) {
|
if (!client) {
|
||||||
@@ -404,7 +404,7 @@ function kickUser(event: MessageEvent<any>, roomId: string, userId: string): voi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWidget(event: MessageEvent<any>, roomId: string | null): void {
|
function setWidget(event: MessageEvent, roomId: string | null): void {
|
||||||
const client = MatrixClientPeg.safeGet();
|
const client = MatrixClientPeg.safeGet();
|
||||||
const widgetId = event.data.widget_id;
|
const widgetId = event.data.widget_id;
|
||||||
let widgetType = event.data.type;
|
let widgetType = event.data.type;
|
||||||
@@ -488,7 +488,7 @@ function setWidget(event: MessageEvent<any>, roomId: string | null): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWidgets(event: MessageEvent<any>, roomId: string | null): void {
|
function getWidgets(event: MessageEvent, roomId: string | null): void {
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
if (!client) {
|
if (!client) {
|
||||||
sendError(event, _t("widget|error_need_to_be_logged_in"));
|
sendError(event, _t("widget|error_need_to_be_logged_in"));
|
||||||
@@ -514,7 +514,7 @@ function getWidgets(event: MessageEvent<any>, roomId: string | null): void {
|
|||||||
sendResponse(event, widgetStateEvents);
|
sendResponse(event, widgetStateEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getRoomEncState(event: MessageEvent<any>, roomId: string): Promise<void> {
|
async function getRoomEncState(event: MessageEvent, roomId: string): Promise<void> {
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
if (!client) {
|
if (!client) {
|
||||||
sendError(event, _t("widget|error_need_to_be_logged_in"));
|
sendError(event, _t("widget|error_need_to_be_logged_in"));
|
||||||
@@ -530,7 +530,7 @@ async function getRoomEncState(event: MessageEvent<any>, roomId: string): Promis
|
|||||||
sendResponse(event, roomIsEncrypted);
|
sendResponse(event, roomIsEncrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setPlumbingState(event: MessageEvent<any>, roomId: string, status: string): void {
|
function setPlumbingState(event: MessageEvent, roomId: string, status: string): void {
|
||||||
if (typeof status !== "string") {
|
if (typeof status !== "string") {
|
||||||
throw new Error("Plumbing state status should be a string");
|
throw new Error("Plumbing state status should be a string");
|
||||||
}
|
}
|
||||||
@@ -552,7 +552,7 @@ function setPlumbingState(event: MessageEvent<any>, roomId: string, status: stri
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBotOptions(event: MessageEvent<any>, roomId: string, userId: string): void {
|
function setBotOptions(event: MessageEvent, roomId: string, userId: string): void {
|
||||||
logger.log(`Received request to set options for bot ${userId} in room ${roomId}`);
|
logger.log(`Received request to set options for bot ${userId} in room ${roomId}`);
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
if (!client) {
|
if (!client) {
|
||||||
@@ -572,7 +572,7 @@ function setBotOptions(event: MessageEvent<any>, roomId: string, userId: string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function setBotPower(
|
async function setBotPower(
|
||||||
event: MessageEvent<any>,
|
event: MessageEvent,
|
||||||
roomId: string,
|
roomId: string,
|
||||||
userId: string,
|
userId: string,
|
||||||
level: number,
|
level: number,
|
||||||
@@ -613,22 +613,22 @@ async function setBotPower(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMembershipState(event: MessageEvent<any>, roomId: string, userId: string): void {
|
function getMembershipState(event: MessageEvent, roomId: string, userId: string): void {
|
||||||
logger.log(`membership_state of ${userId} in room ${roomId} requested.`);
|
logger.log(`membership_state of ${userId} in room ${roomId} requested.`);
|
||||||
returnStateEvent(event, roomId, "m.room.member", userId);
|
returnStateEvent(event, roomId, "m.room.member", userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getJoinRules(event: MessageEvent<any>, roomId: string): void {
|
function getJoinRules(event: MessageEvent, roomId: string): void {
|
||||||
logger.log(`join_rules of ${roomId} requested.`);
|
logger.log(`join_rules of ${roomId} requested.`);
|
||||||
returnStateEvent(event, roomId, "m.room.join_rules", "");
|
returnStateEvent(event, roomId, "m.room.join_rules", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function botOptions(event: MessageEvent<any>, roomId: string, userId: string): void {
|
function botOptions(event: MessageEvent, roomId: string, userId: string): void {
|
||||||
logger.log(`bot_options of ${userId} in room ${roomId} requested.`);
|
logger.log(`bot_options of ${userId} in room ${roomId} requested.`);
|
||||||
returnStateEvent(event, roomId, "m.room.bot.options", "_" + userId);
|
returnStateEvent(event, roomId, "m.room.bot.options", "_" + userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMembershipCount(event: MessageEvent<any>, roomId: string): void {
|
function getMembershipCount(event: MessageEvent, roomId: string): void {
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
if (!client) {
|
if (!client) {
|
||||||
sendError(event, _t("widget|error_need_to_be_logged_in"));
|
sendError(event, _t("widget|error_need_to_be_logged_in"));
|
||||||
@@ -643,7 +643,7 @@ function getMembershipCount(event: MessageEvent<any>, roomId: string): void {
|
|||||||
sendResponse(event, count);
|
sendResponse(event, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
function canSendEvent(event: MessageEvent<any>, roomId: string): void {
|
function canSendEvent(event: MessageEvent, roomId: string): void {
|
||||||
const evType = "" + event.data.event_type; // force stringify
|
const evType = "" + event.data.event_type; // force stringify
|
||||||
const isState = Boolean(event.data.is_state);
|
const isState = Boolean(event.data.is_state);
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
@@ -677,7 +677,7 @@ function canSendEvent(event: MessageEvent<any>, roomId: string): void {
|
|||||||
sendResponse(event, true);
|
sendResponse(event, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function returnStateEvent(event: MessageEvent<any>, roomId: string, eventType: string, stateKey: string): void {
|
function returnStateEvent(event: MessageEvent, roomId: string, eventType: string, stateKey: string): void {
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
if (!client) {
|
if (!client) {
|
||||||
sendError(event, _t("widget|error_need_to_be_logged_in"));
|
sendError(event, _t("widget|error_need_to_be_logged_in"));
|
||||||
@@ -696,7 +696,7 @@ function returnStateEvent(event: MessageEvent<any>, roomId: string, eventType: s
|
|||||||
sendResponse(event, stateEvent.getContent());
|
sendResponse(event, stateEvent.getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getOpenIdToken(event: MessageEvent<any>): Promise<void> {
|
async function getOpenIdToken(event: MessageEvent): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const tokenObject = await MatrixClientPeg.safeGet().getOpenIdToken();
|
const tokenObject = await MatrixClientPeg.safeGet().getOpenIdToken();
|
||||||
sendResponse(event, tokenObject);
|
sendResponse(event, tokenObject);
|
||||||
@@ -841,7 +841,7 @@ async function readEvents(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onMessage = function (event: MessageEvent<any>): void {
|
const onMessage = function (event: MessageEvent): void {
|
||||||
if (!event.origin) {
|
if (!event.origin) {
|
||||||
// @ts-ignore - stupid chrome
|
// @ts-ignore - stupid chrome
|
||||||
event.origin = event.originalEvent.origin;
|
event.origin = event.originalEvent.origin;
|
||||||
@@ -987,7 +987,7 @@ export function stopListening(): void {
|
|||||||
}
|
}
|
||||||
if (listenerCount < 0) {
|
if (listenerCount < 0) {
|
||||||
// Make an error so we get a stack trace
|
// Make an error so we get a stack trace
|
||||||
const e = new Error("ScalarMessaging: mismatched startListening / stopListening detected." + " Negative count");
|
const e = new Error("ScalarMessaging: mismatched startListening / stopListening detected. Negative count");
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ type ObjectType<K extends keyof IConfigOptions> = IConfigOptions[K] extends obje
|
|||||||
? SnakedObject<NonNullable<IConfigOptions[K]>>
|
? SnakedObject<NonNullable<IConfigOptions[K]>>
|
||||||
: SnakedObject<NonNullable<IConfigOptions[K]>> | null | undefined;
|
: SnakedObject<NonNullable<IConfigOptions[K]>> | null | undefined;
|
||||||
|
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export default class SdkConfig {
|
export default class SdkConfig {
|
||||||
private static instance: DeepReadonly<IConfigOptions>;
|
private static instance: DeepReadonly<IConfigOptions>;
|
||||||
private static fallback: SnakedObject<DeepReadonly<IConfigOptions>>;
|
private static fallback: SnakedObject<DeepReadonly<IConfigOptions>>;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ function getRoomMemberDisplayname(client: MatrixClient, event: MatrixEvent, user
|
|||||||
}
|
}
|
||||||
|
|
||||||
function textForCallEvent(event: MatrixEvent, client: MatrixClient): () => string {
|
function textForCallEvent(event: MatrixEvent, client: MatrixClient): () => string {
|
||||||
const roomName = client.getRoom(event.getRoomId()!)?.name;
|
const roomName = client.getRoom(event.getRoomId())?.name;
|
||||||
const isSupported = client.supportsVoip();
|
const isSupported = client.supportsVoip();
|
||||||
|
|
||||||
return isSupported
|
return isSupported
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export const getKeyboardShortcuts = (): IKeyboardShortcuts => {
|
|||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.reduce((o, key) => {
|
.reduce((o, key) => {
|
||||||
o[key as KeyBindingAction] = KEYBOARD_SHORTCUTS[key as KeyBindingAction];
|
o[key] = KEYBOARD_SHORTCUTS[key];
|
||||||
return o;
|
return o;
|
||||||
}, {} as IKeyboardShortcuts);
|
}, {} as IKeyboardShortcuts);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const ORDERED_LANDMARKS = [
|
|||||||
* The landmarks are cycled through in the following order:
|
* The landmarks are cycled through in the following order:
|
||||||
* ACTIVE_SPACE_BUTTON <-> ROOM_SEARCH <-> ROOM_LIST <-> MESSAGE_COMPOSER/HOME <-> ACTIVE_SPACE_BUTTON
|
* ACTIVE_SPACE_BUTTON <-> ROOM_SEARCH <-> ROOM_LIST <-> MESSAGE_COMPOSER/HOME <-> ACTIVE_SPACE_BUTTON
|
||||||
*/
|
*/
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export class LandmarkNavigation {
|
export class LandmarkNavigation {
|
||||||
/**
|
/**
|
||||||
* Get the next/previous landmark that must be focused from a given landmark
|
* Get the next/previous landmark that must be focused from a given landmark
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { type AsyncActionPayload } from "../dispatcher/payloads";
|
|||||||
import { DefaultTagID, type TagID } from "../stores/room-list-v3/skip-list/tag";
|
import { DefaultTagID, type TagID } from "../stores/room-list-v3/skip-list/tag";
|
||||||
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
|
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
|
||||||
|
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export default class RoomListActions {
|
export default class RoomListActions {
|
||||||
/**
|
/**
|
||||||
* Creates an action thunk that will do an asynchronous request to
|
* Creates an action thunk that will do an asynchronous request to
|
||||||
|
|||||||
@@ -62,16 +62,16 @@ class MxVoiceWorklet extends AudioWorkletProcessor {
|
|||||||
const maxVal = Math.max(...monoChan);
|
const maxVal = Math.max(...monoChan);
|
||||||
const amplitude = percentageOf(maxVal, -1, 1) - percentageOf(minVal, -1, 1);
|
const amplitude = percentageOf(maxVal, -1, 1) - percentageOf(minVal, -1, 1);
|
||||||
|
|
||||||
this.port.postMessage(<IAmplitudePayload>{
|
this.port.postMessage({
|
||||||
ev: PayloadEvent.AmplitudeMark,
|
ev: PayloadEvent.AmplitudeMark,
|
||||||
amplitude: amplitude,
|
amplitude: amplitude,
|
||||||
forIndex: this.amplitudeIndex++,
|
forIndex: this.amplitudeIndex++,
|
||||||
});
|
} satisfies IAmplitudePayload);
|
||||||
this.nextAmplitudeSecond = nextTimeForTargetFreq(currentSecond);
|
this.nextAmplitudeSecond = nextTimeForTargetFreq(currentSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We mostly use this worklet to fire regular clock updates through to components
|
// We mostly use this worklet to fire regular clock updates through to components
|
||||||
this.port.postMessage(<ITimingPayload>{ ev: PayloadEvent.Timekeep, timeSeconds: currentTime });
|
this.port.postMessage({ ev: PayloadEvent.Timekeep, timeSeconds: currentTime } satisfies ITimingPayload);
|
||||||
|
|
||||||
// We're supposed to return false when we're "done" with the audio clip, but seeing as
|
// We're supposed to return false when we're "done" with the audio clip, but seeing as
|
||||||
// we are acting as a passive processor we are never truly "done". The browser will clean
|
// we are acting as a passive processor we are never truly "done". The browser will clean
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default class NotifProvider extends AutocompleteProvider {
|
|||||||
if (
|
if (
|
||||||
command?.[0] &&
|
command?.[0] &&
|
||||||
command[0].length > 1 &&
|
command[0].length > 1 &&
|
||||||
["@room", "@channel", "@everyone", "@here"].some((c) => c.startsWith(command![0]))
|
["@room", "@channel", "@everyone", "@here"].some((c) => c.startsWith(command[0]))
|
||||||
) {
|
) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ export default class ContextMenu extends React.PureComponent<React.PropsWithChil
|
|||||||
}
|
}
|
||||||
|
|
||||||
// When an <input> is focused, only handle the Escape key
|
// When an <input> is focused, only handle the Escape key
|
||||||
if (checkInputableElement(ev.target as HTMLElement) && action !== KeyBindingAction.Escape) {
|
if (checkInputableElement(ev.target) && action !== KeyBindingAction.Escape) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export function GenericDropdownMenu<T>({
|
|||||||
className,
|
className,
|
||||||
AdditionalOptions,
|
AdditionalOptions,
|
||||||
}: IProps<T>): JSX.Element {
|
}: IProps<T>): JSX.Element {
|
||||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu<HTMLElement>();
|
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
||||||
|
|
||||||
const valueKey = calculateKey(value, toKey);
|
const valueKey = calculateKey(value, toKey);
|
||||||
const selected: GenericDropdownMenuItem<T> | undefined = options
|
const selected: GenericDropdownMenuItem<T> | undefined = options
|
||||||
|
|||||||
@@ -1264,7 +1264,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||||||
if (isOnlyAdmin(roomToLeave)) {
|
if (isOnlyAdmin(roomToLeave)) {
|
||||||
const userLevelValues = roomToLeave.getJoinedMembers().map((m) => m.powerLevel);
|
const userLevelValues = roomToLeave.getJoinedMembers().map((m) => m.powerLevel);
|
||||||
|
|
||||||
const maxUserLevel = Math.max(...(userLevelValues as number[]));
|
const maxUserLevel = Math.max(...userLevelValues);
|
||||||
|
|
||||||
const warning =
|
const warning =
|
||||||
maxUserLevel >= 100
|
maxUserLevel >= 100
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export type CreatePipChildren = (options: IChildrenOptions) => JSX.Element;
|
|||||||
|
|
||||||
interface IChildrenOptions {
|
interface IChildrenOptions {
|
||||||
// a callback which is called when a mouse event (most likely mouse down) occurs at start of moving the pip around
|
// a callback which is called when a mouse event (most likely mouse down) occurs at start of moving the pip around
|
||||||
onStartMoving: (event: React.MouseEvent<Element, MouseEvent>) => void;
|
onStartMoving: (event: React.MouseEvent) => void;
|
||||||
// a callback which is called when the content fo the pip changes in a way that is likely to cause a resize
|
// a callback which is called when the content fo the pip changes in a way that is likely to cause a resize
|
||||||
onResize: (event: Event) => void;
|
onResize: (event: Event) => void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ export default class RightPanel extends React.Component<Props, IState> {
|
|||||||
<RoomSummaryCardView
|
<RoomSummaryCardView
|
||||||
room={this.props.room}
|
room={this.props.room}
|
||||||
// whenever RightPanel is passed a room it is passed a permalinkcreator
|
// whenever RightPanel is passed a room it is passed a permalinkcreator
|
||||||
permalinkCreator={this.props.permalinkCreator!}
|
permalinkCreator={this.props.permalinkCreator}
|
||||||
onSearchChange={this.props.onSearchChange}
|
onSearchChange={this.props.onSearchChange}
|
||||||
onSearchCancel={this.props.onSearchCancel}
|
onSearchCancel={this.props.onSearchCancel}
|
||||||
searchTerm={this.props.searchTerm}
|
searchTerm={this.props.searchTerm}
|
||||||
|
|||||||
@@ -1523,8 +1523,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
this.setState({ membersLoaded: true });
|
this.setState({ membersLoaded: true });
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const errorMessage =
|
const errorMessage = `Fetching room members for ${room.roomId} failed. Room members will appear incomplete.`;
|
||||||
`Fetching room members for ${room.roomId} failed.` + " Room members will appear incomplete.";
|
|
||||||
logger.error(errorMessage);
|
logger.error(errorMessage);
|
||||||
logger.error(err);
|
logger.error(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ export default class ScrollPanel extends React.Component<IProps> {
|
|||||||
this.unfillDebouncer = window.setTimeout(() => {
|
this.unfillDebouncer = window.setTimeout(() => {
|
||||||
this.unfillDebouncer = null;
|
this.unfillDebouncer = null;
|
||||||
debuglog("unfilling now", { backwards, origExcessHeight });
|
debuglog("unfilling now", { backwards, origExcessHeight });
|
||||||
this.props.onUnfillRequest?.(backwards, markerScrollToken!);
|
this.props.onUnfillRequest?.(backwards, markerScrollToken);
|
||||||
}, UNFILL_REQUEST_DEBOUNCE_MS);
|
}, UNFILL_REQUEST_DEBOUNCE_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -666,7 +666,7 @@ export default class ScrollPanel extends React.Component<IProps> {
|
|||||||
debuglog("unable to save scroll state: found no children in the viewport");
|
debuglog("unable to save scroll state: found no children in the viewport");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const scrollToken = node!.dataset.scrollTokens?.split(",")[0];
|
const scrollToken = node.dataset.scrollTokens?.split(",")[0];
|
||||||
debuglog("saving anchored scroll state to message", scrollToken);
|
debuglog("saving anchored scroll state to message", scrollToken);
|
||||||
const bottomOffset = this.topFromBottom(node);
|
const bottomOffset = this.topFromBottom(node);
|
||||||
this.scrollState = {
|
this.scrollState = {
|
||||||
@@ -788,7 +788,7 @@ export default class ScrollPanel extends React.Component<IProps> {
|
|||||||
const m = messages[i] as HTMLElement;
|
const m = messages[i] as HTMLElement;
|
||||||
// 'data-scroll-tokens' is a DOMString of comma-separated scroll tokens
|
// 'data-scroll-tokens' is a DOMString of comma-separated scroll tokens
|
||||||
// There might only be one scroll token
|
// There might only be one scroll token
|
||||||
if (scrollToken && m.dataset.scrollTokens?.split(",").includes(scrollToken!)) {
|
if (scrollToken && m.dataset.scrollTokens?.split(",").includes(scrollToken)) {
|
||||||
node = m;
|
node = m;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ import { Action } from "../../dispatcher/actions";
|
|||||||
import { type IState, RovingTabIndexProvider, useRovingTabIndex } from "../../accessibility/RovingTabIndex";
|
import { type IState, RovingTabIndexProvider, useRovingTabIndex } from "../../accessibility/RovingTabIndex";
|
||||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||||
import { useTypedEventEmitterState } from "../../hooks/useEventEmitter";
|
import { useTypedEventEmitterState } from "../../hooks/useEventEmitter";
|
||||||
import { type IOOBData } from "../../stores/ThreepidInviteStore";
|
|
||||||
import { awaitRoomDownSync } from "../../utils/RoomUpgrade";
|
import { awaitRoomDownSync } from "../../utils/RoomUpgrade";
|
||||||
import { type ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
|
import { type ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
|
||||||
import { type JoinRoomReadyPayload } from "../../dispatcher/payloads/JoinRoomReadyPayload";
|
import { type JoinRoomReadyPayload } from "../../dispatcher/payloads/JoinRoomReadyPayload";
|
||||||
@@ -400,7 +399,7 @@ export const showRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st
|
|||||||
// XXX: This logic is duplicated from the JS SDK which would normally decide what the name is.
|
// XXX: This logic is duplicated from the JS SDK which would normally decide what the name is.
|
||||||
name: room?.name || roomAlias || _t("common|unnamed_room"),
|
name: room?.name || roomAlias || _t("common|unnamed_room"),
|
||||||
roomType,
|
roomType,
|
||||||
} as IOOBData,
|
},
|
||||||
metricsTrigger: "RoomDirectory",
|
metricsTrigger: "RoomDirectory",
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -617,7 +617,7 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||||||
|
|
||||||
if (showSetup) {
|
if (showSetup) {
|
||||||
phase =
|
phase =
|
||||||
this.props.justCreatedOpts!.createOpts?.preset === Preset.PublicChat
|
this.props.justCreatedOpts.createOpts?.preset === Preset.PublicChat
|
||||||
? Phase.PublicCreateRooms
|
? Phase.PublicCreateRooms
|
||||||
: Phase.PrivateScope;
|
: Phase.PrivateScope;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export const ThreadPanelHeader: React.FC<{
|
|||||||
}> = ({ filterOption, setFilterOption }) => {
|
}> = ({ filterOption, setFilterOption }) => {
|
||||||
const mxClient = useMatrixClientContext();
|
const mxClient = useMatrixClientContext();
|
||||||
const roomContext = useScopedRoomContext("room");
|
const roomContext = useScopedRoomContext("room");
|
||||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu<HTMLElement>();
|
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
||||||
const options: readonly ThreadPanelHeaderOption[] = [
|
const options: readonly ThreadPanelHeaderOption[] = [
|
||||||
{
|
{
|
||||||
label: _t("threads|all_threads"),
|
label: _t("threads|all_threads"),
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||||||
this.timelinePanel.current?.refreshTimeline(this.props.initialEvent?.getId());
|
this.timelinePanel.current?.refreshTimeline(this.props.initialEvent?.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupThreadListeners(thread?: Thread | undefined, oldThread?: Thread | undefined): void {
|
private setupThreadListeners(thread?: Thread, oldThread?: Thread): void {
|
||||||
if (oldThread) {
|
if (oldThread) {
|
||||||
this.state.thread?.off(ThreadEvent.NewReply, this.updateThreadRelation);
|
this.state.thread?.off(ThreadEvent.NewReply, this.updateThreadRelation);
|
||||||
this.props.room.off(RoomEvent.LocalEchoUpdated, this.updateThreadRelation);
|
this.props.room.off(RoomEvent.LocalEchoUpdated, this.updateThreadRelation);
|
||||||
|
|||||||
@@ -1532,6 +1532,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||||||
description,
|
description,
|
||||||
});
|
});
|
||||||
if (onFinished) {
|
if (onFinished) {
|
||||||
|
// oxlint-disable-next-line promise/no-promise-in-callback
|
||||||
finished.then(onFinished);
|
finished.then(onFinished);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export default class UploadBar extends React.PureComponent<IProps, IState> {
|
|||||||
|
|
||||||
public componentWillUnmount(): void {
|
public componentWillUnmount(): void {
|
||||||
this.unmounted = true;
|
this.unmounted = true;
|
||||||
dis.unregister(this.dispatcherRef!);
|
dis.unregister(this.dispatcherRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getUploadsInRoom(): RoomUpload[] {
|
private getUploadsInRoom(): RoomUpload[] {
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
|
|||||||
homeserver={this.props.serverConfig.hsName}
|
homeserver={this.props.serverConfig.hsName}
|
||||||
loading={this.state.phase === Phase.SendingEmail}
|
loading={this.state.phase === Phase.SendingEmail}
|
||||||
onInputChanged={this.onInputChanged}
|
onInputChanged={this.onInputChanged}
|
||||||
onLoginClick={this.props.onLoginClick!} // set by default props
|
onLoginClick={this.props.onLoginClick} // set by default props
|
||||||
onSubmitForm={this.onSubmitForm}
|
onSubmitForm={this.onSubmitForm}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export default class LegacySeekBar extends React.PureComponent<IProps, IState> {
|
|||||||
this.props.playback.skipTo(Number(ev.target.value) * this.props.playback.durationSeconds);
|
this.props.playback.skipTo(Number(ev.target.value) * this.props.playback.durationSeconds);
|
||||||
};
|
};
|
||||||
|
|
||||||
private onMouseDown = (event: React.MouseEvent<Element, MouseEvent>): void => {
|
private onMouseDown = (event: React.MouseEvent): void => {
|
||||||
// do not propagate mouse down events, because these should be handled by the seekbar
|
// do not propagate mouse down events, because these should be handled by the seekbar
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -286,9 +286,7 @@ export default class LoginWithQR extends React.Component<Props, IState> {
|
|||||||
} catch (e: RendezvousError | unknown) {
|
} catch (e: RendezvousError | unknown) {
|
||||||
if (abortController.signal.aborted) return;
|
if (abortController.signal.aborted) return;
|
||||||
logger.error("Error whilst approving login", e);
|
logger.error("Error whilst approving login", e);
|
||||||
await rendezvous.cancel(
|
await rendezvous.cancel(e instanceof RendezvousError ? e.code : ClientRendezvousFailureReason.Unknown);
|
||||||
e instanceof RendezvousError ? (e.code as MSC4108FailureReason) : ClientRendezvousFailureReason.Unknown,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ export default class BugReportDialog extends React.Component<BugReportDialogProp
|
|||||||
this.setState({
|
this.setState({
|
||||||
downloadBusy: false,
|
downloadBusy: false,
|
||||||
downloadProgress:
|
downloadProgress:
|
||||||
_t("bug_reporting|failed_download_logs") + `${err instanceof Error ? err.message : ""}`,
|
_t("bug_reporting|failed_download_logs") + (err instanceof Error ? err.message : ""),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ export default class ChangelogDialog extends React.Component<IProps, State> {
|
|||||||
msg: this.state[repo],
|
msg: this.state[repo],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
content = (this.state[repo] as Commit[]).map(this.elementsForCommit);
|
content = this.state[repo].map(this.elementsForCommit);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key={repo}>
|
<div key={repo}>
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
|
|||||||
className="mx_ExportDialog_attachments-checkbox"
|
className="mx_ExportDialog_attachments-checkbox"
|
||||||
id="include-attachments"
|
id="include-attachments"
|
||||||
checked={includeAttachments}
|
checked={includeAttachments}
|
||||||
onChange={(e) => setAttachments((e.target as HTMLInputElement).checked)}
|
onChange={(e) => setAttachments(e.target.checked)}
|
||||||
>
|
>
|
||||||
{_t("export_chat|include_attachments")}
|
{_t("export_chat|include_attachments")}
|
||||||
</StyledCheckbox>
|
</StyledCheckbox>
|
||||||
|
|||||||
@@ -78,10 +78,7 @@ const GenericFeatureFeedbackDialog: React.FC<IProps> = ({
|
|||||||
}}
|
}}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
/>
|
/>
|
||||||
<StyledCheckbox
|
<StyledCheckbox checked={canContact} onChange={(e) => setCanContact(e.target.checked)}>
|
||||||
checked={canContact}
|
|
||||||
onChange={(e) => setCanContact((e.target as HTMLInputElement).checked)}
|
|
||||||
>
|
|
||||||
{_t("feedback|can_contact_label")}
|
{_t("feedback|can_contact_label")}
|
||||||
</StyledCheckbox>
|
</StyledCheckbox>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|||||||
@@ -323,10 +323,10 @@ describe("InviteDialog", () => {
|
|||||||
|
|
||||||
const input = screen.getByTestId("invite-dialog-input");
|
const input = screen.getByTestId("invite-dialog-input");
|
||||||
input.focus();
|
input.focus();
|
||||||
await userEvent.paste(`${bobbob}`);
|
await userEvent.paste(bobbob);
|
||||||
|
|
||||||
await screen.findAllByText(bobId);
|
await screen.findAllByText(bobId);
|
||||||
expect(input).toHaveValue(`${bobbob}`);
|
expect(input).toHaveValue(bobbob);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow to invite multiple emails to a room", async () => {
|
it("should allow to invite multiple emails to a room", async () => {
|
||||||
@@ -409,9 +409,9 @@ describe("InviteDialog", () => {
|
|||||||
|
|
||||||
const input = screen.getByTestId("invite-dialog-input");
|
const input = screen.getByTestId("invite-dialog-input");
|
||||||
input.focus();
|
input.focus();
|
||||||
await userEvent.paste(`${bobId}`);
|
await userEvent.paste(bobId);
|
||||||
await userEvent.paste(`${bobId}`);
|
await userEvent.paste(bobId);
|
||||||
await userEvent.paste(`${bobId}`);
|
await userEvent.paste(bobId);
|
||||||
|
|
||||||
expect(input).toHaveValue("");
|
expect(input).toHaveValue("");
|
||||||
await expect(screen.findAllByText(bobId, { selector: "a" })).resolves.toHaveLength(1);
|
await expect(screen.findAllByText(bobId, { selector: "a" })).resolves.toHaveLength(1);
|
||||||
@@ -422,7 +422,7 @@ describe("InviteDialog", () => {
|
|||||||
|
|
||||||
const input = screen.getByTestId("invite-dialog-input");
|
const input = screen.getByTestId("invite-dialog-input");
|
||||||
input.focus();
|
input.focus();
|
||||||
await userEvent.keyboard(`${aliceId}`);
|
await userEvent.keyboard(aliceId);
|
||||||
|
|
||||||
const btn = await screen.findByRole("option", { name: aliceId });
|
const btn = await screen.findByRole("option", { name: aliceId });
|
||||||
fireEvent.click(btn);
|
fireEvent.click(btn);
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export default class ModalWidgetDialog extends React.PureComponent<IProps, IStat
|
|||||||
if (isClose || !this.possibleButtons.includes(ev.detail.data.button)) {
|
if (isClose || !this.possibleButtons.includes(ev.detail.data.button)) {
|
||||||
return this.state.messaging?.transport.reply(ev.detail, {
|
return this.state.messaging?.transport.reply(ev.detail, {
|
||||||
error: { message: "Invalid button" },
|
error: { message: "Invalid button" },
|
||||||
} as IWidgetApiErrorResponseData);
|
} satisfies IWidgetApiErrorResponseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
let buttonIds: ModalButtonID[];
|
let buttonIds: ModalButtonID[];
|
||||||
@@ -129,7 +129,7 @@ export default class ModalWidgetDialog extends React.PureComponent<IProps, IStat
|
|||||||
buttonIds = Array.from(tempSet);
|
buttonIds = Array.from(tempSet);
|
||||||
}
|
}
|
||||||
this.setState({ disabledButtonIds: buttonIds });
|
this.setState({ disabledButtonIds: buttonIds });
|
||||||
this.state.messaging?.transport.reply(ev.detail, {} as IWidgetApiAcknowledgeResponseData);
|
this.state.messaging?.transport.reply(ev.detail, {} satisfies IWidgetApiAcknowledgeResponseData);
|
||||||
};
|
};
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
@@ -207,6 +207,7 @@ export default class ModalWidgetDialog extends React.PureComponent<IProps, IStat
|
|||||||
<iframe
|
<iframe
|
||||||
title={this.widget.name ?? undefined}
|
title={this.widget.name ?? undefined}
|
||||||
ref={this.appFrame}
|
ref={this.appFrame}
|
||||||
|
// oxlint-disable-next-line react/iframe-missing-sandbox
|
||||||
sandbox="allow-forms allow-scripts allow-same-origin"
|
sandbox="allow-forms allow-scripts allow-same-origin"
|
||||||
src={widgetUrl}
|
src={widgetUrl}
|
||||||
onLoad={this.onLoad}
|
onLoad={this.onLoad}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { createRef, type RefObject } from "react";
|
import React, { createRef } from "react";
|
||||||
import { type DialogContent, type DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent";
|
import { type DialogContent, type DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { type ModuleApi } from "@matrix-org/react-sdk-module-api/lib/ModuleApi";
|
import { type ModuleApi } from "@matrix-org/react-sdk-module-api/lib/ModuleApi";
|
||||||
@@ -75,10 +75,6 @@ export class ModuleUiDialog<
|
|||||||
} as unknown as P;
|
} as unknown as P;
|
||||||
|
|
||||||
// XXX: we have to fudge the types here a little as the react-sdk-module-api lacks React 19 support
|
// XXX: we have to fudge the types here a little as the react-sdk-module-api lacks React 19 support
|
||||||
return (
|
return <div className="mx_ModuleUiDialog">{this.props.contentFactory(contentProps, this.contentRef)}</div>;
|
||||||
<div className="mx_ModuleUiDialog">
|
|
||||||
{this.props.contentFactory(contentProps, this.contentRef as RefObject<C>)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export class DMRoomTile extends React.PureComponent<IDMRoomTileProps> {
|
|||||||
<BaseAvatar
|
<BaseAvatar
|
||||||
url={
|
url={
|
||||||
this.props.member.getMxcAvatarUrl()
|
this.props.member.getMxcAvatarUrl()
|
||||||
? mediaFromMxc(this.props.member.getMxcAvatarUrl()!).getSquareThumbnailHttp(
|
? mediaFromMxc(this.props.member.getMxcAvatarUrl()).getSquareThumbnailHttp(
|
||||||
parseInt(avatarSize, 10),
|
parseInt(avatarSize, 10),
|
||||||
)
|
)
|
||||||
: null
|
: null
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { Tooltip } from "@vector-im/compound-web";
|
|||||||
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
|
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
|
||||||
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
|
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
|
||||||
|
|
||||||
export type ButtonEvent = React.MouseEvent<Element> | React.KeyboardEvent<Element> | React.FormEvent<Element>;
|
export type ButtonEvent = React.MouseEvent | React.KeyboardEvent | React.FormEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The kind of button, similar to how Bootstrap works.
|
* The kind of button, similar to how Bootstrap works.
|
||||||
|
|||||||
@@ -306,8 +306,8 @@ export default class EventListSummary extends React.Component<Props, State> {
|
|||||||
|
|
||||||
let transition = t;
|
let transition = t;
|
||||||
|
|
||||||
if (i < transitions.length - 1 && modMap[t] && modMap[t]!.after === t2) {
|
if (i < transitions.length - 1 && modMap[t] && modMap[t].after === t2) {
|
||||||
transition = modMap[t]!.newTransition;
|
transition = modMap[t].newTransition;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ export default class ImageView extends React.Component<IProps, IState> {
|
|||||||
|
|
||||||
let info: JSX.Element | undefined;
|
let info: JSX.Element | undefined;
|
||||||
if (showEventMeta) {
|
if (showEventMeta) {
|
||||||
const mxEvent = this.props.mxEvent!;
|
const mxEvent = this.props.mxEvent;
|
||||||
const showTwelveHour = SettingsStore.getValue("showTwelveHourTimestamps");
|
const showTwelveHour = SettingsStore.getValue("showTwelveHourTimestamps");
|
||||||
let permalink = "#";
|
let permalink = "#";
|
||||||
if (this.props.permalinkCreator) {
|
if (this.props.permalinkCreator) {
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ const MapComponent: React.FC<MapProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { map, bodyId } = useMapWithStyle({ centerGeoUri, onError, id, interactive, bounds, allowGeolocate });
|
const { map, bodyId } = useMapWithStyle({ centerGeoUri, onError, id, interactive, bounds, allowGeolocate });
|
||||||
|
|
||||||
const onMapClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>): void => {
|
const onMapClick = (event: React.MouseEvent<HTMLDivElement>): void => {
|
||||||
// Eat click events when clicking the attribution button
|
// Eat click events when clicking the attribution button
|
||||||
const target = event.target as Element;
|
const target = event.target as Element;
|
||||||
if (target.classList.contains("maplibregl-ctrl-attrib-button")) {
|
if (target.classList.contains("maplibregl-ctrl-attrib-button")) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const OptionalTooltip: React.FC<{
|
|||||||
|
|
||||||
const show = (): void => setIsVisible(true);
|
const show = (): void => setIsVisible(true);
|
||||||
const hide = (): void => setIsVisible(false);
|
const hide = (): void => setIsVisible(false);
|
||||||
const toggleVisibility = (e: React.MouseEvent<HTMLDivElement, MouseEvent>): void => {
|
const toggleVisibility = (e: React.MouseEvent<HTMLDivElement>): void => {
|
||||||
// stop map from zooming in on click
|
// stop map from zooming in on click
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setIsVisible(!isVisible);
|
setIsVisible(!isVisible);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { type Media, mediaFromContent } from "../../../customisations/Media";
|
|||||||
import { BLURHASH_FIELD, createThumbnail } from "../../../utils/image-media";
|
import { BLURHASH_FIELD, createThumbnail } from "../../../utils/image-media";
|
||||||
import ImageView from "../elements/ImageView";
|
import ImageView from "../elements/ImageView";
|
||||||
import { type IBodyProps } from "./IBodyProps";
|
import { type IBodyProps } from "./IBodyProps";
|
||||||
import { type ImageSize, suggestedSize as suggestedImageSize } from "../../../settings/enums/ImageSize";
|
import { suggestedSize as suggestedImageSize } from "../../../settings/enums/ImageSize";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
||||||
import { blobIsAnimated, mayBeAnimated } from "../../../utils/Image";
|
import { blobIsAnimated, mayBeAnimated } from "../../../utils/Image";
|
||||||
@@ -409,7 +409,7 @@ export class ImageBodyBaseInner extends React.Component<ImageBodyBaseProps, ISta
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { w: maxWidth, h: maxHeight } = suggestedImageSize(
|
const { w: maxWidth, h: maxHeight } = suggestedImageSize(
|
||||||
SettingsStore.getValue("Images.size") as ImageSize,
|
SettingsStore.getValue("Images.size"),
|
||||||
{ w: infoWidth, h: infoHeight },
|
{ w: infoWidth, h: infoHeight },
|
||||||
forcedHeight ?? this.props.maxImageHeight,
|
forcedHeight ?? this.props.maxImageHeight,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -409,8 +409,8 @@ export function allVotes(voteRelations: Relations): Array<UserVote> {
|
|||||||
*/
|
*/
|
||||||
export function collectUserVotes(
|
export function collectUserVotes(
|
||||||
userResponses: Array<UserVote>,
|
userResponses: Array<UserVote>,
|
||||||
userId?: string | null | undefined,
|
userId?: string | null,
|
||||||
selected?: string | null | undefined,
|
selected?: string | null,
|
||||||
): Map<string, UserVote> {
|
): Map<string, UserVote> {
|
||||||
const userVotes: Map<string, UserVote> = new Map();
|
const userVotes: Map<string, UserVote> = new Map();
|
||||||
|
|
||||||
|
|||||||
@@ -129,13 +129,13 @@ export const PollHistoryList: React.FC<PollHistoryListProps> = ({
|
|||||||
{pollStartEvents.map((pollStartEvent) =>
|
{pollStartEvents.map((pollStartEvent) =>
|
||||||
filter === "ACTIVE" ? (
|
filter === "ACTIVE" ? (
|
||||||
<PollListItem
|
<PollListItem
|
||||||
key={pollStartEvent.getId()!}
|
key={pollStartEvent.getId()}
|
||||||
event={pollStartEvent}
|
event={pollStartEvent}
|
||||||
onClick={() => onItemClick(pollStartEvent.getId()!)}
|
onClick={() => onItemClick(pollStartEvent.getId()!)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<PollListItemEnded
|
<PollListItemEnded
|
||||||
key={pollStartEvent.getId()!}
|
key={pollStartEvent.getId()}
|
||||||
event={pollStartEvent}
|
event={pollStartEvent}
|
||||||
poll={polls.get(pollStartEvent.getId()!)!}
|
poll={polls.get(pollStartEvent.getId()!)!}
|
||||||
onClick={() => onItemClick(pollStartEvent.getId()!)}
|
onClick={() => onItemClick(pollStartEvent.getId()!)}
|
||||||
|
|||||||
@@ -195,14 +195,14 @@ const UserInfo: React.FC<IProps> = ({ user, room, onClose, phase = RightPanelPha
|
|||||||
let content: JSX.Element | undefined;
|
let content: JSX.Element | undefined;
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case RightPanelPhases.MemberInfo:
|
case RightPanelPhases.MemberInfo:
|
||||||
content = <UserInfoBasicView room={room as Room} member={member as User} />;
|
content = <UserInfoBasicView room={room as Room} member={member} />;
|
||||||
break;
|
break;
|
||||||
case RightPanelPhases.EncryptionPanel:
|
case RightPanelPhases.EncryptionPanel:
|
||||||
classes.push("mx_UserInfo_smallAvatar");
|
classes.push("mx_UserInfo_smallAvatar");
|
||||||
content = (
|
content = (
|
||||||
<EncryptionPanel
|
<EncryptionPanel
|
||||||
{...(props as React.ComponentProps<typeof EncryptionPanel>)}
|
{...(props as React.ComponentProps<typeof EncryptionPanel>)}
|
||||||
member={member as User | RoomMember}
|
member={member}
|
||||||
onClose={onEncryptionPanelClose}
|
onClose={onEncryptionPanelClose}
|
||||||
isRoomEncrypted={Boolean(isRoomEncrypted)}
|
isRoomEncrypted={Boolean(isRoomEncrypted)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -240,11 +240,11 @@ export default class AliasSettings extends React.Component<IProps, IState> {
|
|||||||
.createAlias(alias, this.props.roomId)
|
.createAlias(alias, this.props.roomId)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
localAliases: this.state.localAliases.concat(alias!),
|
localAliases: this.state.localAliases.concat(alias),
|
||||||
newAlias: undefined,
|
newAlias: undefined,
|
||||||
});
|
});
|
||||||
if (!this.state.canonicalAlias) {
|
if (!this.state.canonicalAlias) {
|
||||||
this.changeCanonicalAlias(alias!);
|
this.changeCanonicalAlias(alias);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
|
|
||||||
import React, { type AriaRole, useContext } from "react";
|
import React, { type AriaRole, useContext } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Resizable, type Size } from "re-resizable";
|
import { Resizable } from "re-resizable";
|
||||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||||
import { type IWidget } from "matrix-widget-api";
|
import { type IWidget } from "matrix-widget-api";
|
||||||
import { clamp, percentageOf, percentageWithin } from "@element-hq/web-shared-components";
|
import { clamp, percentageOf, percentageWithin } from "@element-hq/web-shared-components";
|
||||||
@@ -340,7 +340,7 @@ const PersistentVResizer: React.FC<IPersistentResizerProps> = ({
|
|||||||
<Resizable
|
<Resizable
|
||||||
// types do not support undefined height/width
|
// types do not support undefined height/width
|
||||||
// but resizable code checks specifically for undefined on Size prop
|
// but resizable code checks specifically for undefined on Size prop
|
||||||
size={{ height: Math.min(defaultHeight, maxHeight), width: undefined } as unknown as Size}
|
size={{ height: Math.min(defaultHeight, maxHeight), width: undefined }}
|
||||||
minHeight={minHeight}
|
minHeight={minHeight}
|
||||||
maxHeight={maxHeight}
|
maxHeight={maxHeight}
|
||||||
onResizeStart={() => {
|
onResizeStart={() => {
|
||||||
@@ -350,7 +350,7 @@ const PersistentVResizer: React.FC<IPersistentResizerProps> = ({
|
|||||||
resizeNotifier.notifyTimelineHeightChanged();
|
resizeNotifier.notifyTimelineHeightChanged();
|
||||||
}}
|
}}
|
||||||
onResizeStop={(e, dir, ref, d) => {
|
onResizeStop={(e, dir, ref, d) => {
|
||||||
let newHeight = defaultHeight! + d.height;
|
let newHeight = defaultHeight + d.height;
|
||||||
newHeight = percentageOf(newHeight, minHeight, maxHeight) * 100;
|
newHeight = percentageOf(newHeight, minHeight, maxHeight) * 100;
|
||||||
|
|
||||||
sdkContext.widgetLayoutStore.setContainerHeight(room, "top", newHeight);
|
sdkContext.widgetLayoutStore.setContainerHeight(room, "top", newHeight);
|
||||||
|
|||||||
@@ -668,7 +668,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||||||
|
|
||||||
private readonly onFocusWithin = (event: FocusEvent<HTMLElement>): void => {
|
private readonly onFocusWithin = (event: FocusEvent<HTMLElement>): void => {
|
||||||
// Show the action toolbar for keyboard-visible focus, with what-input as a fallback signal.
|
// Show the action toolbar for keyboard-visible focus, with what-input as a fallback signal.
|
||||||
const target = event.target as HTMLElement;
|
const target = event.target;
|
||||||
const showActionBarFromFocus =
|
const showActionBarFromFocus =
|
||||||
target.matches(":focus-visible") || document.body.dataset["data-whatinput"] === "keyboard";
|
target.matches(":focus-visible") || document.body.dataset["data-whatinput"] === "keyboard";
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ const NewRoomIntro: React.FC = () => {
|
|||||||
let parentSpace: Room | undefined;
|
let parentSpace: Room | undefined;
|
||||||
if (
|
if (
|
||||||
sdkContext.spaceStore.activeSpaceRoom?.canInvite(cli.getSafeUserId()) &&
|
sdkContext.spaceStore.activeSpaceRoom?.canInvite(cli.getSafeUserId()) &&
|
||||||
sdkContext.spaceStore.isRoomInSpace(sdkContext.spaceStore.activeSpace!, room.roomId)
|
sdkContext.spaceStore.isRoomInSpace(sdkContext.spaceStore.activeSpace, room.roomId)
|
||||||
) {
|
) {
|
||||||
parentSpace = sdkContext.spaceStore.activeSpaceRoom;
|
parentSpace = sdkContext.spaceStore.activeSpaceRoom;
|
||||||
}
|
}
|
||||||
@@ -192,7 +192,7 @@ const NewRoomIntro: React.FC = () => {
|
|||||||
className="mx_NewRoomIntro_inviteButton"
|
className="mx_NewRoomIntro_inviteButton"
|
||||||
kind="primary"
|
kind="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
showSpaceInvite(parentSpace!);
|
showSpaceInvite(parentSpace);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<UserAddIcon />
|
<UserAddIcon />
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export const RoomListPanel: React.FC<RoomListPanelProps> = ({ activeSpace }) =>
|
|||||||
const [focusedElement, setFocusedElement] = useState<Element | null>(null);
|
const [focusedElement, setFocusedElement] = useState<Element | null>(null);
|
||||||
|
|
||||||
const onFocus = useCallback((ev: React.FocusEvent): void => {
|
const onFocus = useCallback((ev: React.FocusEvent): void => {
|
||||||
setFocusedElement(ev.target as Element);
|
setFocusedElement(ev.target);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onBlur = useCallback((): void => {
|
const onBlur = useCallback((): void => {
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ class RoomPreviewBar extends React.Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
return MessageCase.Invite;
|
return MessageCase.Invite;
|
||||||
} else if (this.props.error) {
|
} else if (this.props.error) {
|
||||||
if ((this.props.error as MatrixError).errcode == "M_NOT_FOUND") {
|
if (this.props.error.errcode === "M_NOT_FOUND") {
|
||||||
return MessageCase.RoomNotFound;
|
return MessageCase.RoomNotFound;
|
||||||
} else {
|
} else {
|
||||||
return MessageCase.OtherError;
|
return MessageCase.OtherError;
|
||||||
|
|||||||
@@ -610,7 +610,7 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
|
|||||||
// Fallback to internal onPaste handler
|
// Fallback to internal onPaste handler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const imgSrc = imgDoc!.querySelector("img")!.src;
|
const imgSrc = imgDoc.querySelector("img")!.src;
|
||||||
|
|
||||||
fetch(imgSrc).then(
|
fetch(imgSrc).then(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export default class WhoIsTypingTile extends React.Component<IProps, IState> {
|
|||||||
client.removeListener(RoomMemberEvent.Typing, this.onRoomMemberTyping);
|
client.removeListener(RoomMemberEvent.Typing, this.onRoomMemberTyping);
|
||||||
client.removeListener(RoomEvent.Timeline, this.onRoomTimeline);
|
client.removeListener(RoomEvent.Timeline, this.onRoomTimeline);
|
||||||
}
|
}
|
||||||
Object.values(this.state.delayedStopTypingTimers).forEach((t) => (t as Timer).abort());
|
Object.values(this.state.delayedStopTypingTimers).forEach((t) => t.abort());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static isVisible(state: IState): boolean {
|
private static isVisible(state: IState): boolean {
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ export async function sendMessage(
|
|||||||
|
|
||||||
const prom = doMaybeLocalRoomAction(
|
const prom = doMaybeLocalRoomAction(
|
||||||
roomId,
|
roomId,
|
||||||
(actualRoomId: string) => mxClient.sendMessage(actualRoomId, threadId, content!),
|
(actualRoomId: string) => mxClient.sendMessage(actualRoomId, threadId, content),
|
||||||
mxClient,
|
mxClient,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ const ExistingThreepid: React.FC<ExistingThreepidProps> = ({ mode, threepid, onC
|
|||||||
threepid.medium === "email"
|
threepid.medium === "email"
|
||||||
? _t("settings|general|error_revoke_email_discovery")
|
? _t("settings|general|error_revoke_email_discovery")
|
||||||
: _t("settings|general|error_revoke_msisdn_discovery"),
|
: _t("settings|general|error_revoke_msisdn_discovery"),
|
||||||
}).then();
|
});
|
||||||
},
|
},
|
||||||
[changeBinding, threepid.medium],
|
[changeBinding, threepid.medium],
|
||||||
);
|
);
|
||||||
@@ -143,7 +143,7 @@ const ExistingThreepid: React.FC<ExistingThreepidProps> = ({ mode, threepid, onC
|
|||||||
threepid.medium === "email"
|
threepid.medium === "email"
|
||||||
? _t("settings|general|error_share_email_discovery")
|
? _t("settings|general|error_share_email_discovery")
|
||||||
: _t("settings|general|error_share_msisdn_discovery"),
|
: _t("settings|general|error_share_msisdn_discovery"),
|
||||||
}).then();
|
});
|
||||||
},
|
},
|
||||||
[changeBinding, threepid.medium],
|
[changeBinding, threepid.medium],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ export default class IntegrationManager extends React.Component<IProps, IState>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// oxlint-disable-next-line react/iframe-missing-sandbox
|
||||||
return <iframe title={_t("common|integration_manager")} src={this.props.url} onError={this.onError} />;
|
return <iframe title={_t("common|integration_manager")} src={this.props.url} onError={this.onError} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ export default class Notifications extends React.PureComponent<EmptyObject, ISta
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async refreshRules(): Promise<Partial<IState>> {
|
private async refreshRules(): Promise<Partial<IState>> {
|
||||||
const ruleSets = await MatrixClientPeg.safeGet().getPushRules()!;
|
const ruleSets = await MatrixClientPeg.safeGet().getPushRules();
|
||||||
const categories: Record<string, RuleClass> = {
|
const categories: Record<string, RuleClass> = {
|
||||||
[RuleId.Master]: RuleClass.Master,
|
[RuleId.Master]: RuleClass.Master,
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ export default class Notifications extends React.PureComponent<EmptyObject, ISta
|
|||||||
for (const rule of defaultRules[category]) {
|
for (const rule of defaultRules[category]) {
|
||||||
const definition: VectorPushRuleDefinition = VectorPushRulesDefinitions[rule.rule_id];
|
const definition: VectorPushRuleDefinition = VectorPushRulesDefinitions[rule.rule_id];
|
||||||
const vectorState = definition.ruleToVectorState(rule)!;
|
const vectorState = definition.ruleToVectorState(rule)!;
|
||||||
preparedNewState.vectorPushRules[category]!.push({
|
preparedNewState.vectorPushRules[category].push({
|
||||||
ruleId: rule.rule_id,
|
ruleId: rule.rule_id,
|
||||||
rule,
|
rule,
|
||||||
vectorState,
|
vectorState,
|
||||||
@@ -363,7 +363,7 @@ export default class Notifications extends React.PureComponent<EmptyObject, ISta
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Quickly sort the rules for display purposes
|
// Quickly sort the rules for display purposes
|
||||||
preparedNewState.vectorPushRules[category]!.sort((a, b) => {
|
preparedNewState.vectorPushRules[category].sort((a, b) => {
|
||||||
let idxA = RULE_DISPLAY_ORDER.indexOf(a.ruleId);
|
let idxA = RULE_DISPLAY_ORDER.indexOf(a.ruleId);
|
||||||
let idxB = RULE_DISPLAY_ORDER.indexOf(b.ruleId);
|
let idxB = RULE_DISPLAY_ORDER.indexOf(b.ruleId);
|
||||||
|
|
||||||
@@ -375,7 +375,7 @@ export default class Notifications extends React.PureComponent<EmptyObject, ISta
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (category === KEYWORD_RULE_CATEGORY) {
|
if (category === KEYWORD_RULE_CATEGORY) {
|
||||||
preparedNewState.vectorPushRules[category]!.push({
|
preparedNewState.vectorPushRules[category].push({
|
||||||
ruleId: KEYWORD_RULE_ID,
|
ruleId: KEYWORD_RULE_ID,
|
||||||
description: _t("settings|notifications|messages_containing_keywords"),
|
description: _t("settings|notifications|messages_containing_keywords"),
|
||||||
vectorState: preparedNewState.vectorKeywordRuleInfo.vectorState,
|
vectorState: preparedNewState.vectorKeywordRuleInfo.vectorState,
|
||||||
|
|||||||
@@ -68,15 +68,7 @@ export const UserPersonalInfoSettings: React.FC<UserPersonalInfoSettingsProps> =
|
|||||||
}, [client]);
|
}, [client]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateThreepids().then();
|
updateThreepids();
|
||||||
}, [updateThreepids]);
|
|
||||||
|
|
||||||
const onEmailsChange = useCallback(() => {
|
|
||||||
updateThreepids().then();
|
|
||||||
}, [updateThreepids]);
|
|
||||||
|
|
||||||
const onMsisdnsChange = useCallback(() => {
|
|
||||||
updateThreepids().then();
|
|
||||||
}, [updateThreepids]);
|
}, [updateThreepids]);
|
||||||
|
|
||||||
if (!SettingsStore.getValue(UIFeature.ThirdPartyID)) return null;
|
if (!SettingsStore.getValue(UIFeature.ThirdPartyID)) return null;
|
||||||
@@ -96,7 +88,7 @@ export const UserPersonalInfoSettings: React.FC<UserPersonalInfoSettingsProps> =
|
|||||||
mode="hs"
|
mode="hs"
|
||||||
medium={ThreepidMedium.Email}
|
medium={ThreepidMedium.Email}
|
||||||
threepids={emails!}
|
threepids={emails!}
|
||||||
onChange={onEmailsChange}
|
onChange={updateThreepids}
|
||||||
disabled={!canMake3pidChanges}
|
disabled={!canMake3pidChanges}
|
||||||
isLoading={loadingState === "loading"}
|
isLoading={loadingState === "loading"}
|
||||||
/>
|
/>
|
||||||
@@ -116,7 +108,7 @@ export const UserPersonalInfoSettings: React.FC<UserPersonalInfoSettingsProps> =
|
|||||||
mode="hs"
|
mode="hs"
|
||||||
medium={ThreepidMedium.Phone}
|
medium={ThreepidMedium.Phone}
|
||||||
threepids={phoneNumbers!}
|
threepids={phoneNumbers!}
|
||||||
onChange={onMsisdnsChange}
|
onChange={updateThreepids}
|
||||||
disabled={!canMake3pidChanges}
|
disabled={!canMake3pidChanges}
|
||||||
isLoading={loadingState === "loading"}
|
isLoading={loadingState === "loading"}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ export const FilteredDeviceList = ({
|
|||||||
];
|
];
|
||||||
|
|
||||||
const onFilterOptionChange = (filterId: DeviceFilterKey): void => {
|
const onFilterOptionChange = (filterId: DeviceFilterKey): void => {
|
||||||
onFilterChange(filterId === ALL_FILTER_ID ? undefined : (filterId as FilterVariation));
|
onFilterChange(filterId === ALL_FILTER_ID ? undefined : filterId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isAllSelected = selectedDeviceIds.length >= sortedDevices.length;
|
const isAllSelected = selectedDeviceIds.length >= sortedDevices.length;
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export const DiscoverySettings: React.FC = () => {
|
|||||||
if (payload.action === "id_server_changed") {
|
if (payload.action === "id_server_changed") {
|
||||||
setIdServerName(abbreviateUrl(client.getIdentityServerUrl()));
|
setIdServerName(abbreviateUrl(client.getIdentityServerUrl()));
|
||||||
|
|
||||||
getThreepidState().then();
|
getThreepidState();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[client, getThreepidState],
|
[client, getThreepidState],
|
||||||
@@ -113,9 +113,7 @@ export const DiscoverySettings: React.FC = () => {
|
|||||||
// User accepted all terms
|
// User accepted all terms
|
||||||
setMustAgreeToTerms(false);
|
setMustAgreeToTerms(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.warn(
|
logger.warn(`Unable to reach identity server at ${idServerUrl} to check for terms in Settings`);
|
||||||
`Unable to reach identity server at ${idServerUrl} to check ` + `for terms in Settings`,
|
|
||||||
);
|
|
||||||
logger.warn(e);
|
logger.warn(e);
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export default function NotificationSettings2(): JSX.Element {
|
|||||||
<SettingsBanner
|
<SettingsBanner
|
||||||
icon={<img src={NewAndImprovedIcon} alt="" width={12} />}
|
icon={<img src={NewAndImprovedIcon} alt="" width={12} />}
|
||||||
action={_t("action|proceed")}
|
action={_t("action|proceed")}
|
||||||
onAction={() => reconcile(model!)}
|
onAction={() => reconcile(model)}
|
||||||
>
|
>
|
||||||
{_t(
|
{_t(
|
||||||
"settings|notifications|labs_notice_prompt",
|
"settings|notifications|labs_notice_prompt",
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ interface IProps {
|
|||||||
pipMode?: boolean;
|
pipMode?: boolean;
|
||||||
|
|
||||||
// Used for dragging the PiP LegacyCallView
|
// Used for dragging the PiP LegacyCallView
|
||||||
onMouseDownOnHeader?: (event: React.MouseEvent<Element, MouseEvent>) => void;
|
onMouseDownOnHeader?: (event: React.MouseEvent) => void;
|
||||||
|
|
||||||
showApps?: boolean;
|
showApps?: boolean;
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const SecondaryCallInfo: React.FC<ISecondaryCallInfoProps> = ({ callRoom }) => {
|
|||||||
interface LegacyCallViewHeaderProps {
|
interface LegacyCallViewHeaderProps {
|
||||||
pipMode?: boolean;
|
pipMode?: boolean;
|
||||||
callRooms: [Room, Room | null];
|
callRooms: [Room, Room | null];
|
||||||
onPipMouseDown?: (event: React.MouseEvent<Element, MouseEvent>) => void;
|
onPipMouseDown?: (event: React.MouseEvent) => void;
|
||||||
onExpand?: () => void;
|
onExpand?: () => void;
|
||||||
onPin?: () => void;
|
onPin?: () => void;
|
||||||
onMaximize?: () => void;
|
onMaximize?: () => void;
|
||||||
|
|||||||
@@ -25,4 +25,4 @@ function getDisplayUserIdentifier(
|
|||||||
// customisation points that make up `IUserIdentifierCustomisations`.
|
// customisation points that make up `IUserIdentifierCustomisations`.
|
||||||
export default {
|
export default {
|
||||||
getDisplayUserIdentifier,
|
getDisplayUserIdentifier,
|
||||||
} as UserIdentifierCustomisations;
|
} satisfies UserIdentifierCustomisations;
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ export function formatRangeAsLink(range: Range, text?: string): void {
|
|||||||
replaceRangeAndMoveCaret(range, newParts, 0);
|
replaceRangeAndMoveCaret(range, newParts, 0);
|
||||||
} else {
|
} else {
|
||||||
// We set offset to -1 here so that the caret lands between the brackets
|
// We set offset to -1 here so that the caret lands between the brackets
|
||||||
replaceRangeAndMoveCaret(range, [partCreator.plain("[" + range.text + "]" + "(" + (text ?? "") + ")")], -1);
|
replaceRangeAndMoveCaret(range, [partCreator.plain(`[${range.text}](${text ?? ""})`)], -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ function reconcileLine(lineContainer: ChildNode, parts: Part[]): void {
|
|||||||
currentNode = isFirst ? lineContainer.firstChild : currentNode!.nextSibling;
|
currentNode = isFirst ? lineContainer.firstChild : currentNode!.nextSibling;
|
||||||
|
|
||||||
if (needsCaretNodeBefore(part, prevPart)) {
|
if (needsCaretNodeBefore(part, prevPart)) {
|
||||||
if (isCaretNode(currentNode as Element)) {
|
if (isCaretNode(currentNode)) {
|
||||||
updateCaretNode(currentNode!);
|
updateCaretNode(currentNode);
|
||||||
currentNode = currentNode!.nextSibling;
|
currentNode = currentNode.nextSibling;
|
||||||
} else {
|
} else {
|
||||||
lineContainer.insertBefore(createCaretNode(), currentNode);
|
lineContainer.insertBefore(createCaretNode(), currentNode);
|
||||||
}
|
}
|
||||||
@@ -106,9 +106,9 @@ function reconcileLine(lineContainer: ChildNode, parts: Part[]): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (needsCaretNodeAfter(part, part === lastPart)) {
|
if (needsCaretNodeAfter(part, part === lastPart)) {
|
||||||
if (isCaretNode(currentNode?.nextSibling as Element)) {
|
if (isCaretNode(currentNode?.nextSibling)) {
|
||||||
currentNode = currentNode!.nextSibling;
|
currentNode = currentNode.nextSibling;
|
||||||
updateCaretNode(currentNode as HTMLElement);
|
updateCaretNode(currentNode);
|
||||||
} else {
|
} else {
|
||||||
const caretNode = createCaretNode();
|
const caretNode = createCaretNode();
|
||||||
insertAfter(currentNode as HTMLElement, caretNode);
|
insertAfter(currentNode as HTMLElement, caretNode);
|
||||||
|
|||||||
@@ -177,9 +177,9 @@ export function textSerialize(model: EditorModel): string {
|
|||||||
case Type.RoomPill:
|
case Type.RoomPill:
|
||||||
// Here we use the resourceId for compatibility with non-rich text clients
|
// Here we use the resourceId for compatibility with non-rich text clients
|
||||||
// See https://github.com/vector-im/element-web/issues/16660
|
// See https://github.com/vector-im/element-web/issues/16660
|
||||||
return text + `${part.resourceId}`;
|
return text + part.resourceId;
|
||||||
case Type.UserPill:
|
case Type.UserPill:
|
||||||
return text + `${part.text}`;
|
return text + part.text;
|
||||||
}
|
}
|
||||||
}, "");
|
}, "");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ export class BadgeOverlayRenderer extends IconRenderer {
|
|||||||
(blob) => {
|
(blob) => {
|
||||||
if (blob) {
|
if (blob) {
|
||||||
resolve(blob.arrayBuffer());
|
resolve(blob.arrayBuffer());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
reject(new Error("Could not render badge overlay as blob"));
|
reject(new Error("Could not render badge overlay as blob"));
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -189,4 +189,5 @@ export function useEventEmitterAsyncState<T, Events extends string, Arguments ex
|
|||||||
/**
|
/**
|
||||||
* Indicates that the callback for `useEventEmitterAsyncState` is not changing the value of the state.
|
* Indicates that the callback for `useEventEmitterAsyncState` is not changing the value of the state.
|
||||||
*/
|
*/
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export class NoChange {}
|
export class NoChange {}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export async function isRoomEncrypted(room: Room, cryptoApi: CryptoApi): Promise
|
|||||||
if (room instanceof LocalRoom) {
|
if (room instanceof LocalRoom) {
|
||||||
// For local room check the state.
|
// For local room check the state.
|
||||||
// The crypto check fails because the room ID is not valid (it is a local id)
|
// The crypto check fails because the room ID is not valid (it is a local id)
|
||||||
return (room as LocalRoom).isEncryptionEnabled();
|
return room.isEncryptionEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
return await cryptoApi.isEncryptionEnabledInRoom(room.roomId);
|
return await cryptoApi.isEncryptionEnabledInRoom(room.roomId);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const useSpaceResults = (space: Room | undefined, query: string): [Hierar
|
|||||||
let unmounted = false;
|
let unmounted = false;
|
||||||
|
|
||||||
(async (): Promise<void> => {
|
(async (): Promise<void> => {
|
||||||
|
// oxlint-disable-next-line no-unmodified-loop-condition
|
||||||
while (hierarchy?.canLoadMore && !unmounted && space === hierarchy.root) {
|
while (hierarchy?.canLoadMore && !unmounted && space === hierarchy.root) {
|
||||||
await hierarchy.load();
|
await hierarchy.load();
|
||||||
if (hierarchy.canLoadMore) hierarchy.load(); // start next load so that the loading attribute is right
|
if (hierarchy.canLoadMore) hierarchy.load(); // start next load so that the loading attribute is right
|
||||||
|
|||||||
@@ -458,6 +458,7 @@ export default class EventIndex extends EventEmitter {
|
|||||||
|
|
||||||
let idle = false;
|
let idle = false;
|
||||||
|
|
||||||
|
// oxlint-disable-next-line no-unmodified-loop-condition
|
||||||
while (!cancelled) {
|
while (!cancelled) {
|
||||||
let sleepTime = SettingsStore.getValueAt(SettingLevel.DEVICE, "crawlerSleepTime");
|
let sleepTime = SettingsStore.getValueAt(SettingLevel.DEVICE, "crawlerSleepTime");
|
||||||
|
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ export abstract class Call extends TypedEventEmitter<CallEvent, CallEventHandler
|
|||||||
// The widget might still be initializing, so wait for it in an async
|
// The widget might still be initializing, so wait for it in an async
|
||||||
// event loop. We need the messaging to be both present and started
|
// event loop. We need the messaging to be both present and started
|
||||||
// (have a connected widget API), so register listeners for both cases.
|
// (have a connected widget API), so register listeners for both cases.
|
||||||
|
// oxlint-disable-next-line no-unmodified-loop-condition
|
||||||
while (!messaging?.widgetApi) {
|
while (!messaging?.widgetApi) {
|
||||||
if (messaging) logger.debug(`Messaging present but not yet started for ${this.widgetUid}`);
|
if (messaging) logger.debug(`Messaging present but not yet started for ${this.widgetUid}`);
|
||||||
else logger.debug(`No messaging yet for ${this.widgetUid}`);
|
else logger.debug(`No messaging yet for ${this.widgetUid}`);
|
||||||
@@ -430,7 +431,7 @@ export class JitsiCall extends Call {
|
|||||||
const event = this.room.currentState.getStateEvents(JitsiCall.MEMBER_EVENT_TYPE, this.client.getUserId()!);
|
const event = this.room.currentState.getStateEvents(JitsiCall.MEMBER_EVENT_TYPE, this.client.getUserId()!);
|
||||||
const content = event?.getContent<JitsiCallMemberContent>();
|
const content = event?.getContent<JitsiCallMemberContent>();
|
||||||
const expiresAt = typeof content?.expires_ts === "number" ? content.expires_ts : -Infinity;
|
const expiresAt = typeof content?.expires_ts === "number" ? content.expires_ts : -Infinity;
|
||||||
const devices = expiresAt > Date.now() && Array.isArray(content?.devices) ? content!.devices : [];
|
const devices = expiresAt > Date.now() && Array.isArray(content?.devices) ? content.devices : [];
|
||||||
const newDevices = fn(devices);
|
const newDevices = fn(devices);
|
||||||
|
|
||||||
if (newDevices !== null) {
|
if (newDevices !== null) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export class ConfigApi implements IConfigApi {
|
|||||||
public get<K extends keyof Config>(key: K): Config[K];
|
public get<K extends keyof Config>(key: K): Config[K];
|
||||||
public get<K extends keyof Config = never>(key?: K): Config | Config[K] {
|
public get<K extends keyof Config = never>(key?: K): Config | Config[K] {
|
||||||
if (key === undefined) {
|
if (key === undefined) {
|
||||||
return SdkConfig.get() as Config;
|
return SdkConfig.get();
|
||||||
}
|
}
|
||||||
return SdkConfig.get(key);
|
return SdkConfig.get(key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ export class ProxiedModuleApi implements ModuleApi {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
homeserverUrl: hsUrl,
|
homeserverUrl: hsUrl,
|
||||||
userId: creds.user_id!,
|
userId: creds.user_id,
|
||||||
deviceId: creds.device_id!,
|
deviceId: creds.device_id!,
|
||||||
accessToken: creds.access_token!,
|
accessToken: creds.access_token!,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export interface IContentRules {
|
|||||||
externalRules: IAnnotatedPushRule[];
|
externalRules: IAnnotatedPushRule[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export class ContentRules {
|
export class ContentRules {
|
||||||
/**
|
/**
|
||||||
* Extract the keyword rules from a list of rules, and parse them
|
* Extract the keyword rules from a list of rules, and parse them
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export interface PushRuleActions {
|
|||||||
highlight?: boolean;
|
highlight?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export class NotificationUtils {
|
export class NotificationUtils {
|
||||||
// Encodes a dictionary of {
|
// Encodes a dictionary of {
|
||||||
// "notify": true/false,
|
// "notify": true/false,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export enum VectorState {
|
|||||||
Loud = "loud",
|
Loud = "loud",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export class PushRuleVectorState {
|
export class PushRuleVectorState {
|
||||||
// Backwards compatibility (things should probably be using the enum above instead)
|
// Backwards compatibility (things should probably be using the enum above instead)
|
||||||
public static OFF = VectorState.Off;
|
public static OFF = VectorState.Off;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { NotificationUtils } from "./NotificationUtils";
|
|||||||
|
|
||||||
const encodeActions = NotificationUtils.encodeActions;
|
const encodeActions = NotificationUtils.encodeActions;
|
||||||
|
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export class StandardActions {
|
export class StandardActions {
|
||||||
public static ACTION_NOTIFY = encodeActions({ notify: true });
|
public static ACTION_NOTIFY = encodeActions({ notify: true });
|
||||||
public static ACTION_NOTIFY_DEFAULT_SOUND = encodeActions({ notify: true, sound: "default" });
|
public static ACTION_NOTIFY_DEFAULT_SOUND = encodeActions({ notify: true, sound: "default" });
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ export class IndexedDBLogStore {
|
|||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
txn.onerror = () => {
|
txn.onerror = () => {
|
||||||
reject(new Error("Failed to delete logs for " + `'${id}' : ${query.error?.message}`));
|
reject(new Error(`Failed to delete logs for '${id}' : ${query.error?.message}`));
|
||||||
};
|
};
|
||||||
// delete last modified entries
|
// delete last modified entries
|
||||||
const lastModStore = txn.objectStore("logslastmod");
|
const lastModStore = txn.objectStore("logslastmod");
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const ambiguousLinkTooltipRenderer: RendererMap = {
|
|||||||
|
|
||||||
const href = anchor.attribs["href"];
|
const href = anchor.attribs["href"];
|
||||||
if (href && href !== getSingleTextContentNode(anchor)) {
|
if (href && href !== getSingleTextContentNode(anchor)) {
|
||||||
let tooltip = href as string;
|
let tooltip = href;
|
||||||
try {
|
try {
|
||||||
tooltip = new URL(href, window.location.href).toString();
|
tooltip = new URL(href, window.location.href).toString();
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ type HandlerMap = Partial<{
|
|||||||
* feature may be reported as disabled even though a user has specifically requested it
|
* feature may be reported as disabled even though a user has specifically requested it
|
||||||
* be enabled).
|
* be enabled).
|
||||||
*/
|
*/
|
||||||
|
// oxlint-disable-next-line typescript/no-extraneous-class
|
||||||
export default class SettingsStore {
|
export default class SettingsStore {
|
||||||
// We support watching settings for changes, and do this by tracking which callbacks have
|
// We support watching settings for changes, and do this by tracking which callbacks have
|
||||||
// been given to us. We end up returning the callbackRef to the caller so they can unsubscribe
|
// been given to us. We end up returning the callbackRef to the caller so they can unsubscribe
|
||||||
@@ -263,7 +264,7 @@ export default class SettingsStore {
|
|||||||
if (roomId === null) {
|
if (roomId === null) {
|
||||||
// Unregister all existing watchers and register the new one
|
// Unregister all existing watchers and register the new one
|
||||||
rooms.forEach((roomId) => {
|
rooms.forEach((roomId) => {
|
||||||
SettingsStore.unwatchSetting(this.monitors.get(settingName)!.get(roomId)!);
|
SettingsStore.unwatchSetting(this.monitors.get(settingName)!.get(roomId));
|
||||||
});
|
});
|
||||||
this.monitors.get(settingName)!.clear();
|
this.monitors.get(settingName)!.clear();
|
||||||
registerWatcher();
|
registerWatcher();
|
||||||
@@ -334,10 +335,10 @@ export default class SettingsStore {
|
|||||||
SettingsStore.isFeature(settingName) &&
|
SettingsStore.isFeature(settingName) &&
|
||||||
SettingsStore.getValueAt(SettingLevel.CONFIG, settingName, null, true, true) !== false
|
SettingsStore.getValueAt(SettingLevel.CONFIG, settingName, null, true, true) !== false
|
||||||
) {
|
) {
|
||||||
const betaInfo = SETTINGS[settingName]!.betaInfo;
|
const betaInfo = SETTINGS[settingName].betaInfo;
|
||||||
if (betaInfo) {
|
if (betaInfo) {
|
||||||
betaInfo.requiresRefresh =
|
betaInfo.requiresRefresh =
|
||||||
betaInfo.requiresRefresh ?? SETTINGS[settingName]!.controller instanceof ReloadOnChangeController;
|
betaInfo.requiresRefresh ?? SETTINGS[settingName].controller instanceof ReloadOnChangeController;
|
||||||
}
|
}
|
||||||
return betaInfo;
|
return betaInfo;
|
||||||
}
|
}
|
||||||
@@ -868,8 +869,7 @@ export default class SettingsStore {
|
|||||||
|
|
||||||
private static getHandler(settingName: SettingKey, level: SettingLevel): SettingsHandler | null {
|
private static getHandler(settingName: SettingKey, level: SettingLevel): SettingsHandler | null {
|
||||||
const handlers = SettingsStore.getHandlers(settingName);
|
const handlers = SettingsStore.getHandlers(settingName);
|
||||||
if (!handlers[level]) return null;
|
return handlers[level] ?? null;
|
||||||
return handlers[level]!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getHandlers(settingName: SettingKey): HandlerMap {
|
private static getHandlers(settingName: SettingKey): HandlerMap {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export default class MediaPreviewConfigController extends MatrixClientBackedCont
|
|||||||
|
|
||||||
// Save an account data fetch if we have all the values.
|
// Save an account data fetch if we have all the values.
|
||||||
if (calculatedConfig.invite_avatars && calculatedConfig.media_previews) {
|
if (calculatedConfig.invite_avatars && calculatedConfig.media_previews) {
|
||||||
return calculatedConfig as MediaPreviewConfig;
|
return calculatedConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're missing some keys.
|
// We're missing some keys.
|
||||||
|
|||||||
@@ -123,4 +123,4 @@ let singletonLifecycleStore: LifecycleStore | null = null;
|
|||||||
if (!singletonLifecycleStore) {
|
if (!singletonLifecycleStore) {
|
||||||
singletonLifecycleStore = new LifecycleStore();
|
singletonLifecycleStore = new LifecycleStore();
|
||||||
}
|
}
|
||||||
export default singletonLifecycleStore!;
|
export default singletonLifecycleStore;
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ export class MemberListStore {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const enablePresenceByHsUrl = SdkConfig.get("enable_presence_by_hs_url");
|
const enablePresenceByHsUrl = SdkConfig.get("enable_presence_by_hs_url");
|
||||||
return enablePresenceByHsUrl?.[this.stores.client!.baseUrl] ?? true;
|
return enablePresenceByHsUrl?.[this.stores.client.baseUrl] ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export class ModalWidgetStore extends AsyncStoreWithClient<IState> {
|
|||||||
/* priority = */ false,
|
/* priority = */ false,
|
||||||
/* static = */ true,
|
/* static = */ true,
|
||||||
);
|
);
|
||||||
this.modalInstance!.finished.then(([success, data]) => {
|
this.modalInstance.finished.then(([success, data]) => {
|
||||||
this.closeModalWidget(sourceWidget, widgetRoomId, success && data ? data : { "m.exited": true });
|
this.closeModalWidget(sourceWidget, widgetRoomId, success && data ? data : { "m.exited": true });
|
||||||
|
|
||||||
this.openSourceWidgetId = null;
|
this.openSourceWidgetId = null;
|
||||||
|
|||||||
@@ -512,6 +512,7 @@ export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
|
|||||||
|
|
||||||
this.stopPollingLocation();
|
this.stopPollingLocation();
|
||||||
// kill live beacons when location permissions are revoked
|
// kill live beacons when location permissions are revoked
|
||||||
|
// oxlint-disable-next-line promise/no-promise-in-callback
|
||||||
await Promise.all(this.liveBeaconIds.map(this.stopBeacon));
|
await Promise.all(this.liveBeaconIds.map(this.stopBeacon));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,4 +45,5 @@ export class RoomScrollStateStore {
|
|||||||
if (window.mxRoomScrollStateStore === undefined) {
|
if (window.mxRoomScrollStateStore === undefined) {
|
||||||
window.mxRoomScrollStateStore = new RoomScrollStateStore();
|
window.mxRoomScrollStateStore = new RoomScrollStateStore();
|
||||||
}
|
}
|
||||||
|
// oxlint-disable-next-line typescript/no-unnecessary-type-assertion
|
||||||
export default window.mxRoomScrollStateStore!;
|
export default window.mxRoomScrollStateStore!;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export default class ThreepidInviteStore extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public storeInvite(roomId: string, wireInvite: IThreepidInviteWireFormat): IThreepidInvite {
|
public storeInvite(roomId: string, wireInvite: IThreepidInviteWireFormat): IThreepidInvite {
|
||||||
const invite = <IPersistedThreepidInvite>{ roomId, ...wireInvite };
|
const invite: IPersistedThreepidInvite = { roomId, ...wireInvite };
|
||||||
const id = this.generateIdOf(invite);
|
const id = this.generateIdOf(invite);
|
||||||
localStorage.setItem(`${STORAGE_PREFIX}${id}`, JSON.stringify(invite));
|
localStorage.setItem(`${STORAGE_PREFIX}${id}`, JSON.stringify(invite));
|
||||||
return this.translateInvite(invite);
|
return this.translateInvite(invite);
|
||||||
|
|||||||
@@ -107,4 +107,5 @@ let singletonWidgetEchoStore: WidgetEchoStore | null = null;
|
|||||||
if (!singletonWidgetEchoStore) {
|
if (!singletonWidgetEchoStore) {
|
||||||
singletonWidgetEchoStore = new WidgetEchoStore();
|
singletonWidgetEchoStore = new WidgetEchoStore();
|
||||||
}
|
}
|
||||||
|
// oxlint-disable-next-line typescript/no-unnecessary-type-assertion
|
||||||
export default singletonWidgetEchoStore!;
|
export default singletonWidgetEchoStore!;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user