/** * @fileoverview URL Router Service for Rantii * @author retoor * @description Handles URL routing and navigation state management * @keywords router, navigation, url, history, routing */ class Router { constructor() { this.routes = new Map(); this.currentRoute = null; this.currentParams = {}; this.onRouteChange = null; this.basePath = this.detectBasePath(); } detectBasePath() { const path = window.location.pathname; const htmlIndex = path.lastIndexOf('.html'); if (htmlIndex !== -1) { return path.substring(0, path.lastIndexOf('/') + 1); } return path.endsWith('/') ? path : path + '/'; } init() { window.addEventListener('popstate', () => this.handleRoute()); this.handleRoute(); } register(name, handler) { this.routes.set(name, handler); } getParams() { const params = new URLSearchParams(window.location.search); const result = {}; for (const [key, value] of params) { result[key] = value; } return result; } handleRoute() { const params = this.getParams(); this.currentParams = params; let routeName = 'home'; if (params.rant) { routeName = 'rant'; } else if (params.user) { routeName = 'user'; } else if (params.search !== undefined) { routeName = 'search'; } else if (params.notifications !== undefined) { routeName = 'notifications'; } else if (params.settings !== undefined) { routeName = 'settings'; } else if (params.login !== undefined) { routeName = 'login'; } else if (params.weekly !== undefined) { routeName = 'weekly'; } else if (params.collabs !== undefined) { routeName = 'collabs'; } else if (params.stories !== undefined) { routeName = 'stories'; } this.currentRoute = routeName; const handler = this.routes.get(routeName); if (handler) { handler(params); } if (this.onRouteChange) { this.onRouteChange(routeName, params); } window.dispatchEvent(new CustomEvent('rantii:route-change', { detail: { route: routeName, params } })); } navigate(routeName, params = {}) { const url = this.buildUrl(params); window.history.pushState({ route: routeName, params }, '', url); this.handleRoute(); } replace(routeName, params = {}) { const url = this.buildUrl(params); window.history.replaceState({ route: routeName, params }, '', url); this.handleRoute(); } buildUrl(params = {}) { const searchParams = new URLSearchParams(); Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null && value !== '') { searchParams.set(key, value); } else if (value === '') { searchParams.set(key, ''); } }); const queryString = searchParams.toString(); const currentPath = window.location.pathname; return queryString ? `${currentPath}?${queryString}` : currentPath; } goHome() { this.navigate('home', {}); } goToRant(rantId, commentId = null) { const params = { rant: rantId }; if (commentId) { params.comment = commentId; } this.navigate('rant', params); } goToUser(username) { this.navigate('user', { user: username }); } goToSearch(term = '') { this.navigate('search', { search: term }); } goToNotifications() { this.navigate('notifications', { notifications: '' }); } goToSettings() { this.navigate('settings', { settings: '' }); } goToLogin() { this.navigate('login', { login: '' }); } goToWeekly() { this.navigate('weekly', { weekly: '' }); } goToCollabs() { this.navigate('collabs', { collabs: '' }); } goToStories() { this.navigate('stories', { stories: '' }); } back() { window.history.back(); } forward() { window.history.forward(); } getCurrentRoute() { return this.currentRoute; } getCurrentParams() { return this.currentParams; } setRouteChangeCallback(callback) { this.onRouteChange = callback; } isCurrentRoute(routeName) { return this.currentRoute === routeName; } } export { Router };