115 lines
3.4 KiB
TypeScript
115 lines
3.4 KiB
TypeScript
/* eslint-disable @typescript-eslint/member-ordering, */
|
|
import {
|
|
Injectable,
|
|
signal,
|
|
computed,
|
|
inject
|
|
} from '@angular/core';
|
|
import { Store } from '@ngrx/store';
|
|
import { RoomsActions } from '../../../store/rooms/rooms.actions';
|
|
import { buildVoiceSessionRoom, isViewingVoiceSessionServer } from '../domain/voice-session.logic';
|
|
import type { VoiceSessionInfo } from '../domain/voice-session.models';
|
|
|
|
/**
|
|
* Tracks the user's current voice session across client-side
|
|
* navigation so that floating voice controls remain visible when
|
|
* the user is browsing a different server or view.
|
|
*
|
|
* This service is purely a UI-state tracker - actual WebRTC
|
|
* voice management lives in {@link WebRTCService} and its managers.
|
|
*/
|
|
@Injectable({ providedIn: 'root' })
|
|
export class VoiceSessionFacade {
|
|
private readonly store = inject(Store);
|
|
|
|
/** Current voice session metadata, or `null` when disconnected. */
|
|
private readonly _voiceSession = signal<VoiceSessionInfo | null>(null);
|
|
|
|
/** Whether the user is currently viewing the voice-connected server. */
|
|
private readonly _isViewingVoiceServer = signal<boolean>(true);
|
|
|
|
/** Reactive read-only voice session. */
|
|
readonly voiceSession = computed(() => this._voiceSession());
|
|
|
|
/** Reactive flag: is the user's current view the voice server? */
|
|
readonly isViewingVoiceServer = computed(() => this._isViewingVoiceServer());
|
|
|
|
/**
|
|
* Whether the floating voice-controls overlay should be visible.
|
|
* `true` when a voice session is active AND the user is viewing
|
|
* a different server.
|
|
*/
|
|
readonly showFloatingControls = computed(
|
|
() => this._voiceSession() !== null && !this._isViewingVoiceServer()
|
|
);
|
|
|
|
/**
|
|
* Begin tracking a voice session.
|
|
* Called when the user joins a voice channel.
|
|
*
|
|
* @param sessionInfo - Metadata describing the voice-connected server/channel.
|
|
*/
|
|
startSession(sessionInfo: VoiceSessionInfo): void {
|
|
this._voiceSession.set(sessionInfo);
|
|
this._isViewingVoiceServer.set(true);
|
|
}
|
|
|
|
/**
|
|
* Stop tracking the voice session.
|
|
* Called when the user disconnects from voice.
|
|
*/
|
|
endSession(): void {
|
|
this._voiceSession.set(null);
|
|
this._isViewingVoiceServer.set(true);
|
|
}
|
|
|
|
/**
|
|
* Manually flag whether the user is currently viewing the
|
|
* voice-connected server.
|
|
*
|
|
* @param isViewing - `true` if the user's current view is the voice server.
|
|
*/
|
|
setViewingVoiceServer(isViewing: boolean): void {
|
|
this._isViewingVoiceServer.set(isViewing);
|
|
}
|
|
|
|
/**
|
|
* Compare the given server ID to the voice session's server and
|
|
* update the {@link isViewingVoiceServer} flag accordingly.
|
|
*
|
|
* @param currentServerId - ID of the server the user is currently viewing.
|
|
*/
|
|
checkCurrentRoute(currentServerId: string | null): void {
|
|
this._isViewingVoiceServer.set(
|
|
isViewingVoiceSessionServer(this._voiceSession(), currentServerId)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Navigate the user back to the voice-connected server by
|
|
* dispatching a `viewServer` action.
|
|
*/
|
|
navigateToVoiceServer(): void {
|
|
const session = this._voiceSession();
|
|
|
|
if (!session)
|
|
return;
|
|
|
|
this.store.dispatch(
|
|
RoomsActions.viewServer({
|
|
room: buildVoiceSessionRoom(session)
|
|
})
|
|
);
|
|
|
|
this._isViewingVoiceServer.set(true);
|
|
}
|
|
|
|
/**
|
|
* Return the server ID of the active voice session, or `null`
|
|
* if the user is not in a voice channel.
|
|
*/
|
|
getVoiceServerId(): string | null {
|
|
return this._voiceSession()?.serverId ?? null;
|
|
}
|
|
}
|