view who was fronting when a record was made

fix: make replies have fronter after being created

ptr.pet a88e7061 2170a51c

verified
Changed files
+73 -18
src
+38 -5
src/entrypoints/background.ts
···
memberUriString,
putFronter,
frontersCache,
+
parseSocialAppPostUrl,
} from "@/lib/utils";
-
import { parseResourceUri, ResourceUri } from "@atcute/lexicons";
+
import {
+
parseCanonicalResourceUri,
+
parseResourceUri,
+
ResourceUri,
+
} from "@atcute/lexicons";
export default defineBackground({
persistent: true,
···
console.error(`fronter write: ${resp.error}`);
}
}
+
if (results.length === 0) return;
// hijack timeline fronter message because when a write is made it is either on the timeline
// or its a reply to a depth === 0 post on a threaded view, which is the same as a timeline post
browser.tabs.sendMessage(sender.tab?.id!, {
···
]),
),
);
+
if (results.size === 0) return;
browser.tabs.sendMessage(sender.tab?.id!, {
type: "TIMELINE_FRONTER",
results,
···
// console.log("sent timeline fronters", results);
};
const handleThread = async (
-
{ data: { body } }: any,
+
{
+
data: { body, requestUrl, documentUrl },
+
}: { data: { body: string; requestUrl: string; documentUrl: string } },
sender: globalThis.Browser.runtime.MessageSender,
) => {
+
// check if this request was made for fetching replies
+
// if anchor is not the same as current document url, that is the case
+
// which means the depth of the returned posts are invalid to us, in the case of THREAD_FRONTER
+
// if so we will use TIMELINE_FRONTER to send it back to content script
+
let isReplyThreadFetch = false;
+
const parsedDocumentUri = parseSocialAppPostUrl(documentUrl);
+
const anchorUri = new URL(requestUrl).searchParams.get("anchor");
+
// console.log(
+
// "parsedDocumentUri",
+
// parsedDocumentUri,
+
// "anchorUri",
+
// anchorUri,
+
// );
+
if (parsedDocumentUri && anchorUri) {
+
const parsedAnchorUri = expect(parseResourceUri(anchorUri));
+
isReplyThreadFetch = parsedDocumentUri.rkey !== parsedAnchorUri.rkey;
+
}
+
// console.log("isReplyThreadFetch", isReplyThreadFetch);
const data: any = JSON.parse(body);
const promises = (data.thread as any[]).flatMap((item) => {
return frontersCache.get(item.uri).then(async (cachedFronter) => {
···
}
return fronter.value;
});
-
return promise.then(async (fronter) => {
+
return promise.then(async (fronter): Promise<any> => {
if (!fronter) return;
const parsedUri = await cacheFronter(item.uri, fronter);
+
if (isReplyThreadFetch)
+
return {
+
rkey: parsedUri.rkey!,
+
...fronter,
+
};
if (item.depth === 0) await setTabFronter(item.uri, fronter);
return {
rkey: parsedUri.rkey!,
···
),
),
);
+
if (results.size === 0) return;
browser.tabs.sendMessage(sender.tab?.id!, {
-
type: "THREAD_FRONTER",
+
type: isReplyThreadFetch ? "TIMELINE_FRONTER" : "THREAD_FRONTER",
results,
});
// console.log("sent thread fronters", results);
···
browser.runtime.onMessage.addListener(async (message, sender) => {
if (message.type !== "RESPONSE_CAPTURED") return;
-
// console.log("handling response event", message);
+
console.log("handling response", message.data);
switch (message.data.type as string) {
case "write":
await handleWrite(
+35 -13
src/entrypoints/content.ts
···
}
return authHeader?.split(" ")[1] || null;
};
+
const getRequestUrl = () => {
+
let url: string | null = null;
+
if (args[0] instanceof Request) {
+
url = args[0].url;
+
} else {
+
url = args[0].toString();
+
}
+
return decodeURI(url);
+
};
let detail: any = undefined;
if (response.url.includes("/xrpc/com.atproto.repo.applyWrites")) {
···
detail = {
type: "thread",
body,
+
requestUrl: getRequestUrl(),
+
documentUrl: document.location.href,
};
} else if (response.url.includes("/xrpc/app.bsky.feed.getPosts")) {
detail = {
···
el.textContent += ` [f: ${s}]`;
el.setAttribute("data-fronter", s);
};
-
const applyFrontersToPage = (fronters: Map<string, any>) => {
+
const applyFrontersToPage = (
+
fronters: Map<string, any>,
+
pageChange: boolean,
+
) => {
// console.log("applyFrontersToPage", fronters);
const match = parseSocialAppPostUrl(document.URL);
-
// console.log(match, fronters);
-
for (const el of document.querySelectorAll("[data-fronter]")) {
-
const previousFronter = el.getAttribute("data-fronter")!;
-
// remove fronter text
-
el.textContent = el.textContent.replace(` [f: ${previousFronter}]`, "");
-
el.removeAttribute("data-fronter");
+
console.log("applyFrontersToPage", match, fronters);
+
if (pageChange) {
+
console.log(
+
"page change so clearing all elements with data-fronter attribute",
+
);
+
for (const el of document.querySelectorAll("[data-fronter]")) {
+
const previousFronter = el.getAttribute("data-fronter")!;
+
// remove fronter text
+
el.textContent = el.textContent.replace(
+
` [f: ${previousFronter}]`,
+
"",
+
);
+
el.removeAttribute("data-fronter");
+
}
}
if (fronters.size === 0) return;
for (const el of document.getElementsByTagName("a")) {
···
const fronter = fronters.get(path);
if (!fronter || fronter.members.length === 0) continue;
const isFocusedPost = fronter.depth === 0;
-
if (isFocusedPost && match && match.rkey !== fronter.rkey) continue;
-
if (isFocusedPost && el.ariaLabel !== fronter.displayName) continue;
+
if (isFocusedPost) if (match && match.rkey !== fronter.rkey) continue;
+
if (isFocusedPost) if (el.ariaLabel !== fronter.displayName) continue;
const displayNameElement = isFocusedPost
? (el.firstElementChild?.firstElementChild?.firstElementChild
?.firstElementChild?.firstElementChild ?? null)
: (el.parentElement?.firstElementChild?.firstElementChild
?.firstElementChild?.firstElementChild ?? null);
if (!displayNameElement) continue;
-
// console.log(path, fronter, displayNameElement);
applyFronterName(displayNameElement, fronter.members);
}
};
···
]);
}),
);
-
// console.log("applying cached fronters");
-
applyFrontersToPage(updated);
+
console.log("applying cached fronters", updated);
+
applyFrontersToPage(updated, true);
};
// check if we are on profile so we can update fronters if the post tab is clicked on
const postTabElement = document.querySelector(
···
window.addEventListener("message", (event) => {
if (!["TIMELINE_FRONTER", "THREAD_FRONTER"].includes(event.data.type))
return;
-
applyFrontersToPage(event.data.results as Map<string, any>);
+
console.log(`received ${event.data.type} fronters`, event.data.results);
+
applyFrontersToPage(event.data.results, false);
});
},
});