view who was fronting when a record was made
1import { decodeStorageKey } from "@/lib/cache";
2import { expect } from "@/lib/result";
3import {
4 displayNameCache,
5 Fronter,
6 fronterGetSocialAppHref,
7 fronterGetSocialAppHrefs,
8 frontersCache,
9 FronterView,
10 parseSocialAppPostUrl,
11} from "@/lib/utils";
12import { parseResourceUri, ResourceUri } from "@atcute/lexicons";
13
14export default defineContentScript({
15 matches: ["<all_urls>"],
16 runAt: "document_start",
17 world: "ISOLATED",
18 main: (ctx) => {
19 const checkFronter = async (url: string) => {
20 // match https://*/profile/<actor_identifier>/post/<rkey> regex with named params to extract actor_identifier and rkey
21 const match = parseSocialAppPostUrl(url);
22 if (!match) return false;
23 const recordUri =
24 `at://${match.actorIdentifier}/app.bsky.feed.post/${match.rkey}` as ResourceUri;
25 const fronter = await frontersCache.get(recordUri);
26 if (!fronter) return false;
27 browser.runtime.sendMessage({
28 type: "TAB_FRONTER",
29 recordUri,
30 fronter,
31 });
32 return true;
33 };
34
35 const respEventName = Math.random().toString(36).slice(2);
36 window.addEventListener(`${respEventName}-isolated`, async (event) => {
37 const data = (event as any).detail;
38 // console.log("passing response event to bg", event);
39 await browser.runtime.sendMessage({
40 type: "RESPONSE_CAPTURED",
41 data,
42 });
43 });
44 const bgMessageTypes = ["APPLY_FRONTERS"];
45 browser.runtime.onMessage.addListener((message) => {
46 if (!bgMessageTypes.includes(message.type)) return;
47 window.postMessage(message);
48 });
49 const updateOnUrlChange = async () => {
50 const fronters = await frontersCache.getAll();
51 const updated = new Map<string, FronterView | null>();
52 for (const [storageKey, fronter] of fronters.entries()) {
53 const uri = decodeStorageKey(storageKey);
54 const parsedUri = expect(parseResourceUri(uri));
55 if (!fronter) {
56 updated.set(
57 fronterGetSocialAppHref(parsedUri.repo, parsedUri.rkey!),
58 null,
59 );
60 continue;
61 }
62 const view: FronterView = {
63 type:
64 parsedUri.collection === "app.bsky.feed.repost" ? "repost" : "post",
65 rkey: parsedUri.rkey!,
66 ...fronter,
67 };
68 for (const href of fronterGetSocialAppHrefs(view)) {
69 updated.set(href, view);
70 }
71 }
72 // add entry for current page
73 const match = parseSocialAppPostUrl(document.location.href);
74 if (match && !updated.has(`/profile/${match.actorIdentifier}`)) {
75 const maybeFronter = updated.get(
76 `/profile/${match.actorIdentifier}/post/${match.rkey}`,
77 );
78 if (maybeFronter) {
79 const displayName = await displayNameCache.get(match.actorIdentifier);
80 if (displayName) {
81 const view: FronterView = {
82 ...maybeFronter,
83 type: "thread_post",
84 depth: 0,
85 displayName,
86 rkey: match.rkey,
87 };
88 updated.set(`/profile/${maybeFronter.did}`, view);
89 if (maybeFronter.handle) {
90 updated.set(`/profile/${maybeFronter.handle}`, view);
91 }
92 }
93 }
94 }
95 window.postMessage({
96 type: "APPLY_CACHED_FRONTERS",
97 fronters: Object.fromEntries(updated),
98 });
99 // check for tab fronter for the current "post"
100 await checkFronter(document.location.href);
101 };
102 window.addEventListener("popstate", updateOnUrlChange);
103 ctx.addEventListener(window, "wxt:locationchange", updateOnUrlChange);
104
105 // setup response "channel"
106 document.dispatchEvent(
107 new CustomEvent("at-fronter-channel-setup", {
108 detail: respEventName,
109 }),
110 );
111
112 // checkFronter(document.URL);
113 },
114});