import { decodeStorageKey } from "@/lib/cache"; import { expect } from "@/lib/result"; import { displayNameCache, Fronter, fronterGetSocialAppHref, fronterGetSocialAppHrefs, frontersCache, FronterView, parseSocialAppPostUrl, } from "@/lib/utils"; import { parseResourceUri, ResourceUri } from "@atcute/lexicons"; export default defineContentScript({ matches: [""], runAt: "document_start", world: "ISOLATED", main: (ctx) => { const checkFronter = async (url: string) => { // match https://*/profile//post/ regex with named params to extract actor_identifier and rkey const match = parseSocialAppPostUrl(url); if (!match) return false; const recordUri = `at://${match.actorIdentifier}/app.bsky.feed.post/${match.rkey}` as ResourceUri; const fronter = await frontersCache.get(recordUri); if (!fronter) return false; browser.runtime.sendMessage({ type: "TAB_FRONTER", recordUri, fronter, }); return true; }; const respEventName = Math.random().toString(36).slice(2); window.addEventListener(`${respEventName}-isolated`, async (event) => { const data = (event as any).detail; // console.log("passing response event to bg", event); await browser.runtime.sendMessage({ type: "RESPONSE_CAPTURED", data, }); }); const bgMessageTypes = ["APPLY_FRONTERS"]; browser.runtime.onMessage.addListener((message) => { if (!bgMessageTypes.includes(message.type)) return; window.postMessage(message); }); const updateOnUrlChange = async () => { const fronters = await frontersCache.getAll(); const updated = new Map(); for (const [storageKey, fronter] of fronters.entries()) { const uri = decodeStorageKey(storageKey); const parsedUri = expect(parseResourceUri(uri)); if (!fronter) { updated.set( fronterGetSocialAppHref(parsedUri.repo, parsedUri.rkey!), null, ); continue; } const view: FronterView = { type: parsedUri.collection === "app.bsky.feed.repost" ? "repost" : "post", rkey: parsedUri.rkey!, ...fronter, }; for (const href of fronterGetSocialAppHrefs(view)) { updated.set(href, view); } } // add entry for current page const match = parseSocialAppPostUrl(document.location.href); if (match && !updated.has(`/profile/${match.actorIdentifier}`)) { const maybeFronter = updated.get( `/profile/${match.actorIdentifier}/post/${match.rkey}`, ); if (maybeFronter) { const displayName = await displayNameCache.get(match.actorIdentifier); if (displayName) { const view: FronterView = { ...maybeFronter, type: "thread_post", depth: 0, displayName, rkey: match.rkey, }; updated.set(`/profile/${maybeFronter.did}`, view); if (maybeFronter.handle) { updated.set(`/profile/${maybeFronter.handle}`, view); } } } } window.postMessage({ type: "APPLY_CACHED_FRONTERS", fronters: Object.fromEntries(updated), }); // check for tab fronter for the current "post" await checkFronter(document.location.href); }; window.addEventListener("popstate", updateOnUrlChange); ctx.addEventListener(window, "wxt:locationchange", updateOnUrlChange); // setup response "channel" document.dispatchEvent( new CustomEvent("at-fronter-channel-setup", { detail: respEventName, }), ); // checkFronter(document.URL); }, });