Update static/js/12-calls.js
This commit is contained in:
parent
6b5cd404df
commit
6063da595c
@ -44,6 +44,20 @@ Glow.calls.ensureState = () => {
|
|||||||
state.ignoreOffer ||= new Map();
|
state.ignoreOffer ||= new Map();
|
||||||
state.isSettingRemoteAnswerPending ||= new Map();
|
state.isSettingRemoteAnswerPending ||= new Map();
|
||||||
state.panelOpen ??= false;
|
state.panelOpen ??= false;
|
||||||
|
state.metrics ||= {
|
||||||
|
packetLoss: null,
|
||||||
|
uptime: null,
|
||||||
|
latency: null,
|
||||||
|
elapsedSeconds: 0,
|
||||||
|
userCount: 0
|
||||||
|
};
|
||||||
|
state.drag ||= {
|
||||||
|
active: false,
|
||||||
|
x: null,
|
||||||
|
y: null,
|
||||||
|
offsetX: 0,
|
||||||
|
offsetY: 0
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.calls.scopeLabel = invite => {
|
Glow.calls.scopeLabel = invite => {
|
||||||
@ -182,7 +196,8 @@ Glow.calls.upsertPeer = peer => {
|
|||||||
const normalized = {
|
const normalized = {
|
||||||
participantId,
|
participantId,
|
||||||
roomId: peer.roomId || peer.room_id || state.session?.call_id || "",
|
roomId: peer.roomId || peer.room_id || state.session?.call_id || "",
|
||||||
username: peer.username || participantId
|
username: peer.username || participantId,
|
||||||
|
connectionState: peer.connectionState || "connecting"
|
||||||
};
|
};
|
||||||
|
|
||||||
const index = peers.findIndex(item => item.participantId === participantId);
|
const index = peers.findIndex(item => item.participantId === participantId);
|
||||||
@ -301,13 +316,23 @@ Glow.calls.ensurePeerConnection = async peerId => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pc.onconnectionstatechange = () => {
|
pc.onconnectionstatechange = () => {
|
||||||
Glow.calls.debug("pc connection state", peerId, pc.connectionState);
|
const nextState = pc.connectionState || "connecting";
|
||||||
|
Glow.calls.debug("pc connection state", peerId, nextState);
|
||||||
|
|
||||||
|
const peer = state.peers.find(item => item.participantId === peerId);
|
||||||
|
if (peer) {
|
||||||
|
peer.connectionState = nextState;
|
||||||
|
}
|
||||||
|
|
||||||
const bad =
|
const bad =
|
||||||
pc.connectionState === "failed" ||
|
nextState === "failed" ||
|
||||||
pc.connectionState === "disconnected";
|
nextState === "disconnected";
|
||||||
if (bad) {
|
if (bad) {
|
||||||
Glow.showToast(`Connection issue with ${peerId}.`, "error");
|
Glow.showToast(`Connection issue with ${peerId}.`, "error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Glow.calls.renderParticipants();
|
||||||
|
Glow.calls.updateSummaryMetrics();
|
||||||
};
|
};
|
||||||
|
|
||||||
pc.onsignalingstatechange = () => {
|
pc.onsignalingstatechange = () => {
|
||||||
@ -475,6 +500,15 @@ Glow.calls.renderPendingInvites = () => {
|
|||||||
wrap.classList.remove("hidden");
|
wrap.classList.remove("hidden");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Glow.calls.getParticipantStateLabel = peer => {
|
||||||
|
const state = String(peer?.connectionState || "").toLowerCase();
|
||||||
|
if (state === "connected") return "active";
|
||||||
|
if (state === "connecting" || state === "new") return "connecting";
|
||||||
|
if (state === "disconnected") return "disconnected";
|
||||||
|
if (state === "failed") return "reconnecting";
|
||||||
|
return "joined";
|
||||||
|
};
|
||||||
|
|
||||||
Glow.calls.renderParticipants = () => {
|
Glow.calls.renderParticipants = () => {
|
||||||
if (!Glow.els.callParticipants) return;
|
if (!Glow.els.callParticipants) return;
|
||||||
|
|
||||||
@ -504,7 +538,7 @@ Glow.calls.renderParticipants = () => {
|
|||||||
selfRight.className = "call-participant-status";
|
selfRight.className = "call-participant-status";
|
||||||
selfRight.textContent = state.activeCall
|
selfRight.textContent = state.activeCall
|
||||||
? state.muted
|
? state.muted
|
||||||
? "connected · muted"
|
? "connected · muted"
|
||||||
: "connected"
|
: "connected"
|
||||||
: "idle";
|
: "idle";
|
||||||
|
|
||||||
@ -524,12 +558,16 @@ Glow.calls.renderParticipants = () => {
|
|||||||
const row = document.createElement("div");
|
const row = document.createElement("div");
|
||||||
row.className = "call-participant";
|
row.className = "call-participant";
|
||||||
|
|
||||||
const left = document.createElement("div");
|
const left = document.createElement("button");
|
||||||
left.className = "call-participant-name";
|
left.className = "call-participant-name profile-link";
|
||||||
|
left.type = "button";
|
||||||
left.textContent =
|
left.textContent =
|
||||||
participant.display_name || participant.username || `user ${participant.user_id}`;
|
participant.display_name || participant.username || `user ${participant.user_id}`;
|
||||||
if (participant) {
|
Glow.applyUserColor(left, participant);
|
||||||
Glow.applyUserColor(left, participant);
|
if (participant.username) {
|
||||||
|
left.addEventListener("click", () => {
|
||||||
|
Glow.openProfile?.(participant.username);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const right = document.createElement("div");
|
const right = document.createElement("div");
|
||||||
@ -542,7 +580,9 @@ Glow.calls.renderParticipants = () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
right.textContent = matchingPeer ? "connected" : "joined";
|
const label = Glow.calls.getParticipantStateLabel(matchingPeer);
|
||||||
|
right.textContent = label;
|
||||||
|
right.dataset.state = label;
|
||||||
|
|
||||||
row.append(left, right);
|
row.append(left, right);
|
||||||
box.append(row);
|
box.append(row);
|
||||||
@ -560,13 +600,21 @@ Glow.calls.renderParticipants = () => {
|
|||||||
const row = document.createElement("div");
|
const row = document.createElement("div");
|
||||||
row.className = "call-participant";
|
row.className = "call-participant";
|
||||||
|
|
||||||
const left = document.createElement("div");
|
const left = document.createElement("button");
|
||||||
left.className = "call-participant-name";
|
left.className = "call-participant-name profile-link";
|
||||||
|
left.type = "button";
|
||||||
left.textContent = peer.username || peer.participantId;
|
left.textContent = peer.username || peer.participantId;
|
||||||
|
if (peer.username) {
|
||||||
|
left.addEventListener("click", () => {
|
||||||
|
Glow.openProfile?.(peer.username);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const right = document.createElement("div");
|
const right = document.createElement("div");
|
||||||
right.className = "call-participant-status";
|
right.className = "call-participant-status";
|
||||||
right.textContent = "connecting";
|
const label = Glow.calls.getParticipantStateLabel(peer);
|
||||||
|
right.textContent = label;
|
||||||
|
right.dataset.state = label;
|
||||||
|
|
||||||
row.append(left, right);
|
row.append(left, right);
|
||||||
box.append(row);
|
box.append(row);
|
||||||
@ -583,6 +631,54 @@ Glow.calls.renderParticipants = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Glow.calls.updateSummaryMetrics = () => {
|
||||||
|
Glow.calls.ensureState();
|
||||||
|
const state = Glow.calls.state();
|
||||||
|
|
||||||
|
const createdAt =
|
||||||
|
state.activeCall?.groupSession?.created_at ||
|
||||||
|
state.session?.group_session?.created_at ||
|
||||||
|
null;
|
||||||
|
|
||||||
|
let elapsedSeconds = 0;
|
||||||
|
if (createdAt) {
|
||||||
|
const ms = new Date(createdAt).getTime();
|
||||||
|
if (!Number.isNaN(ms)) {
|
||||||
|
elapsedSeconds = Math.max(0, Math.floor((Date.now() - ms) / 1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.metrics.elapsedSeconds = elapsedSeconds;
|
||||||
|
state.metrics.userCount =
|
||||||
|
1 + Glow.calls.listOtherPeers().length;
|
||||||
|
|
||||||
|
if (Glow.els.callUserCountStat) {
|
||||||
|
Glow.els.callUserCountStat.textContent = String(state.metrics.userCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Glow.els.callElapsedStat) {
|
||||||
|
const minutes = Math.floor(elapsedSeconds / 60);
|
||||||
|
const seconds = elapsedSeconds % 60;
|
||||||
|
Glow.els.callElapsedStat.textContent =
|
||||||
|
minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Glow.els.callLatencyStat) {
|
||||||
|
Glow.els.callLatencyStat.textContent =
|
||||||
|
state.metrics.latency == null ? "—" : `${state.metrics.latency} ms`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Glow.els.callPacketLossStat) {
|
||||||
|
Glow.els.callPacketLossStat.textContent =
|
||||||
|
state.metrics.packetLoss == null ? "—" : `${state.metrics.packetLoss}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Glow.els.callUptimeStat) {
|
||||||
|
Glow.els.callUptimeStat.textContent =
|
||||||
|
state.metrics.uptime == null ? "—" : `${state.metrics.uptime}%`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Glow.calls.connectWebSocket = async () => {
|
Glow.calls.connectWebSocket = async () => {
|
||||||
Glow.calls.ensureState();
|
Glow.calls.ensureState();
|
||||||
const state = Glow.calls.state();
|
const state = Glow.calls.state();
|
||||||
@ -604,6 +700,7 @@ Glow.calls.connectWebSocket = async () => {
|
|||||||
state.reconnecting = false;
|
state.reconnecting = false;
|
||||||
state.joining = false;
|
state.joining = false;
|
||||||
Glow.calls.setStatusText("Connected");
|
Glow.calls.setStatusText("Connected");
|
||||||
|
Glow.calls.updateSummaryMetrics();
|
||||||
settled = true;
|
settled = true;
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
@ -641,6 +738,7 @@ Glow.calls.connectWebSocket = async () => {
|
|||||||
if (signal.type === "joined") {
|
if (signal.type === "joined") {
|
||||||
state.selfPeerId = signal.participantId;
|
state.selfPeerId = signal.participantId;
|
||||||
Glow.calls.setStatusText("Call connected");
|
Glow.calls.setStatusText("Call connected");
|
||||||
|
Glow.calls.updateSummaryMetrics();
|
||||||
Glow.renderCallUi();
|
Glow.renderCallUi();
|
||||||
Glow.calls.renderParticipants();
|
Glow.calls.renderParticipants();
|
||||||
return;
|
return;
|
||||||
@ -651,8 +749,10 @@ Glow.calls.connectWebSocket = async () => {
|
|||||||
Glow.calls.upsertPeer({
|
Glow.calls.upsertPeer({
|
||||||
participantId: signal.participantId,
|
participantId: signal.participantId,
|
||||||
roomId: signal.roomId,
|
roomId: signal.roomId,
|
||||||
username: signal.username || signal.participantId
|
username: signal.username || signal.participantId,
|
||||||
|
connectionState: "connecting"
|
||||||
});
|
});
|
||||||
|
Glow.calls.updateSummaryMetrics();
|
||||||
Glow.renderCallUi();
|
Glow.renderCallUi();
|
||||||
Glow.calls.renderParticipants();
|
Glow.calls.renderParticipants();
|
||||||
|
|
||||||
@ -668,6 +768,7 @@ Glow.calls.connectWebSocket = async () => {
|
|||||||
|
|
||||||
if (signal.type === "participant-left") {
|
if (signal.type === "participant-left") {
|
||||||
Glow.calls.removePeer(signal.participantId);
|
Glow.calls.removePeer(signal.participantId);
|
||||||
|
Glow.calls.updateSummaryMetrics();
|
||||||
Glow.renderCallUi();
|
Glow.renderCallUi();
|
||||||
Glow.calls.renderParticipants();
|
Glow.calls.renderParticipants();
|
||||||
Glow.showToast("Peer left call.");
|
Glow.showToast("Peer left call.");
|
||||||
@ -697,7 +798,8 @@ Glow.calls.connectWebSocket = async () => {
|
|||||||
Glow.calls.upsertPeer({
|
Glow.calls.upsertPeer({
|
||||||
participantId: from,
|
participantId: from,
|
||||||
roomId: signal.roomId,
|
roomId: signal.roomId,
|
||||||
username: signal.username || from
|
username: signal.username || from,
|
||||||
|
connectionState: "connecting"
|
||||||
});
|
});
|
||||||
Glow.calls.renderParticipants();
|
Glow.calls.renderParticipants();
|
||||||
|
|
||||||
@ -893,6 +995,13 @@ Glow.calls.resetAll = () => {
|
|||||||
can_invite: false
|
can_invite: false
|
||||||
};
|
};
|
||||||
state.panelOpen = false;
|
state.panelOpen = false;
|
||||||
|
state.metrics = {
|
||||||
|
packetLoss: null,
|
||||||
|
uptime: null,
|
||||||
|
latency: null,
|
||||||
|
elapsedSeconds: 0,
|
||||||
|
userCount: 0
|
||||||
|
};
|
||||||
|
|
||||||
Glow.calls.debug("resetAll complete");
|
Glow.calls.debug("resetAll complete");
|
||||||
};
|
};
|
||||||
@ -927,7 +1036,7 @@ Glow.calls.scheduleReconnect = () => {
|
|||||||
|
|
||||||
clearTimeout(state.reconnectTimer);
|
clearTimeout(state.reconnectTimer);
|
||||||
state.reconnecting = true;
|
state.reconnecting = true;
|
||||||
Glow.calls.setStatusText("Reconnecting…");
|
Glow.calls.setStatusText("Reconnecting…");
|
||||||
Glow.renderCallUi();
|
Glow.renderCallUi();
|
||||||
|
|
||||||
state.reconnectTimer = setTimeout(async () => {
|
state.reconnectTimer = setTimeout(async () => {
|
||||||
@ -938,7 +1047,7 @@ Glow.calls.scheduleReconnect = () => {
|
|||||||
|
|
||||||
Glow.calls.debug("reconnect attempt", scope);
|
Glow.calls.debug("reconnect attempt", scope);
|
||||||
Glow.calls.resetTransportOnly();
|
Glow.calls.resetTransportOnly();
|
||||||
Glow.calls.setStatusText("Reconnecting…");
|
Glow.calls.setStatusText("Reconnecting…");
|
||||||
state.session = await Glow.calls.fetchGroupCallSession(scope);
|
state.session = await Glow.calls.fetchGroupCallSession(scope);
|
||||||
state.permissions = state.session.permissions || state.permissions;
|
state.permissions = state.session.permissions || state.permissions;
|
||||||
state.scope = state.session.scope || state.scope;
|
state.scope = state.session.scope || state.scope;
|
||||||
@ -969,6 +1078,7 @@ Glow.calls.refreshBackendParticipants = async () => {
|
|||||||
Glow.state.calls.permissions = data.permissions || Glow.state.calls.permissions;
|
Glow.state.calls.permissions = data.permissions || Glow.state.calls.permissions;
|
||||||
Glow.state.calls.scope = data.scope || Glow.state.calls.scope;
|
Glow.state.calls.scope = data.scope || Glow.state.calls.scope;
|
||||||
Glow.calls.renderParticipants();
|
Glow.calls.renderParticipants();
|
||||||
|
Glow.calls.updateSummaryMetrics();
|
||||||
Glow.renderCallUi();
|
Glow.renderCallUi();
|
||||||
Glow.calls.debug("backend participants refreshed", data);
|
Glow.calls.debug("backend participants refreshed", data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -1039,15 +1149,15 @@ Glow.renderCallUi = () => {
|
|||||||
if (!busy) {
|
if (!busy) {
|
||||||
statusText = "Idle";
|
statusText = "Idle";
|
||||||
} else if (state.joining) {
|
} else if (state.joining) {
|
||||||
statusText = "Joining call…";
|
statusText = "Joining call…";
|
||||||
} else if (state.reconnecting) {
|
} else if (state.reconnecting) {
|
||||||
statusText = "Reconnecting…";
|
statusText = "Reconnecting…";
|
||||||
} else if (!Glow.calls.wsReady()) {
|
} else if (!Glow.calls.wsReady()) {
|
||||||
statusText = "Connecting…";
|
statusText = "Connecting…";
|
||||||
} else if (peerCount > 0) {
|
} else if (peerCount > 0) {
|
||||||
statusText = `Group call active · ${peerCount} peer(s)`;
|
statusText = `Group call active · ${peerCount} peer(s)`;
|
||||||
} else {
|
} else {
|
||||||
statusText = "Call open · waiting for others";
|
statusText = "Call open · waiting for others";
|
||||||
}
|
}
|
||||||
|
|
||||||
Glow.els.callStatus.textContent = statusText;
|
Glow.els.callStatus.textContent = statusText;
|
||||||
@ -1083,11 +1193,77 @@ Glow.renderCallUi = () => {
|
|||||||
Glow.els.callParticipants.classList.toggle("hidden", !overlayVisible);
|
Glow.els.callParticipants.classList.toggle("hidden", !overlayVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Glow.calls.updateSummaryMetrics();
|
||||||
Glow.calls.renderParticipants();
|
Glow.calls.renderParticipants();
|
||||||
Glow.calls.renderPendingInvites();
|
Glow.calls.renderPendingInvites();
|
||||||
Glow.calls.renderHeaderCallChip();
|
Glow.calls.renderHeaderCallChip();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Glow.calls.applyPanelPosition = () => {
|
||||||
|
const overlay = Glow.els.callOverlay;
|
||||||
|
const drag = Glow.state.calls?.drag;
|
||||||
|
if (!overlay || !drag) return;
|
||||||
|
if (!Number.isFinite(drag.x) || !Number.isFinite(drag.y)) return;
|
||||||
|
|
||||||
|
overlay.style.left = `${drag.x}px`;
|
||||||
|
overlay.style.top = `${drag.y}px`;
|
||||||
|
overlay.style.right = "auto";
|
||||||
|
overlay.style.bottom = "auto";
|
||||||
|
overlay.style.alignItems = "flex-start";
|
||||||
|
overlay.style.justifyContent = "flex-start";
|
||||||
|
};
|
||||||
|
|
||||||
|
Glow.calls.loadPanelPosition = () => {
|
||||||
|
const x = Number(localStorage.getItem("glow_call_panel_x"));
|
||||||
|
const y = Number(localStorage.getItem("glow_call_panel_y"));
|
||||||
|
if (!Number.isFinite(x) || !Number.isFinite(y)) return;
|
||||||
|
Glow.state.calls.drag.x = x;
|
||||||
|
Glow.state.calls.drag.y = y;
|
||||||
|
Glow.calls.applyPanelPosition();
|
||||||
|
};
|
||||||
|
|
||||||
|
Glow.calls.savePanelPosition = () => {
|
||||||
|
const drag = Glow.state.calls?.drag;
|
||||||
|
if (!drag) return;
|
||||||
|
if (!Number.isFinite(drag.x) || !Number.isFinite(drag.y)) return;
|
||||||
|
localStorage.setItem("glow_call_panel_x", String(drag.x));
|
||||||
|
localStorage.setItem("glow_call_panel_y", String(drag.y));
|
||||||
|
};
|
||||||
|
|
||||||
|
Glow.calls.beginDrag = event => {
|
||||||
|
Glow.calls.ensureState();
|
||||||
|
const overlay = Glow.els.callOverlay;
|
||||||
|
if (!overlay) return;
|
||||||
|
|
||||||
|
const rect = overlay.getBoundingClientRect();
|
||||||
|
Glow.state.calls.drag.active = true;
|
||||||
|
Glow.state.calls.drag.x = rect.left;
|
||||||
|
Glow.state.calls.drag.y = rect.top;
|
||||||
|
Glow.state.calls.drag.offsetX = event.clientX - rect.left;
|
||||||
|
Glow.state.calls.drag.offsetY = event.clientY - rect.top;
|
||||||
|
};
|
||||||
|
|
||||||
|
Glow.calls.onDrag = event => {
|
||||||
|
const drag = Glow.state.calls?.drag;
|
||||||
|
const overlay = Glow.els.callOverlay;
|
||||||
|
if (!drag?.active || !overlay) return;
|
||||||
|
|
||||||
|
const maxX = Math.max(0, window.innerWidth - overlay.offsetWidth);
|
||||||
|
const maxY = Math.max(0, window.innerHeight - overlay.offsetHeight);
|
||||||
|
|
||||||
|
drag.x = Math.min(maxX, Math.max(0, event.clientX - drag.offsetX));
|
||||||
|
drag.y = Math.min(maxY, Math.max(0, event.clientY - drag.offsetY));
|
||||||
|
|
||||||
|
Glow.calls.applyPanelPosition();
|
||||||
|
};
|
||||||
|
|
||||||
|
Glow.calls.endDrag = () => {
|
||||||
|
const drag = Glow.state.calls?.drag;
|
||||||
|
if (!drag) return;
|
||||||
|
drag.active = false;
|
||||||
|
Glow.calls.savePanelPosition();
|
||||||
|
};
|
||||||
|
|
||||||
Glow.startCall = async () => {
|
Glow.startCall = async () => {
|
||||||
Glow.calls.ensureState();
|
Glow.calls.ensureState();
|
||||||
|
|
||||||
@ -1105,7 +1281,7 @@ Glow.startCall = async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Glow.state.calls.joining = true;
|
Glow.state.calls.joining = true;
|
||||||
Glow.calls.setStatusText("Preparing call…");
|
Glow.calls.setStatusText("Preparing call…");
|
||||||
|
|
||||||
const session = await Glow.calls.fetchGroupCallSession(scope);
|
const session = await Glow.calls.fetchGroupCallSession(scope);
|
||||||
Glow.state.calls.session = session;
|
Glow.state.calls.session = session;
|
||||||
@ -1129,14 +1305,15 @@ Glow.startCall = async () => {
|
|||||||
Glow.state.calls.panelOpen = true;
|
Glow.state.calls.panelOpen = true;
|
||||||
|
|
||||||
Glow.openCallPanel();
|
Glow.openCallPanel();
|
||||||
Glow.calls.setStatusText("Connecting microphone…");
|
Glow.calls.setStatusText("Connecting microphone…");
|
||||||
await Glow.calls.ensureLocalAudio();
|
await Glow.calls.ensureLocalAudio();
|
||||||
Glow.calls.setStatusText("Joining call…");
|
Glow.calls.setStatusText("Joining call…");
|
||||||
await Glow.apiJoinGroupCall(session.group_session.id);
|
await Glow.apiJoinGroupCall(session.group_session.id);
|
||||||
await Glow.calls.connectWebSocket();
|
await Glow.calls.connectWebSocket();
|
||||||
Glow.calls.startParticipantSync();
|
Glow.calls.startParticipantSync();
|
||||||
Glow.calls.startHeartbeat();
|
Glow.calls.startHeartbeat();
|
||||||
Glow.state.calls.joining = false;
|
Glow.state.calls.joining = false;
|
||||||
|
Glow.calls.updateSummaryMetrics();
|
||||||
Glow.renderCallUi();
|
Glow.renderCallUi();
|
||||||
Glow.showToast("Group call ready.");
|
Glow.showToast("Group call ready.");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -1164,7 +1341,7 @@ Glow.leaveCall = async () => {
|
|||||||
if (!activeCall) return;
|
if (!activeCall) return;
|
||||||
|
|
||||||
Glow.state.calls.leaving = true;
|
Glow.state.calls.leaving = true;
|
||||||
Glow.calls.setStatusText("Leaving call…");
|
Glow.calls.setStatusText("Leaving call…");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Glow.calls.sendSignal({ type: "hangup" });
|
Glow.calls.sendSignal({ type: "hangup" });
|
||||||
@ -1199,7 +1376,7 @@ Glow.endCallForEveryone = async () => {
|
|||||||
if (!values) return;
|
if (!values) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Glow.calls.setStatusText("Ending call…");
|
Glow.calls.setStatusText("Ending call…");
|
||||||
await Glow.apiEndGroupCall(activeCall.groupSession.id);
|
await Glow.apiEndGroupCall(activeCall.groupSession.id);
|
||||||
Glow.showToast("Call ended.");
|
Glow.showToast("Call ended.");
|
||||||
await Glow.endLocalCallUi();
|
await Glow.endLocalCallUi();
|
||||||
@ -1331,7 +1508,7 @@ Glow.calls.openIncomingInviteDialog = async invite => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Glow.state.calls.joining = true;
|
Glow.state.calls.joining = true;
|
||||||
Glow.calls.setStatusText("Joining call…");
|
Glow.calls.setStatusText("Joining call…");
|
||||||
|
|
||||||
const session = await Glow.calls.acceptInvite(invite.id);
|
const session = await Glow.calls.acceptInvite(invite.id);
|
||||||
|
|
||||||
@ -1356,16 +1533,17 @@ Glow.calls.openIncomingInviteDialog = async invite => {
|
|||||||
Glow.state.calls.panelOpen = true;
|
Glow.state.calls.panelOpen = true;
|
||||||
|
|
||||||
Glow.openCallPanel();
|
Glow.openCallPanel();
|
||||||
Glow.calls.setStatusText("Connecting microphone…");
|
Glow.calls.setStatusText("Connecting microphone…");
|
||||||
await Glow.calls.ensureLocalAudio();
|
await Glow.calls.ensureLocalAudio();
|
||||||
if (session.group_session?.id) {
|
if (session.group_session?.id) {
|
||||||
Glow.calls.setStatusText("Joining call…");
|
Glow.calls.setStatusText("Joining call…");
|
||||||
await Glow.apiJoinGroupCall(session.group_session.id);
|
await Glow.apiJoinGroupCall(session.group_session.id);
|
||||||
}
|
}
|
||||||
await Glow.calls.connectWebSocket();
|
await Glow.calls.connectWebSocket();
|
||||||
Glow.calls.startParticipantSync();
|
Glow.calls.startParticipantSync();
|
||||||
Glow.calls.startHeartbeat();
|
Glow.calls.startHeartbeat();
|
||||||
Glow.state.calls.joining = false;
|
Glow.state.calls.joining = false;
|
||||||
|
Glow.calls.updateSummaryMetrics();
|
||||||
Glow.renderCallUi();
|
Glow.renderCallUi();
|
||||||
Glow.showToast("Joined group call.");
|
Glow.showToast("Joined group call.");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -1429,3 +1607,29 @@ Glow.els.endCallButton?.addEventListener("click", () => {
|
|||||||
Glow.els.addToCallButton?.addEventListener("click", () => {
|
Glow.els.addToCallButton?.addEventListener("click", () => {
|
||||||
Glow.openAddToCallDialog?.();
|
Glow.openAddToCallDialog?.();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Glow.els.callDragHandle?.addEventListener("mousedown", event => {
|
||||||
|
event.preventDefault();
|
||||||
|
Glow.calls.beginDrag(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("mousemove", event => {
|
||||||
|
Glow.calls.onDrag?.(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("mouseup", () => {
|
||||||
|
Glow.calls.endDrag?.();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("resize", () => {
|
||||||
|
if (Glow.state.calls?.panelOpen) {
|
||||||
|
Glow.calls.applyPanelPosition?.();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Glow.calls.loadPanelPosition?.();
|
||||||
|
setInterval(() => {
|
||||||
|
if (Glow.state.calls?.activeCall) {
|
||||||
|
Glow.calls.updateSummaryMetrics?.();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
Loading…
x
Reference in New Issue
Block a user