diff --git a/src/masto/timelines.ts b/src/masto/timelines.ts index 19abea7..0f04e83 100644 --- a/src/masto/timelines.ts +++ b/src/masto/timelines.ts @@ -248,6 +248,64 @@ export type TimelineResource = [ { refetch(info?: TimelineFetchDirection): void }, ]; +export const emptyTimeline = { + list() { + return emptyTimeline; + }, + + setDirection() { + return emptyTimeline; + }, + + async next(): Promise> { + return { + value: undefined, + done: true, + }; + }, + + getDirection(): TimelineFetchDirection { + return "next"; + }, + + clone() { + return emptyTimeline; + }, + + async return(): Promise> { + return { + value: undefined, + done: true, + }; + }, + + async throw(e?: unknown) { + throw e; + }, + + async *values() {}, + async *[Symbol.asyncIterator](): AsyncIterator { + return undefined; + }, + + async then( + onresolve?: null | ((value: any[]) => TNext | PromiseLike), + onrejected?: null | ((reason: unknown) => ENext | PromiseLike), + ) { + try { + if (!onresolve) { + throw new TypeError("no onresolve"); + } + return await onresolve([]); + } catch (reason) { + if (!onrejected) { + throw reason; + } + return await onrejected(reason); + } + }, +}; + /** * Create auto managed timeline controls. * diff --git a/src/profiles/Profile.tsx b/src/profiles/Profile.tsx index b743acd..02bd5de 100644 --- a/src/profiles/Profile.tsx +++ b/src/profiles/Profile.tsx @@ -47,7 +47,11 @@ import { useSessionForAcctStr } from "../masto/clients"; import { resolveCustomEmoji } from "../masto/toot"; import { FastAverageColor } from "fast-average-color"; import { useWindowSize } from "@solid-primitives/resize-observer"; -import { createTimeline, createTimelineSnapshot } from "../masto/timelines"; +import { + createTimeline, + createTimelineSnapshot, + emptyTimeline, +} from "../masto/timelines"; import TootList from "../timelines/TootList"; import { createTimeSource, TimeSourceProvider } from "~platform/timesrc"; import TootFilterButton from "./TootFilterButton"; @@ -102,6 +106,9 @@ const Profile: Component = () => { const [profileUncaught] = createResource( () => [session().client, params.id] as const, async ([client, id]) => { + if (id.startsWith("@")) { + return await client.v1.accounts.lookup({ acct: id.slice(1) }); + } return await client.v1.accounts.$select(id).fetch(); }, ); @@ -114,6 +121,15 @@ const Profile: Component = () => { } }; + const profileAcctId = () => { + if (params.id.startsWith("@")) { + // Webfinger + return profile()?.id; + } else { + return params.id; + } + }; + const isCurrentSessionProfile = () => { return (session().account as Account).inf?.url === profile()?.url; }; @@ -125,26 +141,33 @@ const Profile: Component = () => { original: true, }); + const recentTimeline = () => { + const id = profileAcctId(); + + if (id) { + return session().client.v1.accounts.$select(id).statuses; + } else { + return emptyTimeline; + } + }; + const [recentToots, recentTootChunk, { refetch: refetchRecentToots }] = - createTimeline( - () => session().client.v1.accounts.$select(params.id).statuses, - () => { - const { boost, reply } = recentTootFilter(); - return { limit: 20, excludeReblogs: !boost, excludeReplies: !reply }; - }, - ); + createTimeline(recentTimeline, () => { + const { boost, reply } = recentTootFilter(); + return { limit: 20, excludeReblogs: !boost, excludeReplies: !reply }; + }); const [pinnedToots, pinnedTootChunk] = createTimelineSnapshot( - () => session().client.v1.accounts.$select(params.id).statuses, + recentTimeline, () => { return { limit: 20, pinned: true }; }, ); const [relationshipUncaught, { mutate: mutateRelationship }] = createResource( - () => [session(), params.id] as const, + () => [session(), profileAcctId()] as const, async ([sess, id]) => { - if (!sess.account) return; // No account, no relation + if (!sess.account || !id) return; // No account, no relation const relations = await session().client.v1.accounts.relationships.fetch({ id: [id], }); @@ -177,16 +200,17 @@ const Profile: Component = () => { const toggleSubscribeHome = async (event: Event) => { const client = session().client; - if (!session().account) return; + const acctId = profileAcctId(); + if (!session().account || !acctId) return; const isSubscribed = relationship()?.following ?? false; mutateRelationship((x) => Object.assign({ following: !isSubscribed }, x)); subscribeMenuState.onClose(event); if (isSubscribed) { - const nrel = await client.v1.accounts.$select(params.id).unfollow(); + const nrel = await client.v1.accounts.$select(acctId).unfollow(); mutateRelationship(nrel); } else { - const nrel = await client.v1.accounts.$select(params.id).follow(); + const nrel = await client.v1.accounts.$select(acctId).follow(); mutateRelationship(nrel); } };