Files
element-call/src/state/ViewModel.ts
T

50 lines
1.5 KiB
TypeScript
Raw Normal View History

2026-05-11 17:29:41 +02:00
/*
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";
2026-05-15 18:37:25 +02:00
import { useState, useEffect } from "react";
2026-05-11 17:29:41 +02:00
import { type Behavior } from "./Behavior";
export type ViewModel<Snapshot> = {
[K in keyof Snapshot as `${string & K}$`]: Behavior<Snapshot[K]>;
};
2026-05-12 12:46:01 +02:00
/**
* This allows to build a view model (or Partial view model)
* with BehaviorSubjects.
* It can be used in tests and for simplifying view model creation for non reactive snapshot parameters.
*
* @param snapshot The snapshot values this view model with start with. ({a: number, b: string})
* @returns A view model: ({a$: BehaviroSubject<number>, b$: BehaviroSubject<string>}) (note the automatic addition of $ at the end of the keys)
*/
export function createStaticViewModel<Snapshot>(
2026-05-11 17:29:41 +02:00
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;
}
2026-05-15 18:37:25 +02:00
export function useStaticViewModel<Snapshot>(
snapshot: Snapshot,
): ViewModel<Snapshot> {
const [vm] = useState(createStaticViewModel(snapshot));
useEffect(() => {
for (const key in snapshot) {
(vm as unknown as Record<string, BehaviorSubject<unknown>>)[
`${key}$`
].next(snapshot[key]);
}
}, [snapshot, vm]);
return vm;
}