Move Low Bandwidth feature to devtools. (#32797)

* Move and rename low bandwidth mode.

* Still in use.

* remove string

* Add a test for low bandwidth mode

* Test requests too

* update snaps

* New year!
This commit is contained in:
Will Hunt 2026-04-07 13:16:35 +01:00 committed by GitHub
parent 811670a08c
commit 5de316b752
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 116 additions and 10 deletions

View File

@ -0,0 +1,61 @@
/*
Copyright 2026 Element Creations 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 { test, expect } from "../../element-web-test";
import { getSampleFilePath } from "../../sample-files";
test.describe("Devtools", () => {
test.use({
displayName: "Alice",
});
test("should allow enabling low bandwidth mode", async ({ page, homeserver, user, app }) => {
// Upload a picture
const userSettings = await app.settings.openUserSettings("Account");
const profileSettings = userSettings.locator(".mx_UserProfileSettings");
await profileSettings.getByAltText("Upload").setInputFiles(getSampleFilePath("riot.png"));
await app.closeDialog();
// Create an initial room.
const createRoomDialog = await app.openCreateRoomDialog();
await createRoomDialog.getByRole("textbox", { name: "Name" }).fill("Test Room");
await createRoomDialog.getByRole("button", { name: "Create room" }).click();
const composer = app.getComposer().locator("[contenteditable]");
await composer.fill("/devtools");
await composer.press("Enter");
const dialog = page.locator(".mx_Dialog");
await dialog.getByLabel("Developer mode").check();
await dialog.getByLabel("Disable bandwidth-heavy features").click();
// Wait for refresh.
await page.waitForEvent("domcontentloaded");
await app.viewRoomByName("Test Room");
// This only appears when encryption has been disabled in the client.
await expect(page.getByText("The encryption used by this room isn't supported.")).toBeVisible();
// None of these should be requested.
let hasSentTyping = false;
let hasRequestedThumbnail = false;
await page.route("**/_matrix/client/v3/rooms/*/typing/*", async (route) => {
hasSentTyping = true;
await route.fulfill({ json: {} });
});
await page.route("**/_matrix/media/v3/thumbnail/**", async (route) => {
hasRequestedThumbnail = true;
await route.fulfill({ json: {} });
});
await page.route("**/_matrix/client/v1/media/thumbnail/**", async (route) => {
hasRequestedThumbnail = true;
await route.fulfill({ json: {} });
});
await composer.pressSequentially("Provoke typing request", { delay: 5 });
expect(hasSentTyping).toEqual(false);
expect(hasRequestedThumbnail).toEqual(false);
});
});

View File

@ -115,6 +115,7 @@ const DevtoolsDialog: React.FC<IProps> = ({ roomId, threadRootId, onFinished })
<SettingsFlag name="developerMode" level={SettingLevel.ACCOUNT} />
<SettingsFlag name="showHiddenEventsInTimeline" level={SettingLevel.DEVICE} />
<SettingsFlag name="enableWidgetScreenshots" level={SettingLevel.ACCOUNT} />
<SettingsFlag name="lowBandwidth" level={SettingLevel.DEVICE} />
</Form.Root>
{/* The settings field needs to be outside `Form.Root` because `SettingsField` will have a inner Form,
Otherwise we end up with a nester `Form` and that prohibits `preventDefault` so setting the value

View File

@ -16,7 +16,7 @@ import { SettingLevel } from "../../../../../settings/SettingLevel";
import SdkConfig from "../../../../../SdkConfig";
import BetaCard from "../../../beta/BetaCard";
import SettingsFlag from "../../../elements/SettingsFlag";
import { type FeatureSettingKey, LabGroup, labGroupNames } from "../../../../../settings/Settings";
import { type FeatureSettingKey, type LabGroup, labGroupNames } from "../../../../../settings/Settings";
import { EnhancedMap } from "../../../../../utils/maps";
import { SettingsSection } from "../../shared/SettingsSection";
import { SettingsSubsection, SettingsSubsectionText } from "../../shared/SettingsSubsection";
@ -71,10 +71,6 @@ export default class LabsUserSettingsTab extends React.Component<EmptyObject> {
.push(<SettingsFlag level={SettingLevel.DEVICE} name={f} key={f} />);
});
groups
.getOrCreate(LabGroup.Experimental, [])
.push(<SettingsFlag key="lowBandwidth" name="lowBandwidth" level={SettingLevel.DEVICE} />);
labsSections = (
<>
{sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => (

View File

@ -828,8 +828,8 @@
"invalid_device_key_id": "Invalid device key ID",
"invalid_json": "Doesn't look like valid JSON.",
"level": "Level",
"low_bandwidth_mode": "Low bandwidth mode",
"low_bandwidth_mode_description": "Requires compatible homeserver.",
"low_bandwidth_mode": "Disable bandwidth-heavy features",
"low_bandwidth_mode_description": "Disables encryption, presence, avatars, read receipts, and typing notifications",
"main_timeline": "Main timeline",
"manual_device_verification": "Manual device verification",
"no_receipt_found": "No receipt found",

View File

@ -327,6 +327,10 @@ export interface Settings {
}>;
"breadcrumbs": IBaseSetting<boolean>;
"showHiddenEventsInTimeline": IBaseSetting<boolean>;
/**
* This is the 2019-era low bandwidth that deals with disabling features of the
* client. It does NOT make any API or spec changes.
*/
"lowBandwidth": IBaseSetting<boolean>;
"fallbackICEServerAllowed": IBaseSetting<boolean | null>;
"RoomList.preferredSorting": IBaseSetting<SortingAlgorithm>;

View File

@ -237,6 +237,50 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
</label>
</div>
</div>
<div
class="_inline-field_19upo_32"
>
<div
class="_inline-field-control_19upo_44"
>
<div
class="_container_udcm8_10"
>
<input
class="_input_udcm8_24"
id="mx_SettingsFlag_4yVCeEefiPqp"
role="switch"
type="checkbox"
/>
<div
class="_ui_udcm8_34"
/>
</div>
</div>
<div
class="_inline-field-body_19upo_38"
>
<label
class="_label_19upo_59"
for="mx_SettingsFlag_4yVCeEefiPqp"
>
Disable bandwidth-heavy features
</label>
<span
class="_message_19upo_85 _help-message_19upo_91"
id="radix-_r_c_"
>
<span>
<span
class="mx_SettingsTab_microcopy_warning"
>
WARNING:
</span>
Disables encryption, presence, avatars, read receipts, and typing notifications
</span>
</span>
</div>
</div>
</form>
<form
class="_root_19upo_16"
@ -246,7 +290,7 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
>
<label
class="_label_19upo_59"
for="radix-_r_a_"
for="radix-_r_d_"
>
Element Call URL
</label>
@ -255,7 +299,7 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
>
<input
class="_control_sqdq4_10"
id="radix-_r_a_"
id="radix-_r_d_"
name="input"
title=""
value=""

View File

@ -48,6 +48,6 @@ describe("<LabsUserSettingsTab />", () => {
// non-beta labs section
expect(screen.getByText("Early previews")).toBeInTheDocument();
const labsSections = container.getElementsByClassName("mx_SettingsSubsection");
expect(labsSections).toHaveLength(9);
expect(labsSections).toHaveLength(8);
});
});