Files
discord-decomp/modules/calls/ChannelRTCParticipants.tsx
T
2026-11-01 12:12:55 +02:00

366 lines
13 KiB
TypeScript

// Metro module 10511 (f10512).
import EmbeddedActivitiesStore from "../activities/EmbeddedActivitiesStore";
import ApplicationStreamingStore from "../../stores/ApplicationStreamingStore";
import AuthenticationStore from "../../stores/AuthenticationStore";
import CallStore from "../../stores/CallStore";
import ChannelStore from "../../stores/ChannelStore";
import MediaEngineStore from "../../stores/MediaEngineStore";
import SpeakingStore from "../../stores/SpeakingStore";
import UserStore from "../../stores/UserStore";
import VideoStreamStore from "../../stores/VideoStreamStore";
import VoiceStateStore from "../../stores/VoiceStateStore";
import { ParticipantTypes, isStreamParticipant } from "./CallConstants";
import { ActivityTypes, ChannelTypes } from "../../Constants";
import { MediaEngineContextTypes } from "../../_bundle/Module4250";
import getParticipantUserKey from "./getParticipantUserKey";
import { SecondaryIndexMap } from "../../_bundle/Module3813";
import { getIsSpeaking } from "../../hooks/useIsSpeaking";
import { uniqBy } from "../../_bundle/Module12";
import { ContentClassificationEmbeddedActivityFilterExperiment } from "../activities/ContentClassificationEmbeddedActivityFilterExperiment";
import { isAgeRestrictedClassificationReference } from "../content_classification/ContentClassificationReference";
import NicknameUtils from "../../utils/NicknameUtils";
import { getAvatarDecoration } from "../collectibles/avatar_decorations/useAvatarDecoration";
import { encodeStreamKey } from "../go_live/utils/StreamKeyUtils";
let c7054_18, c7054_20;
const sortKey = function sortKey(a0) {
const type = a0.type;
if (ParticipantTypes.ACTIVITY === type) {
return `\x01${a0.sortKey}`;
}
if (ParticipantTypes.HIDDEN_STREAM !== type && ParticipantTypes.STREAM !== type) {
if (ParticipantTypes.USER === type) {
return `${a0.voiceState?.selfVideo ? "\x03" : a0.voiceState?.selfStream ? "\x04" : "\x05"}${getParticipantUserKey(a0.userNick, a0.user)}`;
}
return void 0;
}
return `${a0.userVideo ? "\x02" : "\x03"}${getParticipantUserKey(a0.userNick, a0.user)}\x03`;
};
c7054_18 = "__EMBEDDED_ACTIVITIES__";
c7054_20 = {
VIDEO: "VIDEO",
STREAM: "STREAM",
FILTERED: "FILTERED",
SPEAKING: "SPEAKING",
ACTIVITY: "ACTIVITY",
NOT_POPPED_OUT: "NOT_POPPED_OUT"
};
class ChannelRTCParticipants {
constructor(a0) {
const r10 = {
__proto__: new.target.prototype,
participants: {},
lastSpoke: null,
guildRingingUsers: null,
poppedOutParticipants: null,
participantByIndex: null
};
r10.lastSpoke = {};
r10.guildRingingUsers = new Set();
r10.poppedOutParticipants = new Set();
r10.participantByIndex = new SecondaryIndexMap((a0) => {
const r8 = a0.type === ParticipantTypes.USER && a0.speaking;
const r9 = [];
if (r8) {
r9.push(c7054_20.SPEAKING);
}
L19: {
if (a0.type === ParticipantTypes.USER) {
if (a0.voiceState?.selfVideo) {
r9.push(c7054_20.VIDEO);
if (a0.localVideoDisabled || a0.isPoppedOut) {
break L19;
}
r9.push(c7054_20.FILTERED);
break L19;
}
}
if (isStreamParticipant(a0)) {
r9.push(c7054_20.STREAM);
if (!(a0.type === ParticipantTypes.HIDDEN_STREAM || a0.streamId == null || a0.isPoppedOut)) {
r9.push(c7054_20.FILTERED);
}
}
}
if (a0.type === ParticipantTypes.ACTIVITY) {
r9.push(c7054_20.ACTIVITY);
}
if (!("isPoppedOut" in a0 && a0.isPoppedOut)) {
r9.push(c7054_20.NOT_POPPED_OUT);
}
return r9;
}, sortKey);
r10.channelId = a0;
return r10;
}
get version() {
return this.participantByIndex.version;
}
size(a0) {
return this.participantByIndex.size(a0);
}
toArray(a0) {
return this.participantByIndex.values(a0, true);
}
rebuild() {
let c18092_0;
const channel = ChannelStore.getChannel(this.channelId);
if (channel != null && channel.type !== ChannelTypes.GUILD_TEXT) {
L5: {
this.call = CallStore.getCall(this.channelId);
if (channel.isPrivate()) {
if (this.call != null && !this.call.unavailable) {
break L5;
}
return false;
}
}
const set = new Set(channel.isGuildVocalOrThread() ? Object.keys(VoiceStateStore.getVoiceStatesForChannel(channel.id)) : channel.recipients);
c18092_0 = set;
set.add(AuthenticationStore.getId());
const size2 = this.guildRingingUsers.size;
let r46 = set;
if (size2 > 0) {
const set2 = new Set([...set, ...this.guildRingingUsers]);
c18092_0 = set2;
r46 = set2;
}
ApplicationStreamingStore.getAllActiveStreamsForChannel(this.channelId).forEach((item) => c18092_0.add(item.ownerId));
this.participantByIndex.clear();
this.participants = {};
r46.forEach((item) => this.updateParticipant(item));
this.updateEmbeddedActivities();
return true;
}
return false;
}
getParticipant(a0) {
let r5 = this.participantByIndex.get(a0);
if (r5 == null) {
r5 = null;
}
return r5;
}
updateEmbeddedActivities() {
return this.updateParticipant(c7054_18);
}
hasEmbeddedActivity() {
return this.size(c7054_20.ACTIVITY) > 0;
}
updateParticipant(a0) {
const r10 = this.participants[a0];
const r14 = a0 === c7054_18 ? this._getParticipantsForEmbeddedActivities() : this._getParticipantsForUser(a0);
let r1 = r10 != null || r14.length !== 0;
if (r1) {
if (r10 != null) {
r10.forEach((item) => {
this.participantByIndex.delete(item.id);
});
}
r14.forEach((item) => {
this.participantByIndex.set(item.id, item);
});
this.participants[a0] = r14;
r1 = true;
}
return r1;
}
updateParticipantSpeaking(a0) {
const userId = a0;
const r5 = this.participants[a0];
let r7 = r5 == null ? void 0 : r5.reduce((acc, item) => {
let r2 = acc;
if (item.type === ParticipantTypes.USER) {
const isSpeaking = getIsSpeaking({
userId,
checkIsMuted: true
});
const isSoundSharing = SpeakingStore.isSoundSharing(userId);
const r26 = this.participantByIndex.get(item.id);
if (!(r26?.type === ParticipantTypes.USER && (r26.speaking === isSpeaking && r26.soundsharing === isSoundSharing))) {
if (isSpeaking) {
this.lastSpoke[userId] = Date.now();
}
this.participantByIndex.set(item.id, {
...item,
speaking: isSpeaking,
lastSpoke: this.lastSpoke[userId],
soundsharing: isSoundSharing
});
r2 = true;
}
return r2;
}
return acc;
}, false);
if (r7 == null) {
r7 = false;
}
return r7;
}
updateParticipantQuality(a0, maxResolution, maxFrameRate) {
const r5 = this.participants[a0];
let r9 = r5 == null ? void 0 : r5.reduce((r1, item) => {
if (item.type === ParticipantTypes.STREAM) {
this.participantByIndex.set(item.id, {
...item,
maxResolution,
maxFrameRate
});
r1 = true;
}
return r1;
}, false);
if (r9 == null) {
r9 = false;
}
return r9;
}
updateGuildRingingUsers(a0, a1) {
const guildRingingUsers = this.guildRingingUsers;
if (a1) {
guildRingingUsers.add(a0);
} else {
guildRingingUsers.delete(a0);
}
}
updateParticipantPoppedOut(a0, a1) {
const poppedOutParticipants = this.poppedOutParticipants;
if (a1) {
poppedOutParticipants.add(a0);
} else {
poppedOutParticipants.delete(a0);
}
}
_getEmbeddedActivities() {
const embeddedActivitiesForChannelIncludingHidden = EmbeddedActivitiesStore.getEmbeddedActivitiesForChannelIncludingHidden(this.channelId);
const selfEmbeddedActivityForChannel = EmbeddedActivitiesStore.getSelfEmbeddedActivityForChannel(this.channelId);
const r16 = selfEmbeddedActivityForChannel != null ? uniqBy([...embeddedActivitiesForChannelIncludingHidden, selfEmbeddedActivityForChannel], (a0) => a0.compositeInstanceId) : embeddedActivitiesForChannelIncludingHidden;
const enabled = ContentClassificationEmbeddedActivityFilterExperiment.getConfig({
location: "rtc_participants"
}).enabled;
return UserStore.getCurrentUser()?.nsfwAllowed ? r16 : enabled ? r16.filter((item) => !isAgeRestrictedClassificationReference(item.contentClassification)) : r16;
}
_getParticipantsForEmbeddedActivities() {
return this._getEmbeddedActivities().map((item, index) => {
const { applicationId, compositeInstanceId } = item;
const id = compositeInstanceId != null ? `activity-${applicationId}-${compositeInstanceId}` : `activity-${applicationId}`;
let participants = item.participants;
if (participants == null) {
participants = [];
}
const participants2 = [...participants];
const channel = ChannelStore.getChannel(this.channelId);
let guildId = channel == null ? void 0 : channel.getGuildId();
if (guildId == null) {
guildId = null;
}
return {
type: ParticipantTypes.ACTIVITY,
id,
applicationId: item.applicationId,
activityType: ActivityTypes.PLAYING,
activityUrl: item.url,
participants: participants2,
guildId,
sortKey: index.toString()
};
});
}
_getParticipantsForUser(a0) {
const r4 = [];
const user = UserStore.getUser(a0);
if (user == null) {
return r4;
}
const voiceStateForChannel = VoiceStateStore.getVoiceStateForChannel(this.channelId, a0);
const voicePlatformForChannel = VoiceStateStore.getVoicePlatformForChannel(this.channelId, a0);
const channel = ChannelStore.getChannel(this.channelId);
const r12 = channel == null ? void 0 : channel.getGuildId();
const call = this.call;
const r34 = call == null;
let ringing2 = void 0;
if (!r34) {
const ringing = call.ringing;
ringing2 = ringing == null ? void 0 : ringing.includes(a0);
}
if (!ringing2) {
ringing2 = this.guildRingingUsers.has(a0);
}
if (ringing2 == null) {
ringing2 = false;
}
if (voiceStateForChannel != null || ringing2) {
const r44 = {
type: ParticipantTypes.USER,
...VideoStreamStore.getUserStreamData(a0, r12),
user,
id: user.id,
voiceState: voiceStateForChannel,
voicePlatform: voicePlatformForChannel,
speaking: getIsSpeaking({
userId: a0,
checkIsMuted: true
})
};
let lastSpoke = this.lastSpoke[a0];
if (lastSpoke == null) {
lastSpoke = 0;
}
r44.lastSpoke = lastSpoke;
r44.soundsharing = SpeakingStore.isSoundSharing(a0);
r44.ringing = ringing2;
r44.userNick = NicknameUtils.getName(r12, this.channelId, user);
r44.userAvatarDecoration = getAvatarDecoration(user, r12);
r44.localVideoDisabled = MediaEngineStore.isLocalVideoDisabled(user.id);
r44.isPoppedOut = this.poppedOutParticipants.has(user.id);
r4.push(r44);
}
let stream = ApplicationStreamingStore.getStreamForUser(a0, r12);
if (stream == null) {
stream = ApplicationStreamingStore.getActiveStreamForUser(a0, r12);
}
if (stream != null && stream.channelId === this.channelId) {
const id = encodeStreamKey(stream);
const participant = this.getParticipant(id);
const r95 = stream.ownerId === AuthenticationStore.getId() && ApplicationStreamingStore.isSelfStreamHidden(this.channelId);
const r101 = participant?.type === ParticipantTypes.STREAM ? {
maxResolution: participant.maxResolution != null ? {
...participant.maxResolution
} : void 0,
maxFrameRate: participant.maxFrameRate
} : null;
const r110 = {
...VideoStreamStore.getUserStreamData(a0, r12, MediaEngineContextTypes.STREAM),
...r101,
type: r95 ? ParticipantTypes.HIDDEN_STREAM : ParticipantTypes.STREAM,
id
};
let userVideo = voiceStateForChannel?.selfVideo;
if (userVideo == null) {
userVideo = false;
}
r110.userVideo = userVideo;
r110.user = user;
r110.userNick = NicknameUtils.getName(r12, this.channelId, user);
r110.stream = stream;
r110.isPoppedOut = this.poppedOutParticipants.has(id);
r4.push(r110);
}
return r4;
}
}
export default ChannelRTCParticipants;
export function getEmbeddedActivityParticipantId({ applicationId, instanceId }) {
return instanceId != null ? `activity-${applicationId}-${instanceId}` : `activity-${applicationId}`;
}
export function activityParticipantIdToApplicationId(a0) {
return a0 != null ? a0.split("-")[1] : a0;
}
export { sortKey };
export function areParticipantsEqual(a0, a1) {
const [, r3] = a0;
const [, r26] = a1;
return r3 === r26;
}
export { c7054_20 as ChannelRTCParticipantsIndexes };