Skip to content

Commit

Permalink
✨ feat(ui): latestCodeList now remembers scroll position before swap
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronlifton committed May 26, 2024
1 parent d308e27 commit 57667d1
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 91 deletions.
49 changes: 35 additions & 14 deletions src/components/LatestCodeList.astro
Original file line number Diff line number Diff line change
Expand Up @@ -94,28 +94,35 @@ for (const post of livePosts) {
}
</div>
<script>
import { isPaused, scrollLeft, scrollDone, currentIndex } from "$state/index";
import { isPaused, scrollDone, scrollLeft, currentIndex } from "$state/index";

const activeTransitionsEnabled = false
const initialDelay = 1750;
const intervalTime = 5000;
let eventListeners: {target: Element | null, type: string, listener: () => void }[] = []
let interval: number | null = null;
let timeout: Timer | null = null;

const getCodesContainer = () => {
return document.querySelector(".codes-container") as HTMLDivElement;
}
const getCodes = (container: HTMLDivElement): NodeListOf<HTMLDivElement> => {
return container.querySelectorAll(".code");
}
const getScrollLeft = (codes: NodeListOf<HTMLDivElement>, container: HTMLDivElement) => {
return codes[currentIndex.get()].offsetLeft - container.offsetLeft;
}

function startInterval(func: Function) {
setTimeout(function() {
timeout = setTimeout(function() {
func();
interval = setInterval(func, intervalTime);
}, initialDelay);
}

const onLoad = () => {
const codesContainer = document.querySelector(
".codes-container",
) as HTMLDivElement;
const codes: NodeListOf<HTMLDivElement> = document.querySelectorAll(
".codes-container .code",
);
const codesContainer = getCodesContainer()
const codes = getCodes(codesContainer)

if (activeTransitionsEnabled) {
scrollDone.subscribe((sd) => {
Expand All @@ -134,8 +141,7 @@ const onLoad = () => {
currentIndex.set(0)
}

const newScrollLeft = codes[currentIndex.get()].offsetLeft
- codesContainer.offsetLeft;
const newScrollLeft = getScrollLeft(codes, codesContainer);
scrollLeft.set(newScrollLeft);
currentIndex.set(currentIndex.get() + 1);
}
Expand Down Expand Up @@ -216,19 +222,34 @@ document.addEventListener("astro:page-load", onLoad, { once: true});
document.addEventListener("astro:before-swap", (props) => {
const { to } = props;

if (interval) {
clearInterval(interval);
interval = null
}
if (timeout) {
clearTimeout(timeout)
timeout = null
};
if (to.pathname !== "/") {
eventListeners.forEach(({ target, type, listener }) => {
target?.removeEventListener(type, listener)
})
if (interval) {
clearInterval(interval);
interval = null
}
}
if (to.pathname === "/") {
document.addEventListener("astro:page-load", onLoad, { once: true});
}
})
document.addEventListener("astro:after-swap", (event) => {
// @ts-expect-error
const pathname = event.target?.location?.pathname;
if (pathname === "/") {
const codesContainer = getCodesContainer()
const codes = getCodes(codesContainer)
const newScrollLeft = getScrollLeft(codes, codesContainer);
scrollLeft.set(newScrollLeft);
codesContainer.scrollTo({ left: newScrollLeft, behavior: "instant" });
}
})
</script>

<style>
Expand Down
1 change: 1 addition & 0 deletions src/components/LatestCodeScroller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const LatestCodeScroller: FC = () => {
scrollDone.set(true);
},
});
return () => controls.current?.stop();
}, [scope, animate, scrollLeftValue]);

useEffect(() => {
Expand Down
10 changes: 5 additions & 5 deletions src/components/PostPreview.astro
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
---
import { getMonthName, mobileUserAgent } from "$/util";
import { getIsMobile } from "$/util";
import { getMonthName } from "$/util";
import { Image } from "astro:assets";
import type { CollectionEntry } from "astro:content";
const isMobile = getIsMobile(Astro);
import { format } from "date-fns";
interface Props {
post: CollectionEntry<"blog">;
Expand All @@ -15,6 +13,8 @@ interface Props {
const { post, noTransition } = Astro.props;
if (!post.data.cover) return "";
const formattedDate = format(post.data.pubDate, "yyyy-MM-dd");
---

<div>
Expand All @@ -28,7 +28,7 @@ if (!post.data.cover) return "";
<header>
<time
class="text-gray-200 code"
datetime="2024-04-11T00:00:00.000Z"
datetime={formattedDate}
>
{
`${new Date(post.data.pubDate).getDate()} ${
Expand Down
22 changes: 17 additions & 5 deletions src/components/PostPreviewList.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
import { getMonthName } from "$/util";
import type { CollectionEntry } from "astro:content";
import PostPreview from "./PostPreview.astro";
import { format } from "date-fns";
interface Props {
posts: CollectionEntry<"blog">[];
Expand Down Expand Up @@ -34,11 +36,21 @@ const { posts, heading, noTransition, asCard = false } = Astro.props;
: (
<ul>
{
posts.map((post) => (
<li class="mb-2 sm:mb-0">
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
</li>
))
posts.map((post) => {
const formattedDate = format(post.data.pubDate, "yyyy-MM-dd");
return (
<li class="mb-2 sm:mb-0">
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
<time class="ml-2 text-gray-400" datetime={formattedDate}>
{
`${new Date(post.data.pubDate).getDate()} ${
getMonthName(post.data.pubDate)
} ${new Date(post.data.pubDate).getFullYear()}`
}
</span>
</li>
)
})
}
</ul>
)
Expand Down
42 changes: 21 additions & 21 deletions src/components/PostStats.svelte
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
<script lang="ts">
import { onMount } from "svelte";
import { onMount } from "svelte";
export let slug: string = "";
export let slug = "";
let loading: boolean = false;
let views: number = 0;
let loading = false;
let views: number | null = null;
onMount(async () => {
if (slug && slug.trim() !== "") {
try {
loading = true;
const resp = await fetch(`/api/blog/views/${slug}.json?increment=true`);
const stats = await resp.json();
views = stats.views;
} catch (e) {
console.error("PostStats", e);
} finally {
loading = false;
}
onMount(async () => {
if (slug && slug.trim() !== "") {
try {
loading = true;
const resp = await fetch(`/api/blog/views/${slug}.json?increment=true`);
const stats = await resp.json();
views = stats.views;
} catch (e) {
console.error("PostStats", e);
} finally {
loading = false;
}
});
}
});
</script>

<span class="emdash">—</span>
<span class="post-stats__views">{views} views</span>
<span class="post-stats__views">{views || "~"} views</span>

<style>
.post-stats__views {
@apply mx-1 pr-1 italic text-accent-gray-mid;
}
.post-stats__views {
@apply mx-1 pr-1 italic text-accent-gray-mid;
}
</style>
38 changes: 0 additions & 38 deletions test/trpc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,6 @@ import { afterEach, beforeEach, describe, expect, it, test, vi } from "vitest";
import { mock } from "vitest-mock-extended";
import githubService from "../rpc-server/services/github.ts";
import prismaMock from "./mocks/prisma.ts";
// const createUserContext = (authId?: string, permissions?: string[]) => {
// let userPermissions = "openid profile email";
// if (permissions) {
// userPermissions = `${userPermissions} ${permissions.join(" ")}`;
// }
// return {
// session: {
// sub: authId,
// permissions: userPermissions,
// },
// user: `{"sub": "${authId}", "permissions": "${userPermissions}"}`,
// };
// };
// const mockGithubService = mock(githubService, () => {
// return {
// getRepoContents: vi.fn().mockImplementation(() => {}),
// getCommits: vi.fn().mockImplementation(() => {}),
// };
// });

vi.mock("../rpc-server/services/github.ts", () => {
return {
Expand Down Expand Up @@ -108,23 +89,4 @@ describe("appRouter", () => {
path: "data/packages/shared/shallowEqual.js",
});
});

// it("should increment views", async () => {
// const ctx = await createContext({});
// const caller = appRouter.createCaller(ctx);
//
// const input: inferProcedureInput<AppRouter["getFile"]> = {
// owner: "facebook",
// repo: "react",
// path: "data/packages/shared/shallowEqual.js",
// };
//
// const result = await caller.getFile(input);
//
// expect(result).toMatchObject({
// id: "1",
// title: "Buy milk",
// completed: false,
// });
// });
});
4 changes: 2 additions & 2 deletions tests/blog.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test, expect } from "@playwright/test";
import { expect, test } from "@playwright/test";
import { baseUrl } from "./util";

test.describe("Blog", () => {
Expand All @@ -16,7 +16,7 @@ test.describe("Blog", () => {
"/blog/ruby-now-produces-machine-code-on-the-fly",
);
await expect(
page.getByRole("link", { name: 'Go to the post titled "Ruby' }),
page.getByRole("link", { name: "Go to the post titled \"Ruby" }),
).toHaveAttribute(
"href",
"/blog/ruby-now-produces-machine-code-on-the-fly",
Expand Down
9 changes: 3 additions & 6 deletions tests/home.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test, expect } from "@playwright/test";
import { expect, test } from "@playwright/test";
import { baseUrl } from "./util";

test.describe("Posts", () => {
Expand All @@ -15,13 +15,13 @@ test.describe("Posts", () => {
// Image links
await expect(
page.getByRole("link", {
name: 'Go to the post titled "Wezterm workspace switcher API"',
name: "Go to the post titled \"Wezterm workspace switcher API\"",
}),
).toHaveAttribute("href", "/blog/wezterm-configuration-tricks");
await expect(
page
.getByRole("link", {
name: 'Go to the post titled "Neovim macros vs normal mode"',
name: "Go to the post titled \"Neovim macros vs normal mode\"",
exact: true,
})
.first(),
Expand Down Expand Up @@ -67,9 +67,6 @@ test.describe("nav", () => {
"href",
"/",
);
await expect(
page.getByRole("link", { name: "Blog", exact: true }),
).toHaveAttribute("href", "/blog/1");
await expect(page.getByRole("link", { name: "Tags" })).toHaveAttribute(
"href",
"/tags",
Expand Down

0 comments on commit 57667d1

Please sign in to comment.