diff --git a/src/lib/components/PostComponent.svelte b/src/lib/components/PostComponent.svelte
index 5bc09d2..f15245a 100644
--- a/src/lib/components/PostComponent.svelte
+++ b/src/lib/components/PostComponent.svelte
@@ -2,10 +2,24 @@
import type { Post } from '$lib/mastodon/response';
import AvatarComponent from '$lib/components/AvatarComponent.svelte';
import AccountComponent from '$lib/components/AccountComponent.svelte';
+ import { secondsSince, relativeTime } from '$lib/relativeTime';
+ import { onMount } from "svelte";
export let post: Post;
- let dateCreated: string;
- $: dateCreated = new Date(post.created_at).toLocaleString();
+ let displayRelativeTime = false;
+ const absoluteDate = new Date(post.created_at).toLocaleString();
+ let dateCreated = absoluteDate;
+ const timePassed = secondsSince(new Date(post.created_at));
+ $: if(displayRelativeTime) {
+ dateCreated = relativeTime($timePassed) ?? absoluteDate;
+ }
+
+ onMount(() => {
+ // Display relative time only after mount:
+ // When JS is disabled the server-side rendered absolute date will be shown,
+ // otherwise the relative date would be outdated very quickly
+ displayRelativeTime = true;
+ })
@@ -14,7 +28,7 @@
diff --git a/src/lib/relativeTime.ts b/src/lib/relativeTime.ts
new file mode 100644
index 0000000..c0955c7
--- /dev/null
+++ b/src/lib/relativeTime.ts
@@ -0,0 +1,40 @@
+import { derived, readable, type Readable } from 'svelte/store';
+
+export const time = readable(new Date(), function start(set) {
+ const interval = setInterval(() => {
+ set(new Date());
+ }, 10000); //Every 10sec is enough, we don't need that much granularity
+
+ return function stop() {
+ clearInterval(interval);
+ };
+});
+
+export function secondsSince(date: Date): Readable {
+ return derived(
+ time,
+ $time => Math.round(($time.getTime() - date.getTime()) / 1000)
+ );
+}
+
+export function relativeTime(seconds: number): string | null {
+ const min = 60;
+ if (seconds < min) {
+ return 'just now';
+ }
+
+ const hour = 60 * min;
+ if (seconds < hour) {
+ return `${Math.floor(seconds / min)}min`;
+ }
+
+ const day = hour * 24;
+ if (seconds < day) {
+ return `${(Math.floor(seconds / hour))}h`;
+ }
+ const maxRelative = day * 31;
+ if (seconds < maxRelative) {
+ return `${seconds % day}d`;
+ }
+ return null;
+}
\ No newline at end of file
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 97dbe9e..bd4e83e 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -30,7 +30,7 @@ let loadingOlderPosts = false;
// Needed, so that edgeFly() can do its thing:
// To determine whether a newly loaded post is older than the existing ones, is required to know what the oldest
// post was, before the fetch happened.
-let oldestBeforeLastFetch: number | null = null;
+let oldestBeforeLastFetch: number | null = null;
/**
* Animate either from the top, or the bottom of the window, depending if the post is