From d733f65cf305966be6d7b8a3217d09147680a094 Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 30 Jan 2025 17:24:53 +0000 Subject: [PATCH] Add FOSDEM module changes. --- src/Avatar.ts | 12 ++++++++ src/components/structures/MatrixChat.tsx | 3 ++ src/components/structures/UserMenu.tsx | 7 ++++- .../views/directory/NetworkDropdown.tsx | 17 +++++++---- .../views/elements/ServerPicker.tsx | 6 +++- src/modules/ModuleRunner.ts | 30 +++++++++++++++++++ 6 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/Avatar.ts b/src/Avatar.ts index a78aa4d03b..64927fdefb 100644 --- a/src/Avatar.ts +++ b/src/Avatar.ts @@ -13,6 +13,7 @@ import DMRoomMap from "./utils/DMRoomMap"; import { mediaFromMxc } from "./customisations/Media"; import { isLocalRoom } from "./utils/localRoom/isLocalRoom"; import { getFirstGrapheme } from "./utils/strings"; +import { ModuleRunner } from "./modules/ModuleRunner"; /** * Hardcoded from the Compound colors. @@ -98,6 +99,12 @@ const colorToDataURLCache = new Map(); export function defaultAvatarUrlForString(s: string): string { if (!s) return ""; // XXX: should never happen but empirically does by evidence of a rageshake + + const avatar = ModuleRunner.instance.extensions.conference.defaultAvatarUrlForString(s); + if (avatar !== null) { + return avatar; + } + // eslint-disable-next-line react-hooks/rules-of-hooks const colorIndex = useIdColorHash(s); // overwritten color value in custom themes @@ -134,6 +141,11 @@ export function getInitialLetter(name: string): string | undefined { return undefined; } + const avatar = ModuleRunner.instance.extensions.conference.getAvatarInitialLetter(name); + if (avatar !== null) { + return avatar; + } + const initial = name[0]; if ((initial === "@" || initial === "#" || initial === "+") && name[1]) { name = name.substring(1); diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 548dbff983..d5b3886772 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -132,6 +132,7 @@ import { SessionLockStolenView } from "./auth/SessionLockStolenView"; import { ConfirmSessionLockTheftView } from "./auth/ConfirmSessionLockTheftView"; import { LoginSplashView } from "./auth/LoginSplashView"; import { cleanUpDraftsIfRequired } from "../../DraftCleaner"; +import { ClientLifecycle } from "@matrix-org/react-sdk-module-api/lib/lifecycles/ClientLifecycle"; // legacy export export { default as Views } from "../../Views"; @@ -1553,6 +1554,8 @@ export default class MatrixChat extends React.PureComponent { this.firstSyncComplete = true; this.firstSyncPromise.resolve(); + console.log('TEST!!!'); + ModuleRunner.instance.invoke(ClientLifecycle.FirstSync); if (Notifier.shouldShowPrompt() && !MatrixClientPeg.userRegisteredWithinLastHours(24)) { showNotificationsToast(false); diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index c5f8ef841d..af7c6131d5 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -43,6 +43,7 @@ import { ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePaylo import { SDKContext } from "../../contexts/SDKContext"; import { shouldShowFeedback } from "../../utils/Feedback"; import DarkLightModeSvg from "../../../res/img/element-icons/roomlist/dark-light-mode.svg"; +import { ModuleRunner } from "../../modules/ModuleRunner"; interface IProps { isPanelCollapsed: boolean; @@ -410,13 +411,17 @@ export default class UserMenu extends React.Component { const userId = MatrixClientPeg.safeGet().getSafeUserId(); const displayName = OwnProfileStore.instance.displayName || userId; - const avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize); + let avatarUrl = OwnProfileStore.instance.getHttpAvatarUrl(avatarSize); let name: JSX.Element | undefined; if (!this.props.isPanelCollapsed) { name =
{displayName}
; } + if (!avatarUrl) { + avatarUrl = ModuleRunner.instance.extensions.conference.defaultAvatarUrlForString(userId); + } + return (
= ({ title, dialogTitle, serverConfig, onSe } let desc; - if (serverConfig.hsName === "matrix.org") { + const moduleDesc = ModuleRunner.instance.extensions.conference.serverLoginNotice(serverConfig.hsName); + if (moduleDesc) { + desc = {moduleDesc}; + } else if (serverConfig.hsName === "matrix.org") { desc = {_t("auth|server_picker_description_matrix.org")}; } diff --git a/src/modules/ModuleRunner.ts b/src/modules/ModuleRunner.ts index 06a17b43b4..cc4ee5d480 100644 --- a/src/modules/ModuleRunner.ts +++ b/src/modules/ModuleRunner.ts @@ -17,6 +17,10 @@ import { DefaultExperimentalExtensions, ProvideExperimentalExtensions, } from "@matrix-org/react-sdk-module-api/lib/lifecycles/ExperimentalExtensions"; +import { + DefaultConferenceExtensions, + ProvideConferenceExtensions, +} from "@matrix-org/react-sdk-module-api/lib/lifecycles/ConferenceExtensions"; import { AppModule } from "./AppModule"; import { ModuleFactory } from "./ModuleFactory"; @@ -30,6 +34,7 @@ class ExtensionsManager { // Private backing fields for extensions private cryptoSetupExtension: ProvideCryptoSetupExtensions; private experimentalExtension: ProvideExperimentalExtensions; + private conferenceExtension: ProvideConferenceExtensions; /** `true` if `cryptoSetupExtension` is the default implementation; `false` if it is implemented by a module. */ private hasDefaultCryptoSetupExtension = true; @@ -37,6 +42,9 @@ class ExtensionsManager { /** `true` if `experimentalExtension` is the default implementation; `false` if it is implemented by a module. */ private hasDefaultExperimentalExtension = true; + /** `true` if `conferenceExtension` is the default implementation; `false` if it is implemented by a module. */ + private hasDefaultConferenceExtension = true; + /** * Create a new instance. */ @@ -44,6 +52,7 @@ class ExtensionsManager { // Set up defaults this.cryptoSetupExtension = new DefaultCryptoSetupExtensions(); this.experimentalExtension = new DefaultExperimentalExtensions(); + this.conferenceExtension = new DefaultConferenceExtensions(); } /** @@ -67,6 +76,15 @@ class ExtensionsManager { return this.experimentalExtension; } + /** + * Provides extensions useful to conferences. + * + * @returns The registered extension. If no module provides this extension, a default implementation is returned. + */ + public get conference(): ProvideConferenceExtensions { + return this.conferenceExtension; + } + /** * Add any extensions provided by the module. * @@ -100,6 +118,18 @@ class ExtensionsManager { ); } } + + /* Add the experimental extension if any */ + if (runtimeModule.extensions?.conference) { + if (this.hasDefaultConferenceExtension) { + this.conferenceExtension = runtimeModule.extensions.conference; + this.hasDefaultConferenceExtension = false; + } else { + throw new Error( + `adding conference extension implementation from module ${runtimeModule.moduleName} but an implementation was already provided.`, + ); + } + } } }