rznb9xaih: Add double-tap to like and the featured experts slide to the phone feed

This commit is contained in:
2026-10-20 08:31:04 -06:00
parent b97dddfc4c
commit bbd84f38a0
9 changed files with 243 additions and 26 deletions
+43 -1
View File
@@ -3,7 +3,8 @@ import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { readFileSync } from "node:fs";
import { FeedView, type FeedViewProps } from "@/components/FeedView";
import { pickCurrent } from "@/components/MobileFeed";
import { pickCurrent, isDoubleTap, isTapTarget, featuredSlideIndex } from "@/components/MobileFeed";
import { FIXTURE_DISCOVER } from "@/dev/fixtures";
import { CompactLayoutContext, isCompactWidth } from "@/components/layout-context";
import { toCardPosts } from "@/lib/feed-model";
@@ -129,3 +130,44 @@ describe("video slide before play", () => {
expect(html).toContain('class="post-play slide-play"');
});
});
describe("double-tap detection", () => {
it("needs two taps within 300ms", () => {
expect(isDoubleTap(null, 100)).toBe(false);
expect(isDoubleTap(100, 250)).toBe(true);
expect(isDoubleTap(100, 400)).toBe(true);
expect(isDoubleTap(100, 401)).toBe(false);
});
it("ignores taps on controls", () => {
const el = (html: string) => {
const fake = (match: boolean) => ({ closest: () => (match ? {} : null) });
return html === "slide" ? fake(false) : fake(true);
};
expect(isTapTarget(el("slide") as unknown as EventTarget)).toBe(true);
expect(isTapTarget(el("button") as unknown as EventTarget)).toBe(false);
});
});
describe("featured experts slide", () => {
it("sits after the second post and only with experts", () => {
expect(featuredSlideIndex(3, 5)).toBe(2);
expect(featuredSlideIndex(2, 5)).toBe(2);
expect(featuredSlideIndex(1, 5)).toBe(-1);
expect(featuredSlideIndex(3, 0)).toBe(-1);
});
it("renders the title, eyebrow, hint and a 156px carousel as a non-post slide", () => {
const out = render({ featuredExperts: FIXTURE_DISCOVER.featuredExperts });
expect(out).toContain('data-slide-kind="featured"');
expect(out).toContain("Featured experts");
expect(out).toContain("Ask the people everyone is talking about");
expect(out).toContain("--cfw:156px");
expect(out).toContain("Keep scrolling");
expect(out.match(/data-testid="feed-slide"/g)).toHaveLength(3);
// After the second post, before the third.
expect(out.indexOf("Author i1")).toBeLessThan(out.indexOf("feed-slide-featured"));
expect(out.indexOf("feed-slide-featured")).toBeLessThan(out.indexOf("Author v1"));
});
it("is absent without experts", () => {
expect(render({})).not.toContain("feed-slide-featured");
});
});