Files
discord-decomp/modules/voice_panel/native/card/VoicePanelCardLayoutManager.tsx
T
2026-11-01 12:12:55 +02:00

794 lines
26 KiB
TypeScript

// Metro module 10040 (f10041).
import { useLayoutEffect, useState } from "react";
import { PixelRatio } from "react-native";
import ChannelRTCStore from "../../../calls/ChannelRTCStore";
import { BASE_TARGET_CARD_SIZE, VOICE_PANEL_CHUNK_DIVISOR, VoicePanelCTACardDimensionKeys, VoicePanelCTACardDimensions, VoicePanelCardItemType } from "../../VoicePanelConstants";
import { CALL_TILE_GUTTER, EDGE_GUTTER } from "./VoicePanelCardConstants";
import { ParticipantTypes } from "../../../calls/CallConstants";
import { useSharedValue } from "../../../reanimated/ReanimatedRexport";
import updateSharedValueIfChanged_native from "../../../reanimated/utils/updateSharedValueIfChanged.native";
import shallowEqual from "../../../../_bundle/shallowEqual";
import participantHasVideo from "../../../video_calls/participantHasVideo";
import calculateVoicePanelHeaderSpecs from "../header/calculateVoicePanelHeaderSpecs";
import fitCardsInGrid from "../utils/fitCardsInGrid";
import { batchUpdates } from "../../../../_bundle/Module705";
let c6675_15, c6675_16, c6675_17, c6675_18;
const getTargetCardSize = function getTargetCardSize({ windowWidth: windowWidth2, windowHeight: windowHeight2, safeAreaLeft, safeAreaRight }) {
const r1 = windowWidth2 > windowHeight2 ? 4 : 3;
return Math.max(BASE_TARGET_CARD_SIZE, (windowWidth2 - safeAreaLeft - safeAreaRight - CALL_TILE_GUTTER * (r1 - 1)) / r1);
};
c6675_15 = {
id: "invalid",
type: VoicePanelCardItemType.PARTICIPANT,
x: 0,
y: 0,
width: 0,
height: 0,
zIndex: 0
};
c6675_16 = new Set();
c6675_17 = {
enlargeSquare: false,
fillAspectRatio: false
};
c6675_18 = [{
match: new Set(["1,camera", "2,camera", "2,camera,camera"]),
layouts: [{
enlargeSquare: true,
fillAspectRatio: false
}],
global: true
}, {
match: new Set(["1,stream", "2,stream", "3,stream", "2,stream,camera", "3,stream,camera", "3,stream,camera,camera", "3,camera", "3,camera,stream"]),
layouts: [{
enlargeSquare: true,
fillAspectRatio: true
}, {
enlargeSquare: false,
fillAspectRatio: false
}, {
enlargeSquare: false,
fillAspectRatio: false
}]
}];
class VoicePanelCardLayoutManager {
constructor(a0) {
const r8 = {
__proto__: new.target.prototype,
dirty: true,
targetDimensions: new Map(),
cardCoords: null,
chunkedCoords: null,
contentDimensions: null,
layoutCallbacks: null,
managerSubscriptions: null,
items: null,
emitItemChanges: true,
mounted: false,
layoutKey: 0,
emitTimeout: -1,
props: null,
defaultTargetCoords: null
};
r8.cardCoords = new Map();
r8.chunkedCoords = new Map();
r8.contentDimensions = {
width: 0,
height: 0
};
r8.layoutCallbacks = new Set();
r8.managerSubscriptions = new Set();
r8.items = [];
r8.props = {
windowWidth: 0,
windowHeight: 0,
chunkSize: 0,
safeAreaLeft: 0,
safeAreaRight: 0,
safeAreaTop: 0,
safeAreaBottom: 0,
gutter: 0,
controlBarSize: 0
};
r8.defaultTargetCoords = {
width: 0,
height: 0
};
r8.channelId = a0;
return r8;
}
setDirty(a0) {
if (a0 ? !this.dirty : a0) {
this.dirty = true;
this.emitItemChanges = true;
}
}
handleLayoutEffect() {
this.mounted = true;
this.emitLayoutChanges();
}
cleanUp() {
this.mounted = false;
}
updateState(a0, { windowWidth: windowWidth2, windowHeight: windowHeight2, safeAreaLeft, safeAreaRight, safeAreaTop, safeAreaBottom, controlBarSize }) {
const props = {
windowHeight: windowHeight2,
windowWidth: windowWidth2,
chunkSize: windowHeight2 / VOICE_PANEL_CHUNK_DIVISOR,
safeAreaLeft: Math.max(safeAreaLeft, EDGE_GUTTER),
safeAreaRight: Math.max(safeAreaRight, EDGE_GUTTER),
safeAreaBottom: Math.max(safeAreaBottom, EDGE_GUTTER),
safeAreaTop,
gutter: CALL_TILE_GUTTER,
controlBarSize
};
if (!shallowEqual(props, this.props)) {
this.props = props;
this.setDirty(true);
}
const setDirty2 = this.setDirty;
const items = this.items;
setDirty2.call(this, !(a0.length === items.length && !a0.some((item, index) => items[index] !== item)));
this.items = a0;
return this.getContentDimensions();
}
getLayoutKey() {
return this.layoutKey;
}
getChunk(a0) {
let r5 = this.chunkedCoords.get(a0);
if (r5 == null) {
r5 = c6675_16;
}
return r5;
}
getContentDimensions() {
this.computeCardsLayout();
return this.contentDimensions;
}
getCardCoords(a0) {
this.computeCardsLayout();
return this.cardCoords.get(a0);
}
getCardCoordsMap() {
this.computeCardsLayout();
return this.cardCoords;
}
getDefaultTargetDimensions() {
return this.defaultTargetCoords;
}
getTargetDimensions(a0) {
let defaultTargetCoords;
if (a0 == null) {
defaultTargetCoords = this.defaultTargetCoords;
} else if (VoicePanelCTACardDimensionKeys.has(a0)) {
defaultTargetCoords = VoicePanelCTACardDimensions[a0];
} else {
defaultTargetCoords = this.targetDimensions.get(a0);
if (defaultTargetCoords == null) {
defaultTargetCoords = this.defaultTargetCoords;
}
}
return defaultTargetCoords;
}
setTargetDimensions(a0, a1, a2) {
const targetDimensions = this.getTargetDimensions(a0);
if (!(targetDimensions.width === a1 && targetDimensions.height === a2)) {
this.targetDimensions.set(a0, {
width: a1,
height: a2
});
this.setDirty(true);
this.deferredLayoutChange();
}
}
resetTargetDimensions(a0) {
if (this.targetDimensions.has(a0)) {
this.targetDimensions.delete(a0);
this.setDirty(true);
this.deferredLayoutChange();
}
}
setTargetAspectRatio(a0, a1) {
const r6 = a1 === "portrait" ? {
width: 1,
height: 2
} : a1 === "landscape" ? {
width: 2,
height: 1
} : a1 === "square" ? {
width: 1,
height: 1
} : void 0;
const targetDimensions = this.getTargetDimensions(a0);
if (!(targetDimensions.width === r6.width && targetDimensions.height === r6.height)) {
this.targetDimensions.set(a0, r6);
this.setDirty(true);
this.deferredLayoutChange();
}
}
computeCardsLayout() {
let r48, availableHeight, cardSize, columns2;
let c17643_0, windowWidth, windowHeight, gutter, c17643_5, c17643_6, c17643_7, c17643_8, c17643_9, columns, c17643_11, c17643_12, c17643_13, c17643_14, c17643_15, c17643_16, c17643_17, c17643_18, c17643_19, placeItem2;
const _this2 = this;
const _this = this;
if (this.dirty) {
this.cardCoords = new Map();
this.chunkedCoords = new Map();
const props = this.props;
windowWidth = props.windowWidth;
windowHeight = props.windowHeight;
const { safeAreaLeft, safeAreaRight, safeAreaTop, safeAreaBottom } = props;
gutter = props.gutter;
const controlBarSize = props.controlBarSize;
const set4 = new Set();
c17643_5 = set4;
const set3 = new Set();
c17643_6 = set3;
const set2 = new Set();
c17643_7 = set2;
const set = new Set(this.items);
c17643_8 = set;
c17643_9 = `${this.items.length}`;
columns = 0;
const _loop = function _loop(a0) {
let r17, participant;
L10: {
participant = ChannelRTCStore.getParticipant(_this.channelId, a0.id);
if (a0.type === VoicePanelCardItemType.CTA) {
r17 = _this.getTargetDimensions(a0.id);
} else {
const r2 = participant == null;
r17 = void 0;
if (!r2) {
if (participant.type === ParticipantTypes.USER) {
const r24 = participantHasVideo(participant);
r17 = void 0;
if (!r24) {
break L10;
}
}
r17 = participant.type === ParticipantTypes.USER ? _this.defaultTargetCoords : _this.getTargetDimensions(a0.id);
}
}
}
if (r17 != null && participant != null) {
const r37 = {
type: "custom",
item: a0,
forceSquare: participant.type === ParticipantTypes.USER
};
const type = participant.type;
if (ParticipantTypes.ACTIVITY === type) {
c17643_5.add(r37);
} else if (ParticipantTypes.STREAM === type) {
c17643_6.add(r37);
} else if (ParticipantTypes.USER === type) {
c17643_7.add(r37);
}
c17643_9 = c17643_9 + ("," + (participant.type !== ParticipantTypes.STREAM ? participant.type === ParticipantTypes.USER ? "camera" : "activity" : "stream"));
c17643_8.delete(a0);
return void 0;
}
return 1;
};
for (const item of set) {
if (!_loop(item)) {
continue;
}
break;
}
const r29 = set4.size === 0 ? c6675_18.find((item) => item.match.has(c17643_9)) : null;
L16: {
c17643_12 = r29;
availableHeight = Math.max(120, windowHeight - calculateVoicePanelHeaderSpecs({
top: safeAreaTop,
left: safeAreaLeft,
right: safeAreaRight,
bottom: safeAreaBottom
}, EDGE_GUTTER).height - EDGE_GUTTER - controlBarSize - safeAreaBottom);
const availableWidth = Math.max(120, windowWidth - safeAreaLeft - safeAreaRight);
if (r29 == null && !(set4.size > 0)) {
const targetCardSize = getTargetCardSize({
windowWidth,
windowHeight,
safeAreaLeft,
safeAreaRight
});
if (!(this.items.length >= 7) && this.items.length !== 0) {
const r126 = fitCardsInGrid({
cardCount: this.items.length,
gutterSize: gutter,
availableWidth,
availableHeight
});
columns2 = r126.columns;
columns = columns2;
cardSize = r126.cardSize;
break L16;
}
columns = Math.max((windowWidth - safeAreaLeft - safeAreaRight) / targetCardSize | 0, 1);
cardSize = PixelRatio.roundToNearestPixel((windowWidth - safeAreaLeft - safeAreaRight - CALL_TILE_GUTTER * (columns - 1)) / columns);
columns2 = columns;
} else {
columns = Math.max(Math.min((windowWidth - safeAreaLeft - safeAreaRight) / getTargetCardSize({
windowWidth,
windowHeight,
safeAreaLeft,
safeAreaRight
}) | 0, 4), 1);
cardSize = PixelRatio.roundToNearestPixel((windowWidth - safeAreaLeft - safeAreaRight - gutter * (columns - 1)) / columns);
columns2 = columns;
}
}
if (r29?.global === true) {
c17643_11 = r29.layouts[0];
}
const r183 = Math.floor(this.items.length / columns2) + (this.items.length % columns2 == 0 ? 0 : 1);
const defaultTargetCoords = {
width: r29 == null ? columns2 === 1 ? r183 > 1 ? set4.size === 0 ? windowWidth - safeAreaLeft - safeAreaRight : cardSize : cardSize : cardSize : cardSize,
height: r29 == null ? r183 === 1 ? columns2 > 1 ? set4.size === 0 ? availableHeight : cardSize : cardSize : cardSize : cardSize
};
if (!shallowEqual(defaultTargetCoords, this.defaultTargetCoords)) {
this.defaultTargetCoords = defaultTargetCoords;
}
c17643_13 = {
cardWidth: this.defaultTargetCoords.width,
cardHeight: this.defaultTargetCoords.height,
gutter,
totalItems: this.items.length,
windowWidth
};
const r209 = [new Array(columns2).fill(0)];
c17643_14 = r209;
c17643_15 = -1;
c17643_16 = -1;
c17643_17 = -1;
c17643_18 = 0;
const r211 = [];
c17643_19 = r211;
placeItem2 = (a0, a1, a2, a3) => {};
c17643_0 = this.items.length === 1;
for (const item2 of [set4, set3, set2, set]) {
const _loop2 = function _loop2(a0) {
let r46, r125, r126, r127, r128, r149, r151, length2;
if (a0.type === "custom") {
let r53 = c17643_11;
if (r53 == null) {
r53 = c17643_12 == null ? void 0 : c17643_12.layouts[c17643_18];
}
if (r53 == null) {
r53 = c6675_17;
}
const forceSquare = a0.forceSquare;
let r60 = "square";
if (!forceSquare) {
const targetDimensions = _this.getTargetDimensions(a0.item.id);
const r66 = targetDimensions.width / targetDimensions.height;
r60 = r66 >= 1.3 ? "landscape" : r66 <= 0.8 ? "portrait" : "square";
}
const r74 = windowWidth > windowHeight;
r46 = {
item: a0.item,
dimensions: r60 === "portrait" ? r53.fillAspectRatio ? r74 ? {
width: 2,
height: 2
} : {
width: 2,
height: 3 + (c17643_0 ? 1 : 0)
} : {
width: 1,
height: 2
} : r60 === "landscape" ? r53.fillAspectRatio ? r74 ? {
width: 3 + (c17643_0 ? 1 : 0),
height: 2
} : {
width: 2,
height: 2
} : {
width: 2,
height: 1
} : r60 === "square" ? r53.enlargeSquare ? {
width: 2,
height: 2
} : {
width: 1,
height: 1
} : void 0
};
} else {
windowWidth > windowHeight;
let r48 = c17643_11;
if (r48 == null) {
r48 = c6675_17;
}
r46 = {
item: a0,
dimensions: r48.enlargeSquare ? {
width: 2,
height: 2
} : {
width: 1,
height: 1
}
};
}
const { item, dimensions } = r46;
const width = dimensions.width;
let height = dimensions.height;
const { id, type } = item;
const r101 = c17643_15;
const width3 = Math.min(width, columns);
if (columns === 1) {
height = 1;
}
let r21 = r101 + 1;
let r20 = -1;
let r19 = -1;
let r111 = void 0;
while (true) {
let r38 = c17643_14[r21];
const r15 = r20;
const r16 = r19;
const r18 = r21;
const r37 = r111;
if (r38 == null) {
const r117 = new Array(columns).fill(0);
c17643_14.push(r117);
r38 = r117;
}
const r24 = 0 < r38.length;
let r10 = 0;
let r12 = r15;
let r11 = r16;
if (r24) {
do {
const r121 = r38[r10];
const r8 = r10;
if (r121 !== 1) {
const r9 = width3 - 1;
const length = r38.length;
const r123 = r8 + r9;
r12 = r8;
r11 = r18;
if (!(r123 >= length)) {
break;
}
}
r10 = r8 + 1;
length2 = r38.length;
r12 = r15;
r11 = r16;
} while (r10 < length2);
}
L72: {
if (r11 !== -1 && r12 !== -1) {
const r130 = r11 + (height - 1);
let r13 = r11;
let r14 = r12;
let r131 = r13;
let startCol2 = r14;
let startRow2 = r131;
if (startRow2 <= r130) {
do {
let r134 = c17643_14[r13];
const r135 = r13;
const r5 = r14;
const r6 = r131;
if (r134 == null) {
const r142 = new Array(columns).fill(0);
c17643_14.push(r142);
r134 = r142;
}
const r145 = r5 + (width3 - 1);
let r0 = r5;
let r2 = r0;
let r3 = r6;
if (r5 <= r145) {
do {
const r146 = r134[r0];
const r147 = r0;
r2 = -1;
r3 = -1;
if (r146 !== 0) {
break;
}
r0 = r147 + 1;
r149 = r5 + (width3 - 1);
r2 = r5;
r3 = r6;
} while (r0 <= r149);
}
startCol2 = r2;
startRow2 = r3;
if (r2 === -1) {
break;
}
startCol2 = r2;
startRow2 = r3;
if (startRow2 === -1) {
break;
}
r13 = r135 + 1;
r151 = r3 + (height - 1);
r14 = r2;
r131 = r3;
startCol2 = r14;
startRow2 = r131;
} while (r13 <= r151);
}
if (startRow2 !== -1 && startCol2 !== -1) {
const r152 = {
startRow: startRow2,
startCol: startCol2,
width: width3,
height
};
r126 = startCol2;
r127 = startRow2;
r125 = r18;
r128 = r152;
break L72;
}
r125 = r18 + 1;
r126 = startCol2;
r127 = startRow2;
r128 = r37;
} else {
r125 = r18 + 1;
r126 = -1;
r127 = -1;
r128 = r37;
}
}
r20 = r126;
r19 = r127;
r21 = r125;
r111 = r128;
if (r111 != null) {
let r23 = c17643_15;
const { startRow, startCol, width: width2, height: height2 } = r128;
const r157 = startRow + height2;
let r158 = startRow;
if (r158 < r157) {
do {
const r159 = startCol + width2;
const r160 = r158;
let r41 = startCol;
if (r41 < r159) {
do {
c17643_14[r160][r41] = 1;
r41 = r41 + 1;
} while (r41 < startCol + width2);
}
r158 = r160 + 1;
} while (r158 < startRow + height2);
}
let r164 = r23 + 1;
while (true) {
const r165 = c17643_14[r164];
const r166 = r164;
const r167 = r23;
if (r165 != null && r165.indexOf(0) === -1) {
r164 = r166 + 1;
r23 = r166;
continue;
}
c17643_15 = r167;
c17643_17 = Math.min(Math.max(c17643_17, r128.startCol + (r128.width - 1)), columns);
const r183 = {
id,
type,
x: r128.startCol * (c17643_13.gutter + c17643_13.cardWidth),
y: r128.startRow * (c17643_13.gutter + c17643_13.cardHeight),
width: c17643_13.cardWidth * r128.width + (r128.width - 1) * c17643_13.gutter,
height: c17643_13.cardHeight * r128.height + (r128.height - 1) * c17643_13.gutter,
zIndex: c17643_13.totalItems - c17643_18
};
const { y: r212, height: height3 } = r183;
const chunkSize = _this2.props.chunkSize;
const r219 = [r212 / chunkSize | 0, (r212 + height3) / chunkSize | 0];
let r223 = r219[0];
while (r223 <= r219[1]) {
let r228 = _this2.chunkedCoords.get(r223);
const r229 = r223;
if (r228 == null) {
const set = new Set();
_this2.chunkedCoords.set(r229, set);
r228 = set;
}
r228.add(r183);
r223 = r229 + 1;
}
_this2.cardCoords.set(id, r183);
const r252 = Math.max(c17643_16, r128.startRow + r128.height - 1);
c17643_16 = r252;
if (r252 !== c17643_15 && (r128.height === 1 && r128.startRow === c17643_16)) {
c17643_19.push(id);
} else {
c17643_19.length = 0;
}
c17643_18 = c17643_18 + 1;
return void 0;
}
}
}
};
for (const item3 of item2) {
_loop2(item3);
}
}
const r234 = c17643_15;
const r235 = c17643_16;
if (r234 !== r235 && r234 !== -1) {
const r236 = r209[r235];
let r238 = r236[0] === 0;
let r239 = false;
let r240 = 0;
let r242 = r236[Symbol.iterator]();
const next = r242.next;
while (true) {
const r245 = r242 === void 0 ? void 0 : (r48 = next.call(r242)).done ? r242 = void 0 : r48.value;
if (r242 === void 0) {
if (r238) {
break;
}
const r254 = columns2 - r240;
const r264 = PixelRatio.roundToNearestPixel((r254 * this.defaultTargetCoords.width + r254 * gutter) / 2);
for (const item4 of r211) {
const r273 = this.cardCoords.get(item4);
if (r273 != null) {
r273.x = r273.x + r264;
}
}
break;
}
try {
r240 = r240 + r245;
if (!r238) {
if (r245 === 1 && r239) {
r238 = true;
}
if (r245 === 0) {
r239 = true;
}
}
} catch (r253) {
if (r242 !== void 0 && typeof r242.return === "function") {
try {
r242.return();
} catch {}
}
throw r253;
}
}
}
this.contentDimensions = {
width: (() => {
let r17;
if (_this2.items.length === 0) {
const width = _this2.defaultTargetCoords.width;
r17 = width * columns + (columns - 1) * gutter;
} else {
c17643_17 = c17643_17 + 1;
r17 = _this2.defaultTargetCoords.width * c17643_17 + (c17643_17 - 1) * gutter;
}
return r17;
})(),
height: (() => {
if (_this2.items.length === 0) {
return 0;
}
let r0 = c17643_14.length - 1;
let r1 = r0;
while (0 <= r1) {
const r8 = c17643_14[r0];
const r2 = r0;
r1 = r2;
if (r8 == null) {
break;
}
const r15 = r8.indexOf(1);
r1 = r2;
if (r15 >= 0) {
break;
}
r0 = r2 - 1;
r1 = r0;
}
const r16 = r1 + 1;
return r16 * _this2.defaultTargetCoords.height + gutter * (r16 - 1);
})()
};
this.dirty = false;
this.layoutKey = this.layoutKey + 1;
}
}
subscribeFromItem(a0) {
this.layoutCallbacks.add(a0);
return () => {
this.layoutCallbacks.delete(a0);
};
}
subscribeToManager(a0) {
this.managerSubscriptions.add(a0);
return () => {
this.managerSubscriptions.delete(a0);
};
}
emitLayoutChanges() {
if (this.emitItemChanges && this.mounted) {
this.emitItemChanges = false;
batchUpdates(() => {
for (const managerSubscription of this.managerSubscriptions) {
managerSubscription();
}
for (const layoutCallback of this.layoutCallbacks) {
layoutCallback();
}
});
}
}
deferredLayoutChange() {
if (this.emitItemChanges && this.mounted) {
this.emitTimeout = setTimeout(() => {
const r4 = clearTimeout;
r4(this.emitTimeout);
this.emitTimeout = -1;
this.emitLayoutChanges();
}, 1);
}
}
checkDimensionsMismatch(a0, a1) {
return this.props.windowWidth === a0 ? this.props.windowHeight !== a1 ? {
staleWidth: this.props.windowWidth,
staleHeight: this.props.windowHeight,
wasDirty: this.dirty
} : null : {
staleWidth: this.props.windowWidth,
staleHeight: this.props.windowHeight,
wasDirty: this.dirty
};
}
}
export default VoicePanelCardLayoutManager;
export function useCardLayoutCoordsSubscription(a0, a1) {
let r8 = a1.getCardCoords(a0);
if (r8 == null) {
r8 = c6675_15;
}
const sharedValue = useSharedValue({
...r8
});
useLayoutEffect(() => {
const cardCoords = a1.getCardCoords(a0);
if (cardCoords != null) {
updateSharedValueIfChanged_native(sharedValue, cardCoords);
}
return a1.subscribeFromItem(function updateSharedValues() {
const cardCoords = a1.getCardCoords(a0);
if (cardCoords != null) {
updateSharedValueIfChanged_native(sharedValue, cardCoords);
}
});
}, [a0, a1, sharedValue]);
return sharedValue;
}
export function useTargetDimensionsSubscription(a0, a1) {
const sharedValue2 = useSharedValue({
...a1.getTargetDimensions(a0)
});
useLayoutEffect(() => {
updateSharedValueIfChanged_native(sharedValue2, a1.getTargetDimensions(a0));
return a1.subscribeFromItem(function updateSharedValues() {
updateSharedValueIfChanged_native(sharedValue2, a1.getTargetDimensions(a0));
});
}, [a0, a1, sharedValue2]);
return sharedValue2;
}
export function useManagerSubscription(a0) {
const [state, setState] = useState(a0.getLayoutKey());
useLayoutEffect(() => a0.subscribeToManager(() => setState(a0.getLayoutKey())));
return state;
}