mirror of
https://github.com/vector-im/element-call.git
synced 2026-05-13 10:34:37 +00:00
Introduce ViewModel.ts
This commit is contained in:
39
src/state/ViewModel.ts
Normal file
39
src/state/ViewModel.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2026 Element Software Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { useBehavior } from "../useBehavior";
|
||||
import { type Behavior } from "./Behavior";
|
||||
|
||||
export type ViewModel<Snapshot> = {
|
||||
[K in keyof Snapshot as `${string & K}$`]: Behavior<Snapshot[K]>;
|
||||
};
|
||||
|
||||
export function useViewModel<Snapshot>(vm: ViewModel<Snapshot>): Snapshot {
|
||||
const snapshot = {} as Snapshot;
|
||||
for (const key in vm) {
|
||||
const value$ = (vm as Record<string, Behavior<unknown>>)[key];
|
||||
const snapshotKey = key.slice(0, -1) as keyof Snapshot;
|
||||
// we allow using hooks in a loop here because we know the shape of the vm is static and won't change between renders, so the order of hooks calls will always be the same.
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
snapshot[snapshotKey] = useBehavior(value$) as Snapshot[keyof Snapshot];
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
export function createMockedViewModel<Snapshot>(
|
||||
snapshot: Snapshot,
|
||||
): ViewModel<Snapshot> {
|
||||
const vm = {} as ViewModel<Snapshot>;
|
||||
for (const key in snapshot) {
|
||||
(vm as Record<string, Behavior<unknown>>)[`${key}$`] = new BehaviorSubject(
|
||||
snapshot[key],
|
||||
);
|
||||
}
|
||||
return vm;
|
||||
}
|
||||
Reference in New Issue
Block a user