Home Reference Source

src/users-new/Presence.ts

import {concat, defer, Observable} from 'rxjs';
import {filter, first, map, shareReplay, mergeMap} from 'rxjs/operators';
import {PresenceService} from '../wac-proxy/wac-stack/presence/PresenceService';
import {PresenceActivity} from './PresenceActivity';
import {PresenceMood} from './PresenceMood';

export type PresenceState = Readonly<{
	online: boolean;
	activity: PresenceActivity;
	mood: PresenceMood;
	note: string;
	avatar: string;
	displayName: string;
}>;

export class Presence {
	readonly state$: Observable<PresenceState>;
	private presenceService: PresenceService;
	private ownId: string;

	constructor(
		presenceService: PresenceService,
		ownId: string,
	) {
		this.presenceService = presenceService;
		this.ownId = ownId;

		const initial$ = defer(() => this.presenceService.subscribeToPresence$(this.ownId));
		const updates$ = defer(() => this.presenceService.event$).pipe(
			map(event => event.body),
			filter(presence => presence.address === this.ownId),
		);
		this.state$ = concat(initial$, updates$).pipe(
			map(presenceDto => ({
				online: presenceDto.online,
				activity: presenceDto.activity,
				mood: presenceDto.mood,
				note: presenceDto.note,
				avatar: presenceDto.avatar,
				displayName: presenceDto.displayName,
			})),
			shareReplay(1),
		);
	}

	update(presence: Partial<PresenceState>): Observable<void> {
		return this.state$.pipe(
			first(),
			mergeMap(currentState => this.presenceService.update$(this.ownId, {...currentState, ...presence})),
			map(() => undefined),
		);
	}
}