Files
bitvid/js/app/routerCoordinator.js
T
thePR0M3TH3ANandClaude Opus 4.8 a20388c5d6 [video-modal] Fix dead channel/creator link — event-name mismatch (#53)
Clicking the creator avatar/name in the video player modal did nothing. VideoModal
dispatched "navigate:profile", but ModalManager only listens for "creator:navigate"
(→ app.openCreatorChannel), so the event went into the void — same class as the old
action:embed bug noted just above the handler.

Fix:
- VideoModal.handleCreatorNavigation dispatches "creator:navigate" (the listened name)
  with { pubkey }.
- ModalManager's handler forwards event.detail.pubkey to app.openCreatorChannel.
- routerCoordinator.openCreatorChannel(pubkey) accepts an optional pubkey (prefers it,
  falls back to the active video's creator), so it navigates to the modal's own
  creator rather than whatever currentVideo happens to be.

Tests: tests/video-modal-controllers.test.mjs (+2 — dispatches creator:navigate with
the pubkey and never the dead navigate:profile; no-op without a pubkey). Lint + build green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-02 08:51:10 -04:00

95 lines
2.5 KiB
JavaScript

// js/app/routerCoordinator.js
/**
* Routing logic for the application.
*
* All module-level dependencies are injected from the Application
* composition root rather than imported at module scope.
*
* Methods use `this` which is bound to the Application instance.
*/
export function createRouterCoordinator(deps) {
const {
devLogger,
} = deps;
return {
goToProfile(pubkey) {
if (typeof pubkey !== "string") {
this.showError("No creator info available.");
return;
}
let candidate = pubkey.trim();
if (!candidate) {
this.showError("No creator info available.");
return;
}
if (candidate.startsWith("nostr:")) {
candidate = candidate.slice("nostr:".length);
}
const normalizedHex = this.normalizeHexPubkey(candidate);
const npub = normalizedHex ? this.safeEncodeNpub(normalizedHex) : null;
if (!npub) {
devLogger.warn(
"[Application] Invalid pubkey for profile navigation:",
candidate,
);
this.showError("Invalid creator profile.");
return;
}
window.location.hash = `#view=channel-profile&npub=${npub}`;
},
openCreatorChannel(pubkey) {
// Prefer an explicit pubkey (e.g. the video modal's own creator) and fall
// back to the active video's creator.
const targetPubkey =
(typeof pubkey === "string" && pubkey.trim()) ||
this.currentVideo?.pubkey ||
"";
if (!targetPubkey) {
this.showError("No creator info available.");
return;
}
try {
// Encode the hex pubkey to npub
const npub = window.NostrTools.nip19.npubEncode(targetPubkey);
// Close the video modal
this.hideModal();
// Switch to channel profile view
window.location.hash = `#view=channel-profile&npub=${npub}`;
} catch (err) {
devLogger.error("Failed to open creator channel:", err);
this.showError("Could not open channel.");
}
},
handleProfileChannelLink(element) {
if (!(element instanceof HTMLElement)) {
return;
}
const targetNpub =
typeof element.dataset.targetNpub === "string"
? element.dataset.targetNpub
: "";
if (this.profileController) {
this.profileController.hide();
}
if (targetNpub) {
window.location.hash = `#view=channel-profile&npub=${encodeURIComponent(
targetNpub,
)}`;
}
}
};
}