initial commit — SIP B2BUA + WebRTC bridge with Rust codec engine
Full-featured SIP router with multi-provider trunking, browser softphone via WebRTC, real-time Opus/G.722/PCM transcoding in Rust, RNNoise ML noise suppression, Kokoro neural TTS announcements, and a Lit-based web dashboard with live call monitoring and REST API.
This commit is contained in:
64
ts_web/router.ts
Normal file
64
ts_web/router.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* URL router for the SipRouter dashboard.
|
||||
* Maps URL paths to views in dees-simple-appdash.
|
||||
*/
|
||||
|
||||
const VIEWS = ['overview', 'calls', 'phone', 'contacts', 'providers', 'log'] as const;
|
||||
type TViewSlug = (typeof VIEWS)[number];
|
||||
|
||||
class AppRouter {
|
||||
private currentView: TViewSlug = 'overview';
|
||||
private onNavigate: ((view: TViewSlug) => void) | null = null;
|
||||
private suppressPush = false;
|
||||
|
||||
init(): void {
|
||||
// Parse initial URL.
|
||||
const path = location.pathname.replace(/^\/+/, '').split('/')[0] || 'overview';
|
||||
if (VIEWS.includes(path as TViewSlug)) {
|
||||
this.currentView = path as TViewSlug;
|
||||
}
|
||||
|
||||
// Handle browser back/forward.
|
||||
window.addEventListener('popstate', () => {
|
||||
const p = location.pathname.replace(/^\/+/, '').split('/')[0] || 'overview';
|
||||
if (VIEWS.includes(p as TViewSlug)) {
|
||||
this.suppressPush = true;
|
||||
this.navigateTo(p as TViewSlug);
|
||||
this.suppressPush = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setNavigateHandler(handler: (view: TViewSlug) => void): void {
|
||||
this.onNavigate = handler;
|
||||
}
|
||||
|
||||
navigateTo(view: TViewSlug, skipCallback = false): void {
|
||||
this.currentView = view;
|
||||
if (!this.suppressPush) {
|
||||
const url = `/${view}`;
|
||||
if (location.pathname !== url) {
|
||||
history.pushState(null, '', url);
|
||||
}
|
||||
}
|
||||
if (!skipCallback) {
|
||||
this.onNavigate?.(view);
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the user selects a tab in dees-simple-appdash. */
|
||||
onViewSelect(viewName: string): void {
|
||||
const slug = viewName.toLowerCase().replace(/\s+/g, '-');
|
||||
const mapped = VIEWS.find((v) => v === slug || viewName.toLowerCase().startsWith(v));
|
||||
if (mapped) {
|
||||
this.navigateTo(mapped);
|
||||
}
|
||||
}
|
||||
|
||||
getCurrentView(): TViewSlug {
|
||||
return this.currentView;
|
||||
}
|
||||
}
|
||||
|
||||
export const appRouter = new AppRouter();
|
||||
export type { TViewSlug };
|
||||
Reference in New Issue
Block a user