diff --git a/frontend/src/ts/controllers/route-controller.ts b/frontend/src/ts/controllers/route-controller.ts index 4e3f5c265141..482f8f9affc6 100644 --- a/frontend/src/ts/controllers/route-controller.ts +++ b/frontend/src/ts/controllers/route-controller.ts @@ -9,7 +9,7 @@ import * as Notifications from "../elements/notifications"; import tribeSocket from "../tribe/tribe-socket"; import { setAutoJoin } from "../tribe/tribe-auto-join"; import { LoadingOptions } from "../pages/page"; -import { setNavigationService } from "../observables/navigate-event"; +import * as NavigationEvent from "../observables/navigation-event"; //source: https://www.youtube.com/watch?v=OstALBk-jTc // https://www.youtube.com/watch?v=OstALBk-jTc @@ -312,10 +312,8 @@ document.addEventListener("DOMContentLoaded", () => { }); }); -// Register navigation service for modules that can't directly import navigate +// Subscribe to navigation events from modules that can't directly import navigate // due to circular dependency constraints -setNavigationService({ - navigate(url, options) { - void navigate(url, options); - }, +NavigationEvent.subscribe((url, options) => { + void navigate(url, options); }); diff --git a/frontend/src/ts/observables/navigate-event.ts b/frontend/src/ts/observables/navigate-event.ts deleted file mode 100644 index f3f4120ac580..000000000000 --- a/frontend/src/ts/observables/navigate-event.ts +++ /dev/null @@ -1,25 +0,0 @@ -type NavigateOptions = { - force?: boolean; - tribeOverride?: boolean; -}; - -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export interface NavigationService { - navigate(url: string, options?: NavigateOptions): void; -} - -let service: NavigationService | undefined; - -export function setNavigationService(s: NavigationService): void { - if (service !== undefined) { - throw new Error("NavigationService already initialized"); - } - service = s; -} - -export function navigate(url: string, options?: NavigateOptions): void { - if (service === undefined) { - throw new Error("NavigationService not initialized"); - } - service.navigate(url, options); -} diff --git a/frontend/src/ts/observables/navigation-event.ts b/frontend/src/ts/observables/navigation-event.ts new file mode 100644 index 000000000000..c35ba3f72d43 --- /dev/null +++ b/frontend/src/ts/observables/navigation-event.ts @@ -0,0 +1,23 @@ +type NavigateOptions = { + force?: boolean; + tribeOverride?: boolean; +}; + +type SubscribeFunction = (url: string, options?: NavigateOptions) => void; + +const subscribers: SubscribeFunction[] = []; + +export function subscribe(fn: SubscribeFunction): void { + subscribers.push(fn); +} + +export function dispatch(url: string, options?: NavigateOptions): void { + subscribers.forEach((fn) => { + try { + fn(url, options); + } catch (e) { + console.error("Navigate event subscriber threw an error"); + console.error(e); + } + }); +} diff --git a/frontend/src/ts/tribe/tribe.ts b/frontend/src/ts/tribe/tribe.ts index d69931aba7db..27988ba92d2f 100644 --- a/frontend/src/ts/tribe/tribe.ts +++ b/frontend/src/ts/tribe/tribe.ts @@ -29,7 +29,7 @@ import * as TestStats from "../test/test-stats"; import * as TestInput from "../test/test-input"; import * as TribeCarets from "./tribe-carets"; import * as TribeTypes from "./types"; -import { navigate } from "../observables/navigate-event"; +import * as NavigationEvent from "../observables/navigation-event"; import { ColorName } from "../elements/theme-colors"; import * as TribeAutoJoin from "./tribe-auto-join"; @@ -392,7 +392,7 @@ TribeSocket.in.room.left(() => { updateState(1); TribePageMenu.enableButtons(); if (!$(".pageTribe").hasClass("active")) { - navigate("/tribe"); + NavigationEvent.dispatch("/tribe"); } TribeCarets.destroyAll(); TribeSound.play("leave"); @@ -521,7 +521,7 @@ TribeSocket.in.room.initRace((data) => { } else { //TODO update lobby bars if (ActivePage.get() !== "tribe") { - navigate("/tribe", { + NavigationEvent.dispatch("/tribe", { tribeOverride: true, }); } @@ -531,7 +531,7 @@ TribeSocket.in.room.initRace((data) => { } if (room) room.seed = data.seed; Random.setSeed(TribeState.getRoom()?.seed.toString() ?? ""); - navigate("/", { + NavigationEvent.dispatch("/", { tribeOverride: true, force: true, }); @@ -766,7 +766,7 @@ TribeSocket.in.room.readyTimerOver(() => { }); TribeSocket.in.room.backToLobby(() => { - navigate("/tribe"); + NavigationEvent.dispatch("/tribe"); }); TribeSocket.in.room.finalPositions((data) => {