From b7d61fa03e83bf6fa4c06b816eb70ba41df35229 Mon Sep 17 00:00:00 2001 From: dusk <y.bera003.06@protonmail.com> Date: Sun, 16 Mar 2025 13:34:58 +0300 Subject: [PATCH] feat: add last updated date to status, instead of not displaying them, fix aligning of stuff --- src/components/note.svelte | 17 +++--------- src/components/token.svelte | 4 ++- src/lib/dateFmt.ts | 25 +++++++++++++++++ src/lib/lastfm.ts | 10 +++++-- src/lib/steam.ts | 10 +++++-- src/routes/+page.svelte | 54 +++++++++++++------------------------ 6 files changed, 67 insertions(+), 53 deletions(-) create mode 100644 src/lib/dateFmt.ts diff --git a/src/components/note.svelte b/src/components/note.svelte index 2cdc483..3d10599 100644 --- a/src/components/note.svelte +++ b/src/components/note.svelte @@ -25,6 +25,7 @@ </script> <script lang="ts"> import Token from "./token.svelte"; + import {renderDate, renderRelativeDate} from '$lib/dateFmt'; interface Props { note: NoteData; @@ -39,16 +40,6 @@ onlyContent = false, showOutgoing = true }: Props = $props(); - - const renderDate = (timestamp: number) => { - return (new Date(timestamp)).toLocaleString("en-GB", { - year: "2-digit", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - }) - } const getOutgoingLink = (name: string, link: string) => { if (name === "bsky") { @@ -65,8 +56,8 @@ } </script> -<div class="text-wrap break-words max-w-[70ch] leading-tight"> -{#if !onlyContent}<Token v={renderDate(note.published)} small={!isHighlighted}/>{/if} <Token v={note.content} str/> +<p class="m-0 max-w-[70ch] text-wrap break-words leading-tight align-middle"> +{#if !onlyContent}<Token title={renderDate(note.published)} v={renderRelativeDate(note.published)} small={!isHighlighted}/>{/if} <Token v={note.content} str/> {#if note.hasMedia}<Token v="-contains media-" keywd small/>{/if} {#if note.hasQuote}<Token v="-contains quote-" keywd small/>{/if} {#if showOutgoing} @@ -75,4 +66,4 @@ <span class="text-sm"><Token v="(" punct/><a class="hover:motion-safe:animate-squiggle hover:underline" style="color: {color};{getTextShadowStyle(color)}" href={getOutgoingLink(name, link)}>{name}</a><Token v=")" punct/></span> {/each} {/if} -</div> \ No newline at end of file +</p> \ No newline at end of file diff --git a/src/components/token.svelte b/src/components/token.svelte index 4ebb145..a6e834a 100644 --- a/src/components/token.svelte +++ b/src/components/token.svelte @@ -8,6 +8,7 @@ str?: boolean; small?: boolean; v: string; + title?: string; } let { @@ -16,6 +17,7 @@ funct = false, str = false, small = false, + title, v }: Props = $props(); @@ -27,4 +29,4 @@ : "" </script> -<span class="align-middle token {ty} {small ? "text-sm" : ""}">{v}</span> \ No newline at end of file +<span {title} class="token {ty} {small ? "text-sm" : ""}">{v}</span> \ No newline at end of file diff --git a/src/lib/dateFmt.ts b/src/lib/dateFmt.ts new file mode 100644 index 0000000..3020457 --- /dev/null +++ b/src/lib/dateFmt.ts @@ -0,0 +1,25 @@ +export const renderRelativeDate = (timestamp: number) => { + const elapsed = timestamp - (new Date()).getTime() + const units: Record<string, number> = { + year : 24 * 60 * 60 * 1000 * 365, + month : 24 * 60 * 60 * 1000 * 365/12, + day : 24 * 60 * 60 * 1000, + hour : 60 * 60 * 1000, + minute: 60 * 1000, + second: 1000 + } + const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }) + for (var unit in units) + if (Math.abs(elapsed) > units[unit] || unit == 'second') + return rtf.format(Math.round(elapsed / units[unit]), unit as Intl.RelativeTimeFormatUnit) + return "" +} +export const renderDate = (timestamp: number) => { + return (new Date(timestamp)).toLocaleString("en-GB", { + year: "2-digit", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + }) +} \ No newline at end of file diff --git a/src/lib/lastfm.ts b/src/lib/lastfm.ts index 8e34248..fed178f 100644 --- a/src/lib/lastfm.ts +++ b/src/lib/lastfm.ts @@ -2,7 +2,13 @@ import { get, writable } from "svelte/store" const GET_RECENT_TRACKS_ENDPOINT = "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=yusdacra&api_key=da1911d405b5b37383e200b8f36ee9ec&format=json&limit=1" -type LastTrack = {name: string, artist: string, image: string | null, link: string} +type LastTrack = { + name: string, + artist: string, + image: string | null, + link: string, + when: number, +} const lastTrack = writable<LastTrack | null>(null) export const lastFmUpdateNowPlaying = async () => { @@ -17,11 +23,11 @@ export const lastFmUpdateNowPlaying = async () => { artist: track.artist['#text'], image: track.image[2]['#text'] ?? null, link: track.url, + when: Date.now(), } lastTrack.set(data) } catch(why) { console.log("could not fetch last fm: ", why) - lastTrack.set(null) } } diff --git a/src/lib/steam.ts b/src/lib/steam.ts index f82041e..d86d5b8 100644 --- a/src/lib/steam.ts +++ b/src/lib/steam.ts @@ -5,7 +5,13 @@ import { get, writable } from "svelte/store"; const STEAM_ID = "76561198106829949" const GET_PLAYER_SUMMARY_ENDPOINT = `http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=${env.STEAM_API_KEY}&steamids=${STEAM_ID}&format=json` -type LastGame = {name: string, link: string, icon: string, pfp: string} +type LastGame = { + name: string, + link: string, + icon: string, + pfp: string, + when: number, +} const steamgriddbClient = writable<SGDB | null>(null) const lastGame = writable<LastGame | null>(null) @@ -28,11 +34,11 @@ export const steamUpdateNowPlaying = async () => { link: `https://store.steampowered.com/app/${profile.gameid}`, icon: icons[0].thumb.toString(), pfp: profile.avatarmedium, + when: Date.now(), } lastGame.set(game) } catch(why) { console.log("could not fetch steam: ", why) - lastGame.set(null) } } diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index bb28868..2f9781d 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -3,37 +3,13 @@ import Note from '../components/note.svelte'; import Window from '../components/window.svelte'; import LatestStuff from './lateststuff.md'; + import {renderDate, renderRelativeDate} from '$lib/dateFmt'; interface Props { data: any; } let { data }: Props = $props(); - - const renderDate = (timestamp: number) => { - return (new Date(timestamp)).toLocaleString("en-GB", { - year: "2-digit", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - }) - } - const renderRelativeDate = (timestamp: number) => { - const elapsed = timestamp - (new Date()).getTime() - const units: Record<string, number> = { - year : 24 * 60 * 60 * 1000 * 365, - month : 24 * 60 * 60 * 1000 * 365/12, - day : 24 * 60 * 60 * 1000, - hour : 60 * 60 * 1000, - minute: 60 * 1000, - second: 1000 - } - const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }) - for (var unit in units) - if (Math.abs(elapsed) > units[unit] || unit == 'second') - return rtf.format(Math.round(elapsed / units[unit]), unit as Intl.RelativeTimeFormatUnit) - } </script> <div class="flex flex-col md:flex-row gap-y-2 lg:gap-y-0 md:h-full h-card"> @@ -182,26 +158,24 @@ </div> {/if} {#if data.lastTrack} - <div class="flex flex-row m-1.5 border-4 border-double bg-ralsei-black"> + <div class="flex flex-row gap-0.5 m-1.5 border-4 border-double bg-ralsei-black"> <!-- svelte-ignore a11y_missing_attribute --> {#if data.lastTrack.image} <img - class="border-4 w-16 h-16" + class="border-4 w-[4.5rem] h-[4.5rem]" style="border-style: none double none none;" - width="64" - height="64" src={data.lastTrack.image} /> {:else} <img - class="border-4 w-16 h-16 p-2" + class="border-4 w-[4.5rem] h-[4.5rem] p-2" style="border-style: none double none none; image-rendering: pixelated;" src="/icons/cd_audio.webp" /> {/if} - <div class="flex flex-col max-w-[40ch] p-2 overflow-hidden"> + <div class="flex flex-col max-w-[40ch] p-2"> <p - class="text-shadow-green text-ralsei-green-light text-ellipsis text-nowrap overflow-hidden max-w-[30ch]" + class="text-shadow-green text-ralsei-green-light text-sm text-ellipsis text-nowrap overflow-hidden max-w-[30ch]" > <span class="text-sm text-shadow-white text-ralsei-white">listening to</span> <a @@ -216,6 +190,11 @@ <span class="text-shadow-white text-ralsei-white">by</span> <span title={data.lastTrack.artist}>{data.lastTrack.artist}</span> </p> + <p + class="text-shadow-white text-ralsei-white text-xs text-ellipsis text-nowrap overflow-hidden max-w-[30ch]" + > + …{renderRelativeDate(data.lastTrack.when)} + </p> </div> </div> {/if} @@ -223,21 +202,26 @@ <div class="flex flex-row m-1.5 border-4 border-double bg-ralsei-black"> <!-- svelte-ignore a11y_missing_attribute --> <img - class="border-4 w-16 h-16" + class="border-4 w-[4.5rem] h-[4.5rem]" style="border-style: none double none none;" width="64" height="64" src={data.lastGame.icon} /> - <div class="flex flex-col max-w-[40ch] p-2 gap-1 overflow-hidden"> + <div class="flex flex-col max-w-[40ch] p-2 gap-0.5 overflow-hidden"> <p - class="text-shadow-green text-ralsei-green-light text-ellipsis text-nowrap overflow-hidden max-w-[30ch]" + class="text-shadow-green text-ralsei-green-light text-sm text-ellipsis text-nowrap overflow-hidden max-w-[30ch]" > <span class="text-sm text-shadow-white text-ralsei-white">playing</span> <a title={data.lastGame.name} class="hover:underline" href={data.lastGame.link} >{data.lastGame.name}</a > </p> + <p + class="text-shadow-white text-ralsei-white text-xs text-ellipsis text-nowrap overflow-hidden max-w-[30ch]" + > + …{renderRelativeDate(data.lastGame.when)} + </p> <!-- svelte-ignore a11y_missing_attribute --> <a href="https://steamcommunity.com/id/yusdacra"