frontend: improve leave redirect URL handling
This commit is contained in:
parent
52974b2883
commit
f02fcb96a9
@ -1,7 +1,13 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn } from '@angular/router';
|
||||
import { ErrorReason } from '@lib/models';
|
||||
import { NavigationService, ParticipantService, RoomService, SessionStorageService } from '@lib/services';
|
||||
import {
|
||||
AppDataService,
|
||||
NavigationService,
|
||||
ParticipantService,
|
||||
RoomService,
|
||||
SessionStorageService
|
||||
} from '@lib/services';
|
||||
import { WebComponentProperty } from '@lib/typings/ce/webcomponent/properties.model';
|
||||
|
||||
export const extractRoomQueryParamsGuard: CanActivateFn = (route: ActivatedRouteSnapshot) => {
|
||||
@ -66,14 +72,28 @@ const extractParams = ({ params, queryParams }: ActivatedRouteSnapshot) => ({
|
||||
/**
|
||||
* Handles the leave redirect URL logic with automatic referrer detection
|
||||
*/
|
||||
const handleLeaveRedirectUrl = (leaveRedirectUrl: string) => {
|
||||
const handleLeaveRedirectUrl = (leaveRedirectUrl: string | undefined) => {
|
||||
const navigationService = inject(NavigationService);
|
||||
const appDataService = inject(AppDataService);
|
||||
const isEmbeddedMode = appDataService.isEmbeddedMode();
|
||||
|
||||
// Explicit valid URL provided - use as is
|
||||
if (leaveRedirectUrl && isValidUrl(leaveRedirectUrl)) {
|
||||
// If explicitly provided, use it
|
||||
navigationService.setLeaveRedirectUrl(leaveRedirectUrl);
|
||||
} else {
|
||||
// Check if user came from another domain and auto-configure redirect
|
||||
return;
|
||||
}
|
||||
|
||||
// Absolute path provided in embedded mode - construct full URL
|
||||
if (isEmbeddedMode && leaveRedirectUrl?.startsWith('/')) {
|
||||
// If in embedded mode and a absolute path is provided, construct full URL based on parent origin
|
||||
const parentUrl = document.referrer;
|
||||
const parentOrigin = new URL(parentUrl).origin;
|
||||
navigationService.setLeaveRedirectUrl(parentOrigin + leaveRedirectUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
// Auto-detect from referrer (only if no explicit URL provided and not embedded)
|
||||
if (!leaveRedirectUrl && !isEmbeddedMode) {
|
||||
const autoRedirectUrl = getAutoRedirectUrl();
|
||||
if (autoRedirectUrl) {
|
||||
navigationService.setLeaveRedirectUrl(autoRedirectUrl);
|
||||
@ -110,8 +130,6 @@ const getAutoRedirectUrl = (): string | null => {
|
||||
};
|
||||
|
||||
const isValidUrl = (url: string) => {
|
||||
if (!url) return false;
|
||||
|
||||
try {
|
||||
new URL(url);
|
||||
return true;
|
||||
|
||||
@ -134,7 +134,7 @@ export class ErrorComponent implements OnInit {
|
||||
const redirectTo = this.navService.getLeaveRedirectURL();
|
||||
if (redirectTo) {
|
||||
// Navigate to the specified redirect URL
|
||||
await this.navService.redirectTo(redirectTo);
|
||||
await this.navService.redirectToLeaveUrl();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -119,7 +119,7 @@ export class EndMeetingComponent implements OnInit {
|
||||
const redirectTo = this.navService.getLeaveRedirectURL();
|
||||
if (redirectTo) {
|
||||
// Navigate to the specified redirect URL
|
||||
await this.navService.redirectTo(redirectTo);
|
||||
await this.navService.redirectToLeaveUrl();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -248,7 +248,7 @@ export class MeetingComponent implements OnInit {
|
||||
const redirectTo = this.navigationService.getLeaveRedirectURL();
|
||||
if (redirectTo) {
|
||||
// Navigate to the specified redirect URL
|
||||
await this.navigationService.redirectTo(redirectTo);
|
||||
await this.navigationService.redirectToLeaveUrl();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Params, Router, UrlTree } from '@angular/router';
|
||||
import { ErrorReason } from '@lib/models';
|
||||
@ -12,7 +11,6 @@ export class NavigationService {
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private location: Location,
|
||||
private sessionStorageService: SessionStorageService,
|
||||
private appDataService: AppDataService
|
||||
) {}
|
||||
@ -31,6 +29,31 @@ export class NavigationService {
|
||||
return this.leaveRedirectUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects the user to the leave redirect URL if set and valid.
|
||||
*/
|
||||
async redirectToLeaveUrl() {
|
||||
const url = this.getLeaveRedirectURL();
|
||||
if (!url) {
|
||||
console.warn('No leave redirect URL set');
|
||||
return;
|
||||
}
|
||||
|
||||
const isExternalURL = /^https?:\/\//.test(url);
|
||||
if (!isExternalURL) {
|
||||
console.error('Leave redirect URL is not a valid external URL:', url);
|
||||
return;
|
||||
}
|
||||
|
||||
const isEmbeddedMode = this.appDataService.isEmbeddedMode();
|
||||
if (isEmbeddedMode) {
|
||||
// Change the top window location if in embedded mode
|
||||
window.top!.location.href = url;
|
||||
} else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to a specific route
|
||||
*
|
||||
@ -50,30 +73,16 @@ export class NavigationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects to internal or external URLs
|
||||
* Redirects to internal URL
|
||||
*
|
||||
* @param url - The URL to redirect to
|
||||
*/
|
||||
async redirectTo(url: string): Promise<void> {
|
||||
const isExternalURL = /^https?:\/\//.test(url);
|
||||
if (isExternalURL) {
|
||||
console.log('Redirecting to external URL:', url);
|
||||
|
||||
if (this.appDataService.isEmbeddedMode()) {
|
||||
// Change the top window location if in embedded mode
|
||||
window.top!.location.href = url;
|
||||
} else {
|
||||
window.location.href = url;
|
||||
}
|
||||
} else {
|
||||
console.log('Redirecting to internal route:', url);
|
||||
|
||||
try {
|
||||
let urlTree = this.router.parseUrl(url);
|
||||
await this.router.navigateByUrl(urlTree, { replaceUrl: true });
|
||||
} catch (error) {
|
||||
console.error('Error navigating to internal route:', error);
|
||||
}
|
||||
try {
|
||||
let urlTree = this.router.parseUrl(url);
|
||||
await this.router.navigateByUrl(urlTree, { replaceUrl: true });
|
||||
} catch (error) {
|
||||
console.error('Error navigating to internal route:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,10 @@ export class ThemeService {
|
||||
public readonly isDark = computed(() => this._currentTheme() === 'dark');
|
||||
public readonly isLight = computed(() => this._currentTheme() === 'light');
|
||||
|
||||
constructor(@Inject(DOCUMENT) private document: Document, protected ovComponentsThemeService: OpenViduThemeService) {}
|
||||
constructor(
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
protected ovComponentsThemeService: OpenViduThemeService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Initializes the theme based on:
|
||||
@ -39,7 +42,8 @@ export class ThemeService {
|
||||
*/
|
||||
public toggleTheme(): void {
|
||||
const newTheme: Theme = this._currentTheme() === 'light' ? 'dark' : 'light';
|
||||
this.setTheme(newTheme); }
|
||||
this.setTheme(newTheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current theme
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user