Fix meeting audio playback and restyle room detail actions.
Deploy Ladill Meet / deploy (push) Successful in 39s
Deploy Ladill Meet / deploy (push) Successful in 39s
Unlock LiveKit audio after user gesture, respect join mute/video settings, and replace plain links with btn-secondary pills on the meeting details page. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -30,6 +30,9 @@ function meetRoom() {
|
||||
captionText: '',
|
||||
displayName: '',
|
||||
canPublish: true,
|
||||
muteOnJoin: true,
|
||||
videoOffOnJoin: false,
|
||||
audioPlaybackBlocked: false,
|
||||
isWebinar: false,
|
||||
qaItems: [],
|
||||
activePolls: [],
|
||||
@@ -95,6 +98,8 @@ function meetRoom() {
|
||||
this.isHost = el.dataset.isHost === '1';
|
||||
this.canPublish = el.dataset.canPublish !== '0';
|
||||
this.isWebinar = el.dataset.isWebinar === '1';
|
||||
this.muteOnJoin = el.dataset.muteOnJoin === '1';
|
||||
this.videoOffOnJoin = el.dataset.videoOffOnJoin === '1';
|
||||
this.isRecording = el.dataset.recordingActive === '1';
|
||||
this.isLocked = el.dataset.locked === '1';
|
||||
this.watermark = el.dataset.watermark === '1';
|
||||
@@ -170,6 +175,9 @@ function meetRoom() {
|
||||
|
||||
room.on(RoomEvent.TrackSubscribed, (track, publication, participant) => {
|
||||
this.attachTrack(track, publication, participant);
|
||||
if (track.kind === Track.Kind.Audio) {
|
||||
this.ensureAudioPlayback();
|
||||
}
|
||||
});
|
||||
room.on(RoomEvent.TrackUnsubscribed, (track, publication, participant) => {
|
||||
track.detach();
|
||||
@@ -218,6 +226,15 @@ function meetRoom() {
|
||||
room.on(RoomEvent.Disconnected, () => {
|
||||
this.connectionStatus = 'Disconnected';
|
||||
});
|
||||
room.on(RoomEvent.AudioPlaybackStatusChanged, () => {
|
||||
this.audioPlaybackBlocked = room ? !room.canPlaybackAudio : false;
|
||||
if (this.audioPlaybackBlocked) {
|
||||
this.connectionStatus = 'Connected — click anywhere to enable audio';
|
||||
this.registerAudioUnlockGesture();
|
||||
} else if (this.connectionStatus.includes('enable audio')) {
|
||||
this.connectionStatus = 'Connected';
|
||||
}
|
||||
});
|
||||
|
||||
await room.prepareConnection(this.config.url, this.config.token);
|
||||
|
||||
@@ -240,6 +257,8 @@ function meetRoom() {
|
||||
this.isVideoOff = true;
|
||||
}
|
||||
|
||||
await this.ensureAudioPlayback();
|
||||
|
||||
this.setupCaptionPipeline();
|
||||
|
||||
this.updateParticipantTile(room.localParticipant);
|
||||
@@ -275,12 +294,24 @@ function meetRoom() {
|
||||
},
|
||||
|
||||
async enableLocalMedia(activeRoom, attempts = 3) {
|
||||
const wantMic = !this.muteOnJoin || this.isHost;
|
||||
const wantCamera = !this.videoOffOnJoin;
|
||||
|
||||
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
||||
try {
|
||||
await activeRoom.localParticipant.setMicrophoneEnabled(true);
|
||||
await activeRoom.localParticipant.setCameraEnabled(false);
|
||||
await activeRoom.localParticipant.setMicrophoneEnabled(wantMic);
|
||||
await activeRoom.localParticipant.setCameraEnabled(wantCamera);
|
||||
this.syncLocalMediaState();
|
||||
this.updateParticipantTile(activeRoom.localParticipant);
|
||||
|
||||
if (wantCamera) {
|
||||
activeRoom.localParticipant.videoTrackPublications.forEach((pub) => {
|
||||
if (pub.track && !pub.isMuted && pub.source !== Track.Source.ScreenShare) {
|
||||
this.attachTrack(pub.track, pub, activeRoom.localParticipant);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.connectionStatus = 'Connected';
|
||||
return;
|
||||
} catch (mediaError) {
|
||||
@@ -299,6 +330,40 @@ function meetRoom() {
|
||||
}
|
||||
},
|
||||
|
||||
async ensureAudioPlayback() {
|
||||
if (!room || room.canPlaybackAudio) {
|
||||
this.audioPlaybackBlocked = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await room.startAudio();
|
||||
this.audioPlaybackBlocked = false;
|
||||
if (this.connectionStatus.includes('enable audio')) {
|
||||
this.connectionStatus = 'Connected';
|
||||
}
|
||||
} catch (e) {
|
||||
this.audioPlaybackBlocked = true;
|
||||
this.registerAudioUnlockGesture();
|
||||
}
|
||||
},
|
||||
|
||||
registerAudioUnlockGesture() {
|
||||
if (this._audioUnlockRegistered) return;
|
||||
this._audioUnlockRegistered = true;
|
||||
|
||||
const unlock = async () => {
|
||||
await this.ensureAudioPlayback();
|
||||
if (!this.audioPlaybackBlocked) {
|
||||
document.removeEventListener('click', unlock, true);
|
||||
document.removeEventListener('keydown', unlock, true);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', unlock, true);
|
||||
document.addEventListener('keydown', unlock, true);
|
||||
},
|
||||
|
||||
syncLocalMediaState() {
|
||||
if (!room) return;
|
||||
|
||||
@@ -502,6 +567,8 @@ function meetRoom() {
|
||||
|
||||
setupCaptionPipeline() {
|
||||
if (!this.liveCaptions || !this.config.captionUrl) return;
|
||||
if (room?.localParticipant?.isMicrophoneEnabled) return;
|
||||
|
||||
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||||
if (!SpeechRecognition) return;
|
||||
|
||||
@@ -653,6 +720,7 @@ function meetRoom() {
|
||||
|
||||
async toggleMute() {
|
||||
if (!room) return;
|
||||
await this.ensureAudioPlayback();
|
||||
const enabled = room.localParticipant.isMicrophoneEnabled;
|
||||
await room.localParticipant.setMicrophoneEnabled(!enabled);
|
||||
this.syncLocalMediaState();
|
||||
@@ -661,6 +729,7 @@ function meetRoom() {
|
||||
|
||||
async toggleVideo() {
|
||||
if (!room) return;
|
||||
await this.ensureAudioPlayback();
|
||||
const enabled = room.localParticipant.isCameraEnabled;
|
||||
await room.localParticipant.setCameraEnabled(!enabled);
|
||||
this.syncLocalMediaState();
|
||||
|
||||
Reference in New Issue
Block a user