Global configuration flag for media previews (#29582)
* Modify useMediaVisible to take a room. * Add initial support for a account data level key. * Update controls. * Update settings * Lint and fixes * make some tests go happy * lint * i18n * update preferences * prettier * Update settings tab. * update screenshot * Update docs * Rewrite controller * Rewrite tons of tests * Rewrite RoomAvatar to be a functional component This is so we can use hooks to determine the setting state. * lint * lint * Tidy up comments * Apply media visible hook to inline images. * Move conditionals. * copyright all the things * Review changes * Update html utils to properly discard media. * Types fix * Fixing tests that break settings getValue expectations * Fix logic around media preview calculation * Fix room header tests * Fixup tests for timelinePanel * Clear settings in matrixchat * Update tests to use SettingsStore where possible. * fix bug * revert changes to client.ts * copyright years * Add header * Add a test for MediaPreviewAccountSettingsTab * Mark initMatrixClient as optional * Improve on types * Ensure we do not set the account data twice. * lint * Review changes * Ensure we include the client on rendered messages. * Fix test * update labels * clean designs * update settings tab * update snapshot * copyright * prevent mutation
This commit is contained in:
@@ -26,7 +26,7 @@ export default abstract class MatrixClientBackedController extends SettingContro
|
||||
MatrixClientBackedController._matrixClient = client;
|
||||
|
||||
for (const instance of MatrixClientBackedController.instances) {
|
||||
instance.initMatrixClient(client, oldClient);
|
||||
instance.initMatrixClient?.(client, oldClient);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,5 +40,5 @@ export default abstract class MatrixClientBackedController extends SettingContro
|
||||
return MatrixClientBackedController._matrixClient;
|
||||
}
|
||||
|
||||
protected abstract initMatrixClient(newClient: MatrixClient, oldClient?: MatrixClient): void;
|
||||
protected initMatrixClient?(newClient: MatrixClient, oldClient?: MatrixClient): void;
|
||||
}
|
||||
|
||||
100
src/settings/controllers/MediaPreviewConfigController.ts
Normal file
100
src/settings/controllers/MediaPreviewConfigController.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type IContent } from "matrix-js-sdk/src/matrix";
|
||||
import { type AccountDataEvents } from "matrix-js-sdk/src/types";
|
||||
|
||||
import {
|
||||
MEDIA_PREVIEW_ACCOUNT_DATA_TYPE,
|
||||
type MediaPreviewConfig,
|
||||
MediaPreviewValue,
|
||||
} from "../../@types/media_preview.ts";
|
||||
import { type SettingLevel } from "../SettingLevel.ts";
|
||||
import MatrixClientBackedController from "./MatrixClientBackedController.ts";
|
||||
|
||||
/**
|
||||
* Handles media preview settings provided by MSC4278.
|
||||
* This uses both account-level and room-level account data.
|
||||
*/
|
||||
export default class MediaPreviewConfigController extends MatrixClientBackedController {
|
||||
public static readonly default: AccountDataEvents[typeof MEDIA_PREVIEW_ACCOUNT_DATA_TYPE] = {
|
||||
media_previews: MediaPreviewValue.On,
|
||||
invite_avatars: MediaPreviewValue.On,
|
||||
};
|
||||
|
||||
private static getValidSettingData(content: IContent): Partial<MediaPreviewConfig> {
|
||||
const mediaPreviews: MediaPreviewConfig["media_previews"] = content.media_previews;
|
||||
const inviteAvatars: MediaPreviewConfig["invite_avatars"] = content.invite_avatars;
|
||||
const validMediaPreviews = Object.values(MediaPreviewValue);
|
||||
const validInviteAvatars = [MediaPreviewValue.Off, MediaPreviewValue.On];
|
||||
return {
|
||||
invite_avatars: validInviteAvatars.includes(inviteAvatars) ? inviteAvatars : undefined,
|
||||
media_previews: validMediaPreviews.includes(mediaPreviews) ? mediaPreviews : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
private getValue = (roomId?: string): MediaPreviewConfig => {
|
||||
const source = roomId ? this.client?.getRoom(roomId) : this.client;
|
||||
const accountData =
|
||||
source?.getAccountData(MEDIA_PREVIEW_ACCOUNT_DATA_TYPE)?.getContent<MediaPreviewConfig>() ?? {};
|
||||
|
||||
const calculatedConfig = MediaPreviewConfigController.getValidSettingData(accountData);
|
||||
|
||||
// Save an account data fetch if we have all the values.
|
||||
if (calculatedConfig.invite_avatars && calculatedConfig.media_previews) {
|
||||
return calculatedConfig as MediaPreviewConfig;
|
||||
}
|
||||
|
||||
// We're missing some keys.
|
||||
if (roomId) {
|
||||
const globalConfig = this.getValue();
|
||||
return {
|
||||
invite_avatars:
|
||||
calculatedConfig.invite_avatars ??
|
||||
globalConfig.invite_avatars ??
|
||||
MediaPreviewConfigController.default.invite_avatars,
|
||||
media_previews:
|
||||
calculatedConfig.media_previews ??
|
||||
globalConfig.media_previews ??
|
||||
MediaPreviewConfigController.default.media_previews,
|
||||
};
|
||||
}
|
||||
return {
|
||||
invite_avatars: calculatedConfig.invite_avatars ?? MediaPreviewConfigController.default.invite_avatars,
|
||||
media_previews: calculatedConfig.media_previews ?? MediaPreviewConfigController.default.media_previews,
|
||||
};
|
||||
};
|
||||
|
||||
public getValueOverride(_level: SettingLevel, roomId: string | null): MediaPreviewConfig {
|
||||
return this.getValue(roomId ?? undefined);
|
||||
}
|
||||
|
||||
public get settingDisabled(): false {
|
||||
// No homeserver support is required for this MSC.
|
||||
return false;
|
||||
}
|
||||
|
||||
public async beforeChange(
|
||||
_level: SettingLevel,
|
||||
roomId: string | null,
|
||||
newValue: MediaPreviewConfig,
|
||||
): Promise<boolean> {
|
||||
if (!this.client) {
|
||||
return false;
|
||||
}
|
||||
if (roomId) {
|
||||
await this.client.setRoomAccountData(roomId, MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, newValue);
|
||||
return true;
|
||||
}
|
||||
await this.client.setAccountData(MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, newValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user