···
15
-
import { AppBskyFeedPost } from "@atcute/bluesky";
20
+
AppBskyNotificationListNotifications,
21
+
} from "@atcute/bluesky";
import { feedViewPostSchema } from "@atcute/bluesky/types/app/feed/defs";
23
+
import { getAtprotoHandle } from "@atcute/identity";
import { is, parseResourceUri, ResourceUri } from "@atcute/lexicons";
18
-
import { AtprotoDid, parseCanonicalResourceUri } from "@atcute/lexicons/syntax";
28
+
parseCanonicalResourceUri,
29
+
} from "@atcute/lexicons/syntax";
export default defineBackground({
···
// 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!, {
115
-
type: "TIMELINE_FRONTER",
126
+
type: "APPLY_FRONTERS",
results: Object.fromEntries(
results.flatMap((fronter) =>
fronterGetSocialAppHrefs(fronter).map((href) => [href, fronter]),
···
134
+
const handleNotifications = async (
136
+
sender: globalThis.Browser.runtime.MessageSender,
138
+
const fetchReply = async (
140
+
): Promise<FronterView | undefined> => {
141
+
const cachedFronter = await frontersCache.get(uri);
143
+
(cachedFronter ?? null) ||
144
+
(await getFronter(uri).then((fronter) => {
146
+
frontersCache.set(uri, null);
149
+
return fronter.value;
151
+
if (!fronter) return;
152
+
const parsedUri = await cacheFronter(uri, fronter);
155
+
rkey: parsedUri.rkey!,
159
+
const handleNotif = async (
160
+
item: AppBskyNotificationListNotifications.Notification,
161
+
): Promise<FronterView | undefined> => {
162
+
let postUrl: ResourceUri | null = null;
163
+
const fronterUrl: ResourceUri = item.uri;
165
+
item.reason === "subscribed-post" ||
166
+
item.reason === "quote" ||
167
+
item.reason === "reply"
169
+
postUrl = item.uri;
170
+
if (item.reason === "repost" || item.reason === "repost-via-repost")
171
+
postUrl = (item.record as AppBskyFeedRepost.Main).subject.uri;
172
+
if (item.reason === "like" || item.reason === "like-via-repost")
173
+
postUrl = (item.record as AppBskyFeedLike.Main).subject.uri;
174
+
if (!postUrl) return;
175
+
const cachedFronter = await frontersCache.get(fronterUrl);
177
+
(cachedFronter ?? null) ||
178
+
(await getFronter(fronterUrl).then((fronter) => {
180
+
frontersCache.set(fronterUrl, null);
183
+
return fronter.value;
185
+
if (!fronter) return;
186
+
if (item.reason === "reply")
187
+
fronter.replyTo = (
188
+
item.record as AppBskyFeedPost.Main
189
+
).reply?.parent.uri;
190
+
const parsedUri = await cacheFronter(fronterUrl, fronter);
191
+
const postParsedUri = expect(parseCanonicalResourceUri(postUrl));
192
+
let handle: Handle | undefined = undefined;
196
+
await docResolver.resolve(postParsedUri.repo as AtprotoDid),
199
+
console.error(`failed to get handle for ${postParsedUri.repo}:`, err);
202
+
type: "notification",
203
+
reason: item.reason,
204
+
rkey: parsedUri.rkey!,
206
+
did: postParsedUri.repo as AtprotoDid,
207
+
rkey: postParsedUri.rkey,
213
+
const allPromises = [];
214
+
for (const item of items.notifications ?? []) {
215
+
if (!is(AppBskyNotificationListNotifications.notificationSchema, item))
217
+
console.log("Handling notification:", item);
218
+
allPromises.push(handleNotif(item));
219
+
if (item.reason === "reply" && item.record) {
220
+
const parentUri = (item.record as AppBskyFeedPost.Main).reply?.parent
222
+
if (parentUri) allPromises.push(fetchReply(parentUri));
225
+
const results = new Map(
226
+
(await Promise.allSettled(allPromises))
227
+
.filter((result) => result.status === "fulfilled")
228
+
.flatMap((result) => result.value ?? [])
229
+
.flatMap((fronter) =>
230
+
fronterGetSocialAppHrefs(fronter).map((href) => [href, fronter]),
233
+
if (results.size === 0) return;
234
+
browser.tabs.sendMessage(sender.tab?.id!, {
235
+
type: "APPLY_FRONTERS",
236
+
results: Object.fromEntries(results),
const handleTimeline = async (
sender: globalThis.Browser.runtime.MessageSender,
···
if (results.size === 0) return;
browser.tabs.sendMessage(sender.tab?.id!, {
225
-
type: "TIMELINE_FRONTER",
341
+
type: "APPLY_FRONTERS",
results: Object.fromEntries(results),
// console.log("sent timeline fronters", results);
···
// check if this request was made for fetching replies
// if anchor is not the same as current document url, that is the case
238
-
// which means the depth of the returned posts are invalid to us, in the case of THREAD_FRONTER
239
-
// if so we will use TIMELINE_FRONTER to send it back to content script
354
+
// which means the depth of the returned posts are invalid to us
let isReplyThreadFetch = false;
const parsedDocumentUri = parseSocialAppPostUrl(documentUrl);
const anchorUri = new URL(requestUrl).searchParams.get("anchor");
···
if (results.size === 0) return;
browser.tabs.sendMessage(sender.tab?.id!, {
304
-
type: isReplyThreadFetch ? "TIMELINE_FRONTER" : "THREAD_FRONTER",
419
+
type: "APPLY_FRONTERS",
results: Object.fromEntries(results),
// console.log("sent thread fronters", results);
···
await handleThread(message, sender);
463
+
case "notifications":
464
+
await handleNotifications(JSON.parse(message.data.body), sender);