diff --git a/src/classes/Channel.ts b/src/classes/Channel.ts index 00805a62..0cb10ab7 100644 --- a/src/classes/Channel.ts +++ b/src/classes/Channel.ts @@ -30,7 +30,7 @@ import type { Message } from "./Message.js"; import type { Server } from "./Server.js"; import type { ServerMember } from "./ServerMember.js"; import type { User } from "./User.js"; -import { VoiceParticipant } from "./VoiceParticipant.js"; +import { VoiceParticipant, VoiceStatus } from "./VoiceParticipant.js"; /** * Channel Class @@ -850,4 +850,28 @@ export class Channel { channel: this.id, }); } + + /** + * The voice status of a channel. Screenshare supersedes video, video + * supersedes voice, and voice supersedes none. This getter takes the highest + * priority status from all participants in the channel. + */ + get voiceStatus(): VoiceStatus { + if (!this.isVoice || this.voiceParticipants.size === 0) { + return "none"; + } + + let highest: VoiceStatus = "voice"; + for (const participant of this.voiceParticipants.values()) { + const status = participant.voiceStatus; + if (status === "screenshare") { + return "screenshare"; + } + if (status === "video") { + highest = "video"; + } + } + + return highest; + } } diff --git a/src/classes/Server.ts b/src/classes/Server.ts index e7f08866..f246c5ba 100644 --- a/src/classes/Server.ts +++ b/src/classes/Server.ts @@ -13,7 +13,6 @@ import type { DataEditRole, DataEditServer, Override, - OverrideField, Role, } from "stoat-api"; import { decodeTime } from "ulid"; @@ -35,6 +34,7 @@ import { ServerBan } from "./ServerBan.js"; import { ServerMember } from "./ServerMember.js"; import { ServerRole } from "./ServerRole.js"; import { User } from "./User.js"; +import { VoiceStatus } from "./VoiceParticipant.js"; /** * Server Class @@ -827,4 +827,28 @@ export class Server { async deleteEmoji(emojiId: string): Promise { await this.#collection.client.api.delete(`/custom/emoji/${emojiId}`); } + + /** + * The voice status of a server. Screenshare supersedes video, video + * supersedes voice, and voice supersedes none. This getter takes the highest + * priority status from all channels in the server. + */ + get voiceStatus(): VoiceStatus { + let highest: VoiceStatus = "none"; + + for (const chan of this.channels) { + const status = chan.voiceStatus; + if (status === "screenshare") { + return "screenshare"; + } + if (status === "video") { + highest = "video"; + } + if (status === "voice" && highest === "none") { + highest = "voice"; + } + } + + return highest; + } } diff --git a/src/classes/VoiceParticipant.ts b/src/classes/VoiceParticipant.ts index 6e01cede..4625330d 100644 --- a/src/classes/VoiceParticipant.ts +++ b/src/classes/VoiceParticipant.ts @@ -3,6 +3,11 @@ import { Accessor, Setter, createSignal } from "solid-js"; import type { Client } from "../Client.js"; import { UserVoiceState } from "../events/v1.js"; +/** + * The voice status of an entity. Screenshare supersedes video, video supersedes voice, and voice supersedes none. + */ +export type VoiceStatus = "none" | "voice" | "video" | "screenshare"; + /** * Voice Participant */ @@ -71,4 +76,17 @@ export class VoiceParticipant { this.#setCamera(data.camera); } } + + /** + * The voice status of a participant. Screenshare supersedes video, video supersedes voice, and voice supersedes none. + */ + get voiceStatus(): VoiceStatus { + if (this.isScreensharing()) { + return "screenshare"; + } + if (this.isCamera()) { + return "video"; + } + return "voice"; + } }