diff --git a/src/js/dataLayer/mutations.js b/src/js/dataLayer/mutations.js
index 42941a74..98194be5 100644
--- a/src/js/dataLayer/mutations.js
+++ b/src/js/dataLayer/mutations.js
@@ -333,7 +333,7 @@ export class Mutations {
const showLessInteraction = {
item: postURI,
event: "app.bsky.feed.defs#requestLess",
- ...(feedContext ? { feedContext } : {}),
+ ...(feedContext != null ? { feedContext } : {}),
};
this.dataStore.$showLessInteractions.set([
...this.dataStore.$showLessInteractions.get(),
@@ -351,7 +351,7 @@ export class Mutations {
const showMoreInteraction = {
item: postURI,
event: "app.bsky.feed.defs#requestMore",
- ...(feedContext ? { feedContext } : {}),
+ ...(feedContext != null ? { feedContext } : {}),
};
// Note, we don't really need to store this interaction because we don't use it in the UI (yet).
// But, let's do it anyway for consistency.
diff --git a/src/js/postSeenObserver.js b/src/js/postSeenObserver.js
index b0e85cf7..cc4d6a52 100644
--- a/src/js/postSeenObserver.js
+++ b/src/js/postSeenObserver.js
@@ -115,7 +115,7 @@ export class PostSeenObserver {
await this.interactionsDispatch.sendInteraction({
item: postUri,
event: "app.bsky.feed.defs#interactionSeen",
- feedContext,
+ ...(feedContext != null ? { feedContext } : {}),
});
this.seenPosts.add(postUri);
} catch (error) {
diff --git a/src/js/templates/postFeed.template.js b/src/js/templates/postFeed.template.js
index 978104c0..ecfd44d6 100644
--- a/src/js/templates/postFeed.template.js
+++ b/src/js/templates/postFeed.template.js
@@ -226,7 +226,6 @@ export function postFeedTemplate({
const content = html`
diff --git a/src/js/views/home.view.js b/src/js/views/home.view.js
index 10e9fde2..f62a71e7 100644
--- a/src/js/views/home.view.js
+++ b/src/js/views/home.view.js
@@ -211,6 +211,17 @@ class HomeView extends View {
);
const currentUser = dataLayer.derived.$currentUser.get();
const pinnedItems = dataLayer.derived.$hydratedPinnedItems.get() ?? [];
+ // Map of feed items -> feedContexts for postSeenObserver
+ const feedContextsByFeedUri = new Map(
+ pinnedItems.map((item) => [
+ item.uri,
+ new Map(
+ (dataLayer.derived.$hydratedFeeds.get(item.uri)?.feed ?? []).map(
+ (feedItem) => [feedItem.post.uri, feedItem.feedContext ?? null],
+ ),
+ ),
+ ]),
+ );
const currentFeedUri = state.$currentFeedUri.get();
const currentFeedRequestStatus =
dataLayer.requests.statusStore.$statuses.get(
@@ -291,10 +302,12 @@ class HomeView extends View {
);
const feedItems = document.querySelectorAll(".feed-item");
feedItems.forEach((feedItem) => {
- const { feedGeneratorUri, feedContext, postUri } = feedItem.dataset;
+ const { feedGeneratorUri, postUri } = feedItem.dataset;
if (feedGeneratorUri) {
const postSeenObserver = postSeenObservers.get(feedGeneratorUri);
if (postSeenObserver) {
+ const feedContext =
+ feedContextsByFeedUri.get(feedGeneratorUri)?.get(postUri) ?? null;
postSeenObserver.register(feedItem, postUri, feedContext);
}
}
diff --git a/tests/unit/specs/dataLayer/mutations.test.js b/tests/unit/specs/dataLayer/mutations.test.js
index 9fd5e3ea..05a888cd 100644
--- a/tests/unit/specs/dataLayer/mutations.test.js
+++ b/tests/unit/specs/dataLayer/mutations.test.js
@@ -3054,6 +3054,37 @@ describe("sendShowLessInteraction", () => {
assert.deepEqual(stored.length, 2);
assert.deepEqual(stored[1].item, postURI);
});
+
+ it("should omit feedContext when null but keep an empty string", async () => {
+ const dataStore = new DataStore();
+ const patchStore = new PatchStore(dataStore);
+ const mockPreferencesProvider = {
+ requirePreferences: () => Preferences.createLoggedOutPreferences(),
+ };
+ const sentInteractions = [];
+ const mutations = makeMutations(
+ {
+ sendInteractions: async (interactions) => {
+ sentInteractions.push(...interactions);
+ },
+ },
+ dataStore,
+ patchStore,
+ mockPreferencesProvider,
+ );
+
+ await mutations.sendShowLessInteraction(postURI, null, feedProxyUrl);
+ await mutations.sendShowLessInteraction(postURI, "", feedProxyUrl);
+
+ assert.deepEqual(sentInteractions, [
+ { item: postURI, event: "app.bsky.feed.defs#requestLess" },
+ {
+ item: postURI,
+ event: "app.bsky.feed.defs#requestLess",
+ feedContext: "",
+ },
+ ]);
+ });
});
describe("sendShowMoreInteraction", () => {
diff --git a/tests/unit/specs/postSeenObserver.test.js b/tests/unit/specs/postSeenObserver.test.js
index f5648767..1ee9baca 100644
--- a/tests/unit/specs/postSeenObserver.test.js
+++ b/tests/unit/specs/postSeenObserver.test.js
@@ -115,6 +115,16 @@ describe("PostSeenObserver - seen tracking", () => {
assert(observer.seenPosts.has(postUriA));
});
+ it("omits feedContext from the interaction when it is null", async () => {
+ const { element } = createTrackedElement();
+ observer.register(element, postUriA, null);
+ await flushTimers();
+ assert.deepEqual(sendInteractions.mock.callCount(), 1);
+ assert.deepEqual(sendInteractions.mock.calls[0].arguments[0], [
+ { item: postUriA, event: "app.bsky.feed.defs#interactionSeen" },
+ ]);
+ });
+
it("does not send an interaction for an off-screen post", async () => {
const { element } = createTrackedElement({ top: 2000, bottom: 2100 });
observer.register(element, postUriA, null);
diff --git a/tests/unit/specs/templates/postFeed.template.test.js b/tests/unit/specs/templates/postFeed.template.test.js
index 729a1bda..661a0419 100644
--- a/tests/unit/specs/templates/postFeed.template.test.js
+++ b/tests/unit/specs/templates/postFeed.template.test.js
@@ -115,18 +115,6 @@ describe("postFeedTemplate - feed with posts", () => {
const feedItem = container.querySelector("[data-testid='feed-item']");
assert(feedItem.getAttribute("data-post-uri") !== null);
});
-
- it("should set data-feed-context attribute on feed items", () => {
- const result = postFeedTemplate({
- feed: { feed: feed.slice(0, 1), cursor: null },
- currentUser: mockUser,
- postInteractionHandler,
- });
- const container = document.createElement("div");
- render(result, container);
- const feedItem = container.querySelector("[data-testid='feed-item']");
- assert(feedItem.hasAttribute("data-feed-context"));
- });
});
describe("postFeedTemplate - pagination", () => {