Add a developer option to duplicate tiles
This is useful for testing how the UI behaves with different numbers of participants.
This commit is contained in:
@@ -132,6 +132,7 @@
|
|||||||
"developer_settings_label": "Developer Settings",
|
"developer_settings_label": "Developer Settings",
|
||||||
"developer_settings_label_description": "Expose developer settings in the settings window.",
|
"developer_settings_label_description": "Expose developer settings in the settings window.",
|
||||||
"developer_tab_title": "Developer",
|
"developer_tab_title": "Developer",
|
||||||
|
"duplicate_tiles_label": "Number of duplicate tiles",
|
||||||
"feedback_tab_body": "If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.",
|
"feedback_tab_body": "If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.",
|
||||||
"feedback_tab_description_label": "Your feedback",
|
"feedback_tab_description_label": "Your feedback",
|
||||||
"feedback_tab_h4": "Submit feedback",
|
"feedback_tab_h4": "Submit feedback",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChangeEvent, FC, Key, ReactNode } from "react";
|
import { ChangeEvent, FC, Key, ReactNode, useCallback } from "react";
|
||||||
import { Item } from "@react-stately/collections";
|
import { Item } from "@react-stately/collections";
|
||||||
import { Trans, useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { MatrixClient } from "matrix-js-sdk";
|
import { MatrixClient } from "matrix-js-sdk";
|
||||||
@@ -44,6 +44,7 @@ import {
|
|||||||
useSetting,
|
useSetting,
|
||||||
optInAnalytics as optInAnalyticsSetting,
|
optInAnalytics as optInAnalyticsSetting,
|
||||||
developerSettingsTab as developerSettingsTabSetting,
|
developerSettingsTab as developerSettingsTabSetting,
|
||||||
|
duplicateTiles as duplicateTilesSetting,
|
||||||
} from "./settings";
|
} from "./settings";
|
||||||
import { isFirefox } from "../Platform";
|
import { isFirefox } from "../Platform";
|
||||||
|
|
||||||
@@ -80,6 +81,7 @@ export const SettingsModal: FC<Props> = ({
|
|||||||
const [developerSettingsTab, setDeveloperSettingsTab] = useSetting(
|
const [developerSettingsTab, setDeveloperSettingsTab] = useSetting(
|
||||||
developerSettingsTabSetting,
|
developerSettingsTabSetting,
|
||||||
);
|
);
|
||||||
|
const [duplicateTiles, setDuplicateTiles] = useSetting(duplicateTilesSetting);
|
||||||
|
|
||||||
// Generate a `SelectInput` with a list of devices for a given device kind.
|
// Generate a `SelectInput` with a list of devices for a given device kind.
|
||||||
const generateDeviceSelection = (
|
const generateDeviceSelection = (
|
||||||
@@ -244,6 +246,20 @@ export const SettingsModal: FC<Props> = ({
|
|||||||
})}
|
})}
|
||||||
</Body>
|
</Body>
|
||||||
</FieldRow>
|
</FieldRow>
|
||||||
|
<FieldRow>
|
||||||
|
<InputField
|
||||||
|
id="duplicateTiles"
|
||||||
|
type="number"
|
||||||
|
label={t("settings.duplicate_tiles_label")}
|
||||||
|
value={duplicateTiles.toString()}
|
||||||
|
onChange={useCallback(
|
||||||
|
(event: ChangeEvent<HTMLInputElement>): void => {
|
||||||
|
setDuplicateTiles(event.target.valueAsNumber);
|
||||||
|
},
|
||||||
|
[setDuplicateTiles],
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FieldRow>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ export const developerSettingsTab = new Setting(
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const duplicateTiles = new Setting("duplicate-tiles", 0);
|
||||||
|
|
||||||
export const audioInput = new Setting<string | undefined>(
|
export const audioInput = new Setting<string | undefined>(
|
||||||
"audio-input",
|
"audio-input",
|
||||||
undefined,
|
undefined,
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import {
|
|||||||
} from "./MediaViewModel";
|
} from "./MediaViewModel";
|
||||||
import { finalizeValue } from "../observable-utils";
|
import { finalizeValue } from "../observable-utils";
|
||||||
import { ObservableScope } from "./ObservableScope";
|
import { ObservableScope } from "./ObservableScope";
|
||||||
|
import { duplicateTiles } from "../settings/settings";
|
||||||
|
|
||||||
// How long we wait after a focus switch before showing the real participant
|
// How long we wait after a focus switch before showing the real participant
|
||||||
// list again
|
// list again
|
||||||
@@ -308,11 +309,16 @@ export class CallViewModel extends ViewModel {
|
|||||||
combineLatest([
|
combineLatest([
|
||||||
this.remoteParticipants,
|
this.remoteParticipants,
|
||||||
observeParticipantMedia(this.livekitRoom.localParticipant),
|
observeParticipantMedia(this.livekitRoom.localParticipant),
|
||||||
|
duplicateTiles.value,
|
||||||
]).pipe(
|
]).pipe(
|
||||||
scan(
|
scan(
|
||||||
(
|
(
|
||||||
prevItems,
|
prevItems,
|
||||||
[remoteParticipants, { participant: localParticipant }],
|
[
|
||||||
|
remoteParticipants,
|
||||||
|
{ participant: localParticipant },
|
||||||
|
duplicateTiles,
|
||||||
|
],
|
||||||
) => {
|
) => {
|
||||||
let allGhosts = true;
|
let allGhosts = true;
|
||||||
|
|
||||||
@@ -330,20 +336,29 @@ export class CallViewModel extends ViewModel {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userMediaId = p.identity;
|
// Create as many tiles for this participant as called for by
|
||||||
yield [
|
// the duplicateTiles option
|
||||||
userMediaId,
|
for (let i = 0; i < 1 + duplicateTiles; i++) {
|
||||||
prevItems.get(userMediaId) ??
|
const userMediaId = `${p.identity}:${i}`;
|
||||||
new UserMedia(userMediaId, member, p, this.encrypted),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (p.isScreenShareEnabled) {
|
|
||||||
const screenShareId = `${userMediaId}:screen-share`;
|
|
||||||
yield [
|
yield [
|
||||||
screenShareId,
|
userMediaId,
|
||||||
prevItems.get(screenShareId) ??
|
prevItems.get(userMediaId) ??
|
||||||
new ScreenShare(screenShareId, member, p, this.encrypted),
|
new UserMedia(userMediaId, member, p, this.encrypted),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (p.isScreenShareEnabled) {
|
||||||
|
const screenShareId = `${userMediaId}:screen-share`;
|
||||||
|
yield [
|
||||||
|
screenShareId,
|
||||||
|
prevItems.get(screenShareId) ??
|
||||||
|
new ScreenShare(
|
||||||
|
screenShareId,
|
||||||
|
member,
|
||||||
|
p,
|
||||||
|
this.encrypted,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.bind(this)(),
|
}.bind(this)(),
|
||||||
|
|||||||
Reference in New Issue
Block a user