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 { inject } from '@angular/core';
|
||||||
import { ActivatedRouteSnapshot, CanActivateFn } from '@angular/router';
|
import { ActivatedRouteSnapshot, CanActivateFn } from '@angular/router';
|
||||||
import { ErrorReason } from '@lib/models';
|
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';
|
import { WebComponentProperty } from '@lib/typings/ce/webcomponent/properties.model';
|
||||||
|
|
||||||
export const extractRoomQueryParamsGuard: CanActivateFn = (route: ActivatedRouteSnapshot) => {
|
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
|
* Handles the leave redirect URL logic with automatic referrer detection
|
||||||
*/
|
*/
|
||||||
const handleLeaveRedirectUrl = (leaveRedirectUrl: string) => {
|
const handleLeaveRedirectUrl = (leaveRedirectUrl: string | undefined) => {
|
||||||
const navigationService = inject(NavigationService);
|
const navigationService = inject(NavigationService);
|
||||||
|
const appDataService = inject(AppDataService);
|
||||||
|
const isEmbeddedMode = appDataService.isEmbeddedMode();
|
||||||
|
|
||||||
|
// Explicit valid URL provided - use as is
|
||||||
if (leaveRedirectUrl && isValidUrl(leaveRedirectUrl)) {
|
if (leaveRedirectUrl && isValidUrl(leaveRedirectUrl)) {
|
||||||
// If explicitly provided, use it
|
|
||||||
navigationService.setLeaveRedirectUrl(leaveRedirectUrl);
|
navigationService.setLeaveRedirectUrl(leaveRedirectUrl);
|
||||||
} else {
|
return;
|
||||||
// Check if user came from another domain and auto-configure redirect
|
}
|
||||||
|
|
||||||
|
// 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();
|
const autoRedirectUrl = getAutoRedirectUrl();
|
||||||
if (autoRedirectUrl) {
|
if (autoRedirectUrl) {
|
||||||
navigationService.setLeaveRedirectUrl(autoRedirectUrl);
|
navigationService.setLeaveRedirectUrl(autoRedirectUrl);
|
||||||
@ -110,8 +130,6 @@ const getAutoRedirectUrl = (): string | null => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const isValidUrl = (url: string) => {
|
const isValidUrl = (url: string) => {
|
||||||
if (!url) return false;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new URL(url);
|
new URL(url);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -134,7 +134,7 @@ export class ErrorComponent implements OnInit {
|
|||||||
const redirectTo = this.navService.getLeaveRedirectURL();
|
const redirectTo = this.navService.getLeaveRedirectURL();
|
||||||
if (redirectTo) {
|
if (redirectTo) {
|
||||||
// Navigate to the specified redirect URL
|
// Navigate to the specified redirect URL
|
||||||
await this.navService.redirectTo(redirectTo);
|
await this.navService.redirectToLeaveUrl();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -119,7 +119,7 @@ export class EndMeetingComponent implements OnInit {
|
|||||||
const redirectTo = this.navService.getLeaveRedirectURL();
|
const redirectTo = this.navService.getLeaveRedirectURL();
|
||||||
if (redirectTo) {
|
if (redirectTo) {
|
||||||
// Navigate to the specified redirect URL
|
// Navigate to the specified redirect URL
|
||||||
await this.navService.redirectTo(redirectTo);
|
await this.navService.redirectToLeaveUrl();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -248,7 +248,7 @@ export class MeetingComponent implements OnInit {
|
|||||||
const redirectTo = this.navigationService.getLeaveRedirectURL();
|
const redirectTo = this.navigationService.getLeaveRedirectURL();
|
||||||
if (redirectTo) {
|
if (redirectTo) {
|
||||||
// Navigate to the specified redirect URL
|
// Navigate to the specified redirect URL
|
||||||
await this.navigationService.redirectTo(redirectTo);
|
await this.navigationService.redirectToLeaveUrl();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { Location } from '@angular/common';
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Params, Router, UrlTree } from '@angular/router';
|
import { Params, Router, UrlTree } from '@angular/router';
|
||||||
import { ErrorReason } from '@lib/models';
|
import { ErrorReason } from '@lib/models';
|
||||||
@ -12,7 +11,6 @@ export class NavigationService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private location: Location,
|
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
private appDataService: AppDataService
|
private appDataService: AppDataService
|
||||||
) {}
|
) {}
|
||||||
@ -31,6 +29,31 @@ export class NavigationService {
|
|||||||
return this.leaveRedirectUrl;
|
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
|
* 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
|
* @param url - The URL to redirect to
|
||||||
*/
|
*/
|
||||||
async redirectTo(url: string): Promise<void> {
|
async redirectTo(url: string): Promise<void> {
|
||||||
const isExternalURL = /^https?:\/\//.test(url);
|
try {
|
||||||
if (isExternalURL) {
|
let urlTree = this.router.parseUrl(url);
|
||||||
console.log('Redirecting to external URL:', url);
|
await this.router.navigateByUrl(urlTree, { replaceUrl: true });
|
||||||
|
} catch (error) {
|
||||||
if (this.appDataService.isEmbeddedMode()) {
|
console.error('Error navigating to internal route:', error);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,10 @@ export class ThemeService {
|
|||||||
public readonly isDark = computed(() => this._currentTheme() === 'dark');
|
public readonly isDark = computed(() => this._currentTheme() === 'dark');
|
||||||
public readonly isLight = computed(() => this._currentTheme() === 'light');
|
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:
|
* Initializes the theme based on:
|
||||||
@ -39,7 +42,8 @@ export class ThemeService {
|
|||||||
*/
|
*/
|
||||||
public toggleTheme(): void {
|
public toggleTheme(): void {
|
||||||
const newTheme: Theme = this._currentTheme() === 'light' ? 'dark' : 'light';
|
const newTheme: Theme = this._currentTheme() === 'light' ? 'dark' : 'light';
|
||||||
this.setTheme(newTheme); }
|
this.setTheme(newTheme);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the current theme
|
* Changes the current theme
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user