Skip to content

Commit 455ea7f

Browse files
jordaneclaude
authored andcommitted
fix(meeting-join): prevent infinite auto-join loop and ensure new tab opening
- Remove isJoining() dependency from auto-join effect to prevent re-triggering - Eliminate hasAutoJoined flag resets that caused infinite loops - Remove popup blocker detection and toast notifications - Ensure all join buttons use click handler for consistent new tab behavior - Simplify openMeetingSecurely method for reliable URL opening 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Jordan Evans <jevans@linuxfoundation.org>
1 parent 7ded74d commit 455ea7f

File tree

2 files changed

+26
-56
lines changed

2 files changed

+26
-56
lines changed

apps/lfx-one/src/app/modules/meeting/meeting-join/meeting-join.component.html

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -232,25 +232,14 @@ <h4 class="font-medium text-gray-900 font-sans">{{ user.name }}</h4>
232232
}
233233
</div>
234234
<div class="ml-4">
235-
@if (meeting().join_url) {
236-
<lfx-button
237-
size="small"
238-
[href]="canJoinMeeting() ? joinUrlWithParams() : undefined"
239-
[disabled]="!canJoinMeeting()"
240-
severity="primary"
241-
label="Join Meeting"
242-
icon="fa-light fa-sign-in"
243-
[attr.data-testid]="'join-meeting-button-authenticated'"></lfx-button>
244-
} @else {
245-
<lfx-button
246-
size="small"
247-
severity="primary"
248-
label="Join Meeting"
249-
[disabled]="!canJoinMeeting()"
250-
icon="fa-light fa-sign-in"
251-
[attr.data-testid]="'join-meeting-button-authenticated'"
252-
(click)="onJoinMeeting()"></lfx-button>
253-
}
235+
<lfx-button
236+
size="small"
237+
severity="primary"
238+
label="Join Meeting"
239+
[disabled]="!canJoinMeeting()"
240+
icon="fa-light fa-sign-in"
241+
[attr.data-testid]="'join-meeting-button-authenticated'"
242+
(click)="onJoinMeeting()"></lfx-button>
254243
</div>
255244
</div>
256245
</ng-template>
@@ -343,25 +332,14 @@ <h4 class="font-medium text-gray-900 font-sans">Enter your information</h4>
343332
</div>
344333
}
345334
<div class="flex items-center">
346-
@if (meeting().join_url) {
347-
<lfx-button
348-
size="small"
349-
[href]="joinForm.invalid || !canJoinMeeting() ? undefined : joinUrlWithParams()"
350-
severity="primary"
351-
label="Join Meeting"
352-
icon="fa-light fa-sign-in"
353-
[disabled]="joinForm.invalid || !canJoinMeeting()"
354-
[attr.data-testid]="'join-meeting-button-form'"></lfx-button>
355-
} @else {
356-
<lfx-button
357-
size="small"
358-
severity="primary"
359-
label="Join Meeting"
360-
[disabled]="joinForm.invalid || !canJoinMeeting()"
361-
icon="fa-light fa-sign-in"
362-
[attr.data-testid]="'join-meeting-button-form'"
363-
(click)="onJoinMeeting()"></lfx-button>
364-
}
335+
<lfx-button
336+
size="small"
337+
severity="primary"
338+
label="Join Meeting"
339+
[disabled]="joinForm.invalid || !canJoinMeeting()"
340+
icon="fa-light fa-sign-in"
341+
[attr.data-testid]="'join-meeting-button-form'"
342+
(click)="onJoinMeeting()"></lfx-button>
365343
</div>
366344
</div>
367345
</form>

apps/lfx-one/src/app/modules/meeting/meeting-join/meeting-join.component.ts

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export class MeetingJoinComponent implements OnDestroy {
110110
}
111111

112112
// Schedule auto-join only if conditions are met
113-
if (authenticated && user && user.email && canJoinMeeting && !hasAutoJoined && meeting && meeting.uid && !this.isJoining()) {
113+
if (authenticated && user && user.email && canJoinMeeting && !hasAutoJoined && meeting && meeting.uid) {
114114
// Set a timeout to prevent rapid-fire execution
115115
this.autoJoinTimeout = setTimeout(() => {
116116
this.performAutoJoin();
@@ -166,7 +166,7 @@ export class MeetingJoinComponent implements OnDestroy {
166166
const hasAutoJoined = this.hasAutoJoined();
167167
const meeting = this.meeting();
168168

169-
if (!authenticated || !user || !user.email || !canJoinMeeting || hasAutoJoined || !meeting || !meeting.uid || this.isJoining()) {
169+
if (!authenticated || !user || !user.email || !canJoinMeeting || hasAutoJoined || !meeting || !meeting.uid) {
170170
return; // Conditions no longer met, abort
171171
}
172172

@@ -210,8 +210,7 @@ export class MeetingJoinComponent implements OnDestroy {
210210
detail: 'Could not automatically join the meeting. Please use the Join Meeting button.',
211211
life: 5000,
212212
});
213-
// Reset auto-join flag so user can try manually
214-
this.hasAutoJoined.set(false);
213+
// Don't reset auto-join flag - we should only try once automatically
215214
},
216215
});
217216
}
@@ -435,23 +434,16 @@ export class MeetingJoinComponent implements OnDestroy {
435434
}
436435

437436
private openMeetingSecurely(url: string): void {
437+
// Check if we're running in the browser (not SSR)
438+
if (typeof window === 'undefined') {
439+
return;
440+
}
441+
438442
// Try to open the meeting URL securely
439443
const newWindow = window.open(url, '_blank', 'noopener,noreferrer');
440444

441-
// Handle popup blocker scenarios
442-
if (!newWindow || newWindow.closed || typeof newWindow.closed === 'undefined') {
443-
// Popup was blocked, show user message with manual link
444-
this.messageService.add({
445-
severity: 'warn',
446-
summary: 'Popup Blocked',
447-
detail: 'Your browser blocked the meeting popup. Please allow popups for this site and try again, or click the Join Meeting button.',
448-
life: 8000,
449-
});
450-
451-
// Reset auto-join flag so user can try manually
452-
this.hasAutoJoined.set(false);
453-
} else {
454-
// Clear opener reference for security (prevent tabnabbing)
445+
// Clear opener reference for security (prevent tabnabbing)
446+
if (newWindow) {
455447
newWindow.opener = null;
456448
}
457449
}

0 commit comments

Comments
 (0)