mirror of
https://github.com/vector-im/element-call.git
synced 2026-02-08 04:19:11 +00:00
Add some quick-and-dirty debug info for TileStore (#2887)
* Add some quick-and-dirty debug info for TileStore I'm still in need of more detailed data in order to understand why big layout shifts happen in large calls. This adds a developer option to enable logging and a visual indicator for the state of the TileStore. The indicator should be useful for matching up the behavior I'm seeing in my recordings with the right timestamps. * Reduce performance impact of checking for whether debug mode is enabled --------- Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
This commit is contained in:
@@ -891,10 +891,9 @@ export class CallViewModel extends ViewModel {
|
||||
this.scope.state(),
|
||||
);
|
||||
|
||||
/**
|
||||
* The layout of tiles in the call interface.
|
||||
*/
|
||||
public readonly layout: Observable<Layout> = this.layoutMedia.pipe(
|
||||
public readonly layoutInternals: Observable<
|
||||
LayoutScanState & { layout: Layout }
|
||||
> = this.layoutMedia.pipe(
|
||||
// Each layout will produce a set of tiles, and these tiles have an
|
||||
// observable indicating whether they're visible. We loop this information
|
||||
// back into the layout process by using switchScan.
|
||||
@@ -949,10 +948,26 @@ export class CallViewModel extends ViewModel {
|
||||
visibleTiles: new Set(),
|
||||
},
|
||||
),
|
||||
this.scope.state(),
|
||||
);
|
||||
|
||||
/**
|
||||
* The layout of tiles in the call interface.
|
||||
*/
|
||||
public readonly layout: Observable<Layout> = this.layoutInternals.pipe(
|
||||
map(({ layout }) => layout),
|
||||
this.scope.state(),
|
||||
);
|
||||
|
||||
/**
|
||||
* The current generation of the tile store, exposed for debugging purposes.
|
||||
*/
|
||||
public readonly tileStoreGeneration: Observable<number> =
|
||||
this.layoutInternals.pipe(
|
||||
map(({ tiles }) => tiles.generation),
|
||||
this.scope.state(),
|
||||
);
|
||||
|
||||
public showSpotlightIndicators: Observable<boolean> = this.layout.pipe(
|
||||
map((l) => l.type !== "grid"),
|
||||
this.scope.state(),
|
||||
|
||||
@@ -6,10 +6,19 @@ Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { type MediaViewModel, type UserMediaViewModel } from "./MediaViewModel";
|
||||
import { GridTileViewModel, SpotlightTileViewModel } from "./TileViewModel";
|
||||
import { fillGaps } from "../utils/iter";
|
||||
import { debugTileLayout } from "../settings/settings";
|
||||
|
||||
function debugEntries(entries: GridTileData[]): string[] {
|
||||
return entries.map((e) => e.media.member?.rawDisplayName ?? "[👻]");
|
||||
}
|
||||
|
||||
let DEBUG_ENABLED = false;
|
||||
debugTileLayout.value.subscribe((value) => (DEBUG_ENABLED = value));
|
||||
|
||||
class SpotlightTileData {
|
||||
private readonly media_: BehaviorSubject<MediaViewModel[]>;
|
||||
@@ -69,6 +78,10 @@ export class TileStore {
|
||||
private constructor(
|
||||
private readonly spotlight: SpotlightTileData | null,
|
||||
private readonly grid: GridTileData[],
|
||||
/**
|
||||
* A number incremented on each update, just for debugging purposes.
|
||||
*/
|
||||
public readonly generation: number,
|
||||
) {}
|
||||
|
||||
public readonly spotlightTile = this.spotlight?.vm;
|
||||
@@ -81,7 +94,7 @@ export class TileStore {
|
||||
* Creates an an empty collection of tiles.
|
||||
*/
|
||||
public static empty(): TileStore {
|
||||
return new TileStore(null, []);
|
||||
return new TileStore(null, [], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,8 +105,9 @@ export class TileStore {
|
||||
return new TileStoreBuilder(
|
||||
this.spotlight,
|
||||
this.grid,
|
||||
(spotlight, grid) => new TileStore(spotlight, grid),
|
||||
(spotlight, grid) => new TileStore(spotlight, grid, this.generation + 1),
|
||||
visibleTiles,
|
||||
this.generation,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -133,6 +147,10 @@ export class TileStoreBuilder {
|
||||
grid: GridTileData[],
|
||||
) => TileStore,
|
||||
private readonly visibleTiles: Set<GridTileViewModel>,
|
||||
/**
|
||||
* A number incremented on each update, just for debugging purposes.
|
||||
*/
|
||||
private readonly generation: number,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -140,6 +158,11 @@ export class TileStoreBuilder {
|
||||
* will be no spotlight tile.
|
||||
*/
|
||||
public registerSpotlight(media: MediaViewModel[], maximised: boolean): void {
|
||||
if (DEBUG_ENABLED)
|
||||
logger.debug(
|
||||
`[TileStore, ${this.generation}] register spotlight: ${media.map((m) => m.member?.rawDisplayName ?? "[👻]")}`,
|
||||
);
|
||||
|
||||
if (this.spotlight !== null) throw new Error("Spotlight already set");
|
||||
if (this.numGridEntries > 0)
|
||||
throw new Error("Spotlight must be registered before grid tiles");
|
||||
@@ -159,6 +182,11 @@ export class TileStoreBuilder {
|
||||
* media, then that media will have no grid tile.
|
||||
*/
|
||||
public registerGridTile(media: UserMediaViewModel): void {
|
||||
if (DEBUG_ENABLED)
|
||||
logger.debug(
|
||||
`[TileStore, ${this.generation}] register grid tile: ${media.member?.rawDisplayName ?? "[👻]"}`,
|
||||
);
|
||||
|
||||
if (this.spotlight !== null) {
|
||||
// We actually *don't* want spotlight speakers to appear in both the
|
||||
// spotlight and the grid, so they're filtered out here
|
||||
@@ -246,6 +274,20 @@ export class TileStoreBuilder {
|
||||
...this.invisibleGridEntries,
|
||||
]),
|
||||
];
|
||||
if (DEBUG_ENABLED) {
|
||||
logger.debug(
|
||||
`[TileStore, ${this.generation}] stationary: ${debugEntries(this.stationaryGridEntries)}`,
|
||||
);
|
||||
logger.debug(
|
||||
`[TileStore, ${this.generation}] visible: ${debugEntries(this.visibleGridEntries)}`,
|
||||
);
|
||||
logger.debug(
|
||||
`[TileStore, ${this.generation}] invisible: ${debugEntries(this.invisibleGridEntries)}`,
|
||||
);
|
||||
logger.debug(
|
||||
`[TileStore, ${this.generation}] result: ${debugEntries(grid)}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Destroy unused tiles
|
||||
if (this.spotlight === null && this.prevSpotlight !== null)
|
||||
|
||||
Reference in New Issue
Block a user