view who was fronting when a record was made

fix: set fronters for depth 0 thread view items on router url change

ptr.pet b172643d a88e7061

verified
Changed files
+60 -23
src
+7 -1
src/entrypoints/background.ts
··· 10 putFronter, 11 frontersCache, 12 parseSocialAppPostUrl, 13 } from "@/lib/utils"; 14 import { 15 parseCanonicalResourceUri, ··· 201 ...fronter, 202 }; 203 if (item.depth === 0) await setTabFronter(item.uri, fronter); 204 return { 205 rkey: parsedUri.rkey!, 206 - displayName: item.value.post.author.displayName, 207 depth: item.depth, 208 ...fronter, 209 };
··· 10 putFronter, 11 frontersCache, 12 parseSocialAppPostUrl, 13 + displayNameCache, 14 } from "@/lib/utils"; 15 import { 16 parseCanonicalResourceUri, ··· 202 ...fronter, 203 }; 204 if (item.depth === 0) await setTabFronter(item.uri, fronter); 205 + const displayName = item.value.post.author.displayName; 206 + // cache display name for later use 207 + if (fronter.handle) 208 + await displayNameCache.set(fronter.handle, displayName); 209 + await displayNameCache.set(fronter.did, displayName); 210 return { 211 rkey: parsedUri.rkey!, 212 + displayName, 213 depth: item.depth, 214 ...fronter, 215 };
+7 -17
src/entrypoints/content.ts
··· 72 body, 73 authToken: getAuthToken(), 74 }; 75 } else if (response.url.includes("/xrpc/com.atproto.repo.createRecord")) { 76 detail = { 77 type: "writeOne", ··· 124 respEventSetup.then((name) => (respEventName = name)); 125 126 const applyFronterName = (el: Element, fronters: Fronter["members"]) => { 127 - if (el.getAttribute("data-fronter")) return; 128 const s = fronters.map((f) => f.name).join(", "); 129 el.textContent += ` [f: ${s}]`; 130 el.setAttribute("data-fronter", s); ··· 135 ) => { 136 // console.log("applyFrontersToPage", fronters); 137 const match = parseSocialAppPostUrl(document.URL); 138 - console.log("applyFrontersToPage", match, fronters); 139 if (pageChange) { 140 console.log( 141 "page change so clearing all elements with data-fronter attribute", ··· 150 el.removeAttribute("data-fronter"); 151 } 152 } 153 if (fronters.size === 0) return; 154 for (const el of document.getElementsByTagName("a")) { 155 const path = `/${el.href.split("/").slice(3).join("/")}`; 156 const fronter = fronters.get(path); 157 - if (!fronter || fronter.members.length === 0) continue; 158 const isFocusedPost = fronter.depth === 0; 159 if (isFocusedPost) if (match && match.rkey !== fronter.rkey) continue; 160 if (isFocusedPost) if (el.ariaLabel !== fronter.displayName) continue; ··· 171 window.addEventListener("message", (event) => { 172 if (event.data.type !== "APPLY_CACHED_FRONTERS") return; 173 const applyFronters = () => { 174 - const fronters = event.data.fronters as Map<string, Fronter | null>; 175 - const updated = new Map( 176 - fronters.entries().flatMap(([storageKey, fronter]) => { 177 - if (!fronter) return []; 178 - const uri = decodeStorageKey(storageKey); 179 - const rkey = expect(parseResourceUri(uri)).rkey!; 180 - return fronterGetSocialAppHrefs(fronter, rkey).map((href) => [ 181 - href, 182 - fronter, 183 - ]); 184 - }), 185 - ); 186 - console.log("applying cached fronters", updated); 187 - applyFrontersToPage(updated, true); 188 }; 189 // check if we are on profile so we can update fronters if the post tab is clicked on 190 const postTabElement = document.querySelector(
··· 72 body, 73 authToken: getAuthToken(), 74 }; 75 + } else if (response.url.includes("/xrpc/com.atproto.repo.deleteRecord")) { 76 } else if (response.url.includes("/xrpc/com.atproto.repo.createRecord")) { 77 detail = { 78 type: "writeOne", ··· 125 respEventSetup.then((name) => (respEventName = name)); 126 127 const applyFronterName = (el: Element, fronters: Fronter["members"]) => { 128 + if (el.hasAttribute("data-fronter")) return; 129 const s = fronters.map((f) => f.name).join(", "); 130 el.textContent += ` [f: ${s}]`; 131 el.setAttribute("data-fronter", s); ··· 136 ) => { 137 // console.log("applyFrontersToPage", fronters); 138 const match = parseSocialAppPostUrl(document.URL); 139 if (pageChange) { 140 console.log( 141 "page change so clearing all elements with data-fronter attribute", ··· 150 el.removeAttribute("data-fronter"); 151 } 152 } 153 + console.log("applyFrontersToPage", match, fronters); 154 if (fronters.size === 0) return; 155 for (const el of document.getElementsByTagName("a")) { 156 const path = `/${el.href.split("/").slice(3).join("/")}`; 157 const fronter = fronters.get(path); 158 + if (!fronter || fronter.members?.length === 0) continue; 159 + if (el.hasAttribute("data-fronter")) continue; 160 const isFocusedPost = fronter.depth === 0; 161 if (isFocusedPost) if (match && match.rkey !== fronter.rkey) continue; 162 if (isFocusedPost) if (el.ariaLabel !== fronter.displayName) continue; ··· 173 window.addEventListener("message", (event) => { 174 if (event.data.type !== "APPLY_CACHED_FRONTERS") return; 175 const applyFronters = () => { 176 + console.log("applying cached fronters", event.data.fronters); 177 + applyFrontersToPage(event.data.fronters, true); 178 }; 179 // check if we are on profile so we can update fronters if the post tab is clicked on 180 const postTabElement = document.querySelector(
+41 -5
src/entrypoints/isolated.content.ts
··· 1 - import { Fronter, frontersCache, parseSocialAppPostUrl } from "@/lib/utils"; 2 - import { ResourceUri } from "@atcute/lexicons"; 3 4 export default defineContentScript({ 5 matches: ["<all_urls>"], ··· 36 if (!messageTypes.includes(message.type)) return; 37 window.postMessage(message); 38 }); 39 - window.addEventListener("popstate", async (event) => { 40 window.postMessage({ 41 type: "APPLY_CACHED_FRONTERS", 42 - fronters: await frontersCache.getAll(), 43 }); 44 // check for tab fronter for the current "post" 45 await checkFronter(document.location.href); 46 - }); 47 48 // setup response "channel" 49 document.dispatchEvent(
··· 1 + import { decodeStorageKey } from "@/lib/cache"; 2 + import { expect } from "@/lib/result"; 3 + import { 4 + displayNameCache, 5 + Fronter, 6 + fronterGetSocialAppHrefs, 7 + frontersCache, 8 + parseSocialAppPostUrl, 9 + } from "@/lib/utils"; 10 + import { parseResourceUri, ResourceUri } from "@atcute/lexicons"; 11 12 export default defineContentScript({ 13 matches: ["<all_urls>"], ··· 44 if (!messageTypes.includes(message.type)) return; 45 window.postMessage(message); 46 }); 47 + const updateOnUrlChange = async () => { 48 + const fronters = await frontersCache.getAll(); 49 + const updated = new Map<string, any>( 50 + fronters.entries().flatMap(([storageKey, fronter]) => { 51 + if (!fronter) return []; 52 + const uri = decodeStorageKey(storageKey); 53 + const rkey = expect(parseResourceUri(uri)).rkey!; 54 + return fronterGetSocialAppHrefs(fronter, rkey).map((href) => [ 55 + href, 56 + fronter, 57 + ]); 58 + }), 59 + ); 60 + // add entry for current page 61 + const match = parseSocialAppPostUrl(document.location.href); 62 + if (match && !updated.has(`/profile/${match.actorIdentifier}`)) { 63 + const maybeFronter = updated.get( 64 + `/profile/${match.actorIdentifier}/post/${match.rkey}`, 65 + ); 66 + if (maybeFronter) 67 + updated.set(`/profile/${match.actorIdentifier}`, { 68 + depth: 0, 69 + displayName: await displayNameCache.get(match.actorIdentifier), 70 + rkey: match.rkey, 71 + ...maybeFronter, 72 + }); 73 + } 74 window.postMessage({ 75 type: "APPLY_CACHED_FRONTERS", 76 + fronters: updated, 77 }); 78 // check for tab fronter for the current "post" 79 await checkFronter(document.location.href); 80 + }; 81 + window.addEventListener("popstate", updateOnUrlChange); 82 + ctx.addEventListener(window, "wxt:locationchange", updateOnUrlChange); 83 84 // setup response "channel" 85 document.dispatchEvent(
+5
src/lib/utils.ts
··· 334 const [website, actorIdentifier, rkey] = match; 335 return { actorIdentifier, rkey }; 336 };
··· 334 const [website, actorIdentifier, rkey] = match; 335 return { actorIdentifier, rkey }; 336 }; 337 + 338 + export const displayNameCache = new PersistentCache<string>( 339 + "displayNameCache", 340 + 1, 341 + );