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 12:16:35 +00:00
committed by GitHub
parent 811670a08c
commit 5de316b752
7 changed files with 116 additions and 10 deletions
@@ -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);
});
});
@@ -115,6 +115,7 @@ const DevtoolsDialog: React.FC<IProps> = ({ roomId, threadRootId, onFinished })
<SettingsFlag name="developerMode" level={SettingLevel.ACCOUNT} /> <SettingsFlag name="developerMode" level={SettingLevel.ACCOUNT} />
<SettingsFlag name="showHiddenEventsInTimeline" level={SettingLevel.DEVICE} /> <SettingsFlag name="showHiddenEventsInTimeline" level={SettingLevel.DEVICE} />
<SettingsFlag name="enableWidgetScreenshots" level={SettingLevel.ACCOUNT} /> <SettingsFlag name="enableWidgetScreenshots" level={SettingLevel.ACCOUNT} />
<SettingsFlag name="lowBandwidth" level={SettingLevel.DEVICE} />
</Form.Root> </Form.Root>
{/* The settings field needs to be outside `Form.Root` because `SettingsField` will have a inner Form, {/* 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 Otherwise we end up with a nester `Form` and that prohibits `preventDefault` so setting the value
@@ -16,7 +16,7 @@ import { SettingLevel } from "../../../../../settings/SettingLevel";
import SdkConfig from "../../../../../SdkConfig"; import SdkConfig from "../../../../../SdkConfig";
import BetaCard from "../../../beta/BetaCard"; import BetaCard from "../../../beta/BetaCard";
import SettingsFlag from "../../../elements/SettingsFlag"; 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 { EnhancedMap } from "../../../../../utils/maps";
import { SettingsSection } from "../../shared/SettingsSection"; import { SettingsSection } from "../../shared/SettingsSection";
import { SettingsSubsection, SettingsSubsectionText } from "../../shared/SettingsSubsection"; 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} />); .push(<SettingsFlag level={SettingLevel.DEVICE} name={f} key={f} />);
}); });
groups
.getOrCreate(LabGroup.Experimental, [])
.push(<SettingsFlag key="lowBandwidth" name="lowBandwidth" level={SettingLevel.DEVICE} />);
labsSections = ( labsSections = (
<> <>
{sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => ( {sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => (
+2 -2
View File
@@ -828,8 +828,8 @@
"invalid_device_key_id": "Invalid device key ID", "invalid_device_key_id": "Invalid device key ID",
"invalid_json": "Doesn't look like valid JSON.", "invalid_json": "Doesn't look like valid JSON.",
"level": "Level", "level": "Level",
"low_bandwidth_mode": "Low bandwidth mode", "low_bandwidth_mode": "Disable bandwidth-heavy features",
"low_bandwidth_mode_description": "Requires compatible homeserver.", "low_bandwidth_mode_description": "Disables encryption, presence, avatars, read receipts, and typing notifications",
"main_timeline": "Main timeline", "main_timeline": "Main timeline",
"manual_device_verification": "Manual device verification", "manual_device_verification": "Manual device verification",
"no_receipt_found": "No receipt found", "no_receipt_found": "No receipt found",
+4
View File
@@ -327,6 +327,10 @@ export interface Settings {
}>; }>;
"breadcrumbs": IBaseSetting<boolean>; "breadcrumbs": IBaseSetting<boolean>;
"showHiddenEventsInTimeline": 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>; "lowBandwidth": IBaseSetting<boolean>;
"fallbackICEServerAllowed": IBaseSetting<boolean | null>; "fallbackICEServerAllowed": IBaseSetting<boolean | null>;
"RoomList.preferredSorting": IBaseSetting<SortingAlgorithm>; "RoomList.preferredSorting": IBaseSetting<SortingAlgorithm>;
@@ -237,6 +237,50 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
</label> </label>
</div> </div>
</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>
<form <form
class="_root_19upo_16" class="_root_19upo_16"
@@ -246,7 +290,7 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
> >
<label <label
class="_label_19upo_59" class="_label_19upo_59"
for="radix-_r_a_" for="radix-_r_d_"
> >
Element Call URL Element Call URL
</label> </label>
@@ -255,7 +299,7 @@ exports[`DevtoolsDialog renders the devtools dialog 1`] = `
> >
<input <input
class="_control_sqdq4_10" class="_control_sqdq4_10"
id="radix-_r_a_" id="radix-_r_d_"
name="input" name="input"
title="" title=""
value="" value=""
@@ -48,6 +48,6 @@ describe("<LabsUserSettingsTab />", () => {
// non-beta labs section // non-beta labs section
expect(screen.getByText("Early previews")).toBeInTheDocument(); expect(screen.getByText("Early previews")).toBeInTheDocument();
const labsSections = container.getElementsByClassName("mx_SettingsSubsection"); const labsSections = container.getElementsByClassName("mx_SettingsSubsection");
expect(labsSections).toHaveLength(9); expect(labsSections).toHaveLength(8);
}); });
}); });