endPair/disconnect: WebRTC tamamen kapatılıyor + tiles temizleniyor
sdk/Peer.js — endPair():
- this.rtc?.destroy() eklendi
- Yerel akışlar durur, RTCPeerConnection kapanır
sdk/index.js — sinyal handler'ları:
- end/pair: peer.rtc?.destroy() (alan taraf da kapatır)
- peer/disconnect: peer.rtc?.destroy() (WebSocket kopunca RTC da kapanır)
public/studio/Studio.js:
_clearPeerTiles(peerId):
- data-peer-id dataset'i ile local + remote grid'den tile'ları kaldırır
- Gizli <audio> elemanını srcObject=null + remove() ile temizler
- CSS.escape ile güvenli selector
tile.dataset.peerId: _addLocalTile ve _addRemoteTile her ikisinde eklendi
tile._audioEl: ses tile'larında referans saklanır (clearPeerTiles için)
_watchIncoming: peer.rtc.on('disconnected') → clearPeerTiles + rebuildPeerItems
end/pair handler: clearPeerTiles(from) çağrısı eklendi
peer/disconnect handler: clearPeerTiles(peer.socketId) çağrısı eklendi
_addLocalTile/_addRemoteTile: peerLabel yerine peer objesi alır
go test -race ./... — yeşil
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d468c95adf
commit
5ebd111af0
|
|
@ -62,14 +62,16 @@ export default class Studio {
|
|||
this._setStatus('online', `${this._peerLabel(peer)} eşleşmesi kuruldu`);
|
||||
});
|
||||
|
||||
// Eşleşme bitti (karşı taraf koptu veya endPair çağrıldı)
|
||||
// Eşleşme bitti — tiles + RTC (SDK zaten destroy çağırdı, ama tiles Studio'ya ait)
|
||||
this.mwse.me.on('end/pair', (from) => {
|
||||
if (typeof from === 'string') this._clearPeerTiles(from);
|
||||
this._rebuildPeerItems();
|
||||
this._setStatus('', `${typeof from === 'string' ? from.slice(-8) : ''} ayrıldı`);
|
||||
});
|
||||
|
||||
// WebSocket bağlantısı kopunca (sayfa yenileme, ağ kesilmesi)
|
||||
// WebSocket koptu → RTC da kapandı (SDK destroy çağırdı)
|
||||
this.mwse.me.on('peer/disconnect', peer => {
|
||||
this._clearPeerTiles(peer.socketId);
|
||||
this._rebuildPeerItems();
|
||||
this._setStatus('error', `${this._peerLabel(peer)} bağlantısı kesildi`);
|
||||
});
|
||||
|
|
@ -173,24 +175,29 @@ export default class Studio {
|
|||
}
|
||||
|
||||
// Yerel (gönderilen) akış tile'ı ekle
|
||||
_addLocalTile(label, stream, peerLabel) {
|
||||
const hasVideo = stream.getVideoTracks().length > 0;
|
||||
_addLocalTile(label, stream, peer) {
|
||||
const peerLabel = typeof peer === 'string' ? peer : this._peerLabel(peer);
|
||||
const peerId = peer?.socketId ?? peerLabel;
|
||||
const hasVideo = stream.getVideoTracks().length > 0;
|
||||
const tile = this._makeTile(
|
||||
label,
|
||||
`→ ${peerLabel}`,
|
||||
stream,
|
||||
hasVideo,
|
||||
true, // muted (geri besleme yok)
|
||||
() => tile.remove() && this._updatePanelVisibility()
|
||||
() => { tile.remove(); this._updatePanelVisibility(); }
|
||||
);
|
||||
tile.dataset.peerId = peerId;
|
||||
this._localGrid.appendChild(tile);
|
||||
this._updatePanelVisibility();
|
||||
}
|
||||
|
||||
// Uzak (gelen) track tile'ı → ses kontrollü
|
||||
_addRemoteTile(track, streams, peerLabel) {
|
||||
const isVideo = track.kind === 'video';
|
||||
const stream = streams?.[0] ?? new MediaStream([track]);
|
||||
_addRemoteTile(track, streams, peer) {
|
||||
const peerLabel = typeof peer === 'string' ? peer : this._peerLabel(peer);
|
||||
const peerId = peer?.socketId ?? peerLabel;
|
||||
const isVideo = track.kind === 'video';
|
||||
const stream = streams?.[0] ?? new MediaStream([track]);
|
||||
|
||||
const tile = document.createElement('div');
|
||||
tile.className = `mwse-stream-tile${isVideo ? '' : ' mwse-stream-tile--audio'}`;
|
||||
|
|
@ -212,6 +219,8 @@ export default class Studio {
|
|||
mediaEl.muted = false;
|
||||
mediaEl.srcObject = stream;
|
||||
document.body.appendChild(mediaEl);
|
||||
// tile'a referans ekle ki _clearPeerTiles kapatabilsin
|
||||
tile._audioEl = mediaEl;
|
||||
|
||||
const icon = document.createElement('div');
|
||||
icon.className = 'mwse-stream-tile__audio-icon';
|
||||
|
|
@ -258,6 +267,7 @@ export default class Studio {
|
|||
|
||||
info.append(lbl, peerEl, muteBtn, closeBtn);
|
||||
tile.appendChild(info);
|
||||
tile.dataset.peerId = peerId;
|
||||
this._remoteGrid.appendChild(tile);
|
||||
this._updatePanelVisibility();
|
||||
|
||||
|
|
@ -588,7 +598,7 @@ export default class Studio {
|
|||
const label = dev.label || dev.deviceId.slice(-6);
|
||||
if (peer.rtc._streams?.has(label)) peer.rtc.removeStream(label);
|
||||
peer.rtc.addStream(label, stream);
|
||||
this._addLocalTile(label, stream, this._peerLabel(peer));
|
||||
this._addLocalTile(label, stream, peer);
|
||||
this._view.popTo(4); this._pushStreamsColumn(peer);
|
||||
} else {
|
||||
this._previewStream(stream, dev.label || title);
|
||||
|
|
@ -662,7 +672,7 @@ export default class Studio {
|
|||
|
||||
if (peer.rtc._streams?.has(type)) peer.rtc.removeStream(type);
|
||||
peer.rtc.addStream(type, stream);
|
||||
this._addLocalTile(type, stream, this._peerLabel(peer));
|
||||
this._addLocalTile(type, stream, peer);
|
||||
this._setStatus('online', `${type} → ${this._peerLabel(peer)}`);
|
||||
this._view.popTo(3);
|
||||
this._pushStreamsColumn(peer);
|
||||
|
|
@ -690,6 +700,21 @@ export default class Studio {
|
|||
peer.rtc.connect({ polite: this.mwse.me.socketId < peer.socketId });
|
||||
}
|
||||
|
||||
// Bir peer'a ait tüm tile'ları temizle (pair bitti veya disconnect)
|
||||
_clearPeerTiles(peerId) {
|
||||
for (const grid of [this._localGrid, this._remoteGrid]) {
|
||||
if (!grid) continue;
|
||||
// dataset.peerId → attribute adı: data-peer-id
|
||||
for (const tile of [...grid.querySelectorAll(`[data-peer-id="${CSS.escape(peerId)}"]`)]) {
|
||||
// Gizli <audio> elemanlarını da kapat
|
||||
const audio = tile._audioEl;
|
||||
if (audio) { audio.srcObject = null; audio.remove(); }
|
||||
tile.remove();
|
||||
}
|
||||
}
|
||||
this._updatePanelVisibility();
|
||||
}
|
||||
|
||||
// Gelen track'leri izle → panel'e ekle
|
||||
_watchIncoming(peer) {
|
||||
// RTC başlatılmazsa gelen :rtcpack: sinyalleri receive() içinde _neg=null
|
||||
|
|
@ -697,9 +722,15 @@ export default class Studio {
|
|||
this._ensureRTC(peer);
|
||||
|
||||
peer.rtc.on('track', (track, streams) => {
|
||||
this._addRemoteTile(track, streams, this._peerLabel(peer));
|
||||
this._addRemoteTile(track, streams, peer);
|
||||
this._setStatus('online', `← ${this._peerLabel(peer)} ${track.kind}`);
|
||||
});
|
||||
|
||||
// RTC kapandığında (endPair, peer/disconnect) tile'ları temizle
|
||||
peer.rtc.on('disconnected', () => {
|
||||
this._clearPeerTiles(peer.socketId);
|
||||
this._rebuildPeerItems();
|
||||
});
|
||||
}
|
||||
|
||||
_previewStream(stream, label) {
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ export default class Peer extends MWSEEventTarget {
|
|||
async endPair() {
|
||||
await this.mwse.EventPooling.request({ type: 'end/pair', to: this.socketId });
|
||||
this.mwse.pairs.delete(this.socketId);
|
||||
this.rtc?.destroy(); // WebRTC bağlantısını kapat, akışları durdur
|
||||
this.forget();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -236,8 +236,8 @@ export default class MWSE {
|
|||
ep.signal('peer/disconnect', ({ id }) => {
|
||||
const peer = this.peer(id, true);
|
||||
this.pairs.delete(id);
|
||||
peer.rtc?.destroy(); // WebSocket kopunca (sayfa yenileme vb.) RTC da kapat
|
||||
peer.emit('disconnect');
|
||||
// me üzerinden de yay, Studio dinleyebilsin.
|
||||
this.peer('me').emit('peer/disconnect', peer);
|
||||
});
|
||||
|
||||
|
|
@ -253,6 +253,7 @@ export default class MWSE {
|
|||
ep.signal('end/pair', ({ from, info }) => {
|
||||
const peer = this.peer(from, true);
|
||||
this.pairs.delete(from);
|
||||
peer.rtc?.destroy(); // karşı taraf endPair çağırdığında da RTC kapat
|
||||
peer.emit('end/pair', info);
|
||||
this.peer('me').emit('end/pair', from, info);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue