@oobleck/fluid-backend
Version:
Fluid Framework backend for nteract RTC
82 lines (73 loc) • 2.82 kB
text/typescript
import { fromEventPattern, merge, Observable } from "rxjs";
import { filter, map } from "rxjs/operators";
import { IFluidDataStoreRuntime } from "@fluidframework/datastore-definitions";
import { IInboundSignalMessage } from "@fluidframework/runtime-definitions";
import { FrsMember, IFrsAudience } from "@fluid-experimental/frs-client";
import { IPeerConnectedEvent, IPeerDisconnectedEvent, IPeerLocationUpdatedEvent, PeerLocationDef, PresenceEvent } from "../schema";
// import {
// FluidContainer,
// IMember,
// IServiceAudience,
// SignalManager,
// } from "@fluid-experimental/fluid-framework";
export class Presence {
private readonly presenceKey: string;
// private readonly presenceMap = new Map<string, PeerPresenceDef>();
readonly events$ = new Observable<PresenceEvent>();
constructor(
audience: IFrsAudience,
private readonly runtime: IFluidDataStoreRuntime
) {
this.presenceKey = `presence-${runtime.id}`;
const added$ = fromEventPattern<[string, FrsMember]>(
handler => audience.on("memberAdded", handler),
handler => audience.off("memberAdded", handler)
).pipe(map(([clientId, { userId, userName }]) => {
return {
__typename: "PeerConnectedEvent",
id: clientId,
userId,
userName
} as IPeerConnectedEvent;
}));
const removed$ = fromEventPattern<[string, FrsMember]>(
handler => audience.on("memberRemoved", handler),
handler => audience.off("memberRemoved", handler)
).pipe(map(([clientId]) => {
return {
__typename: "PeerDisconnectedEvent",
id: clientId
} as IPeerDisconnectedEvent;
}));
const updates$ = fromEventPattern<[IInboundSignalMessage, boolean]>(
handler => this.runtime.on("signal", handler),
handler => this.runtime.off("signal", handler)
).pipe(
filter(([message, local]) => !local && runtime.connected && !!message.clientId && message.type === this.presenceKey),
map(([{ clientId, content }]) => {
return {
__typename: "PeerLocationUpdatedEvent",
id: clientId!,
location: content as PeerLocationDef
} as IPeerLocationUpdatedEvent;
})
);
const current$ = new Observable<IPeerConnectedEvent>((observer) => {
audience.getMembers().forEach(({ userId, userName }, id) => {
observer.next({
__typename: "PeerConnectedEvent",
id,
userId,
userName
});
});
observer.complete();
});
this.events$ = merge(current$, added$, removed$, updates$);
}
update(input: PeerLocationDef) {
if (this.runtime.connected) {
this.runtime.submitSignal(this.presenceKey, input);
}
}
}