import { createFileRoute } from "@tanstack/react-router";
import { useAtom } from "jotai";
import * as React from "react";
import { useLayoutEffect, useState } from "react";
import { Header } from "~/components/Header";
import { InfiniteCustomFeed } from "~/components/InfiniteCustomFeed";
import { useAuth } from "~/providers/UnifiedAuthProvider";
import {
feedScrollPositionsAtom,
isAtTopAtom,
quickAuthAtom,
selectedFeedUriAtom,
} from "~/utils/atoms";
//import { usePersistentStore } from "~/providers/PersistentStoreProvider";
import {
//constructArbitraryQuery,
//constructIdentityQuery,
//constructInfiniteFeedSkeletonQuery,
//constructPostQuery,
useQueryArbitrary,
useQueryIdentity,
useQueryPreferences,
} from "~/utils/useQuery";
export const Route = createFileRoute("/")({
// loader: async ({ context }) => {
// const { queryClient } = context;
// const atomauth = store.get(authedAtom);
// const atomagent = store.get(agentAtom);
// let identitypds: string | undefined;
// const initialselectedfeed = store.get(selectedFeedUriAtom);
// if (atomagent && atomauth && atomagent?.did) {
// const identityopts = constructIdentityQuery(atomagent.did);
// const identityresultmaybe =
// await queryClient.ensureQueryData(identityopts);
// identitypds = identityresultmaybe?.pds;
// }
// const arbitraryopts = constructArbitraryQuery(
// initialselectedfeed ??
// "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot"
// );
// const feedGengetrecordquery =
// await queryClient.ensureQueryData(arbitraryopts);
// const feedServiceDid = (feedGengetrecordquery?.value as any)?.did;
// //queryClient.ensureInfiniteQueryData()
// const { queryKey, queryFn } = constructInfiniteFeedSkeletonQuery({
// feedUri:
// initialselectedfeed ??
// "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot",
// agent: atomagent ?? undefined,
// isAuthed: atomauth ?? false,
// pdsUrl: identitypds,
// feedServiceDid: feedServiceDid,
// });
// const res = await queryClient.ensureInfiniteQueryData({
// queryKey,
// queryFn,
// initialPageParam: undefined as never,
// getNextPageParam: (lastPage: any) => lastPage.cursor as null | undefined,
// staleTime: Infinity,
// //refetchOnWindowFocus: false,
// //enabled: true,
// });
// await Promise.all(
// res.pages.map(async (page) => {
// await Promise.all(
// page.feed.map(async (feedviewpost) => {
// if (!feedviewpost.post) return;
// // /*mass comment*/ console.log("preloading: ", feedviewpost.post);
// const opts = constructPostQuery(feedviewpost.post);
// try {
// await queryClient.ensureQueryData(opts);
// } catch (e) {
// // /*mass comment*/ console.log(" failed:", e);
// }
// })
// );
// })
// );
// },
component: Home,
pendingComponent: PendingHome, // PendingHome,
staticData: { keepAlive: true },
});
function PendingHome() {
return
loading... (prefetching your timeline)
;
}
//function Homer() {
// return
//}
export function Home({ hidden = false }: { hidden?: boolean }) {
const {
agent,
status,
authMethod,
loginWithPassword,
loginWithOAuth,
logout,
} = useAuth();
const authed = !!agent?.did;
// i dont remember why this is even here
// useEffect(() => {
// if (agent?.did) {
// store.set(authedAtom, true);
// } else {
// store.set(authedAtom, false);
// }
// }, [status, agent, authed]);
// useEffect(() => {
// if (agent) {
// // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// // @ts-ignore is it just me or is the type really weird here it should be Agent not AtpAgent
// store.set(agentAtom, agent);
// } else {
// store.set(agentAtom, null);
// }
// }, [status, agent, authed]);
//const { get, set } = usePersistentStore();
// const [feed, setFeed] = React.useState([]);
// const [loading, setLoading] = React.useState(true);
// const [error, setError] = React.useState(null);
// const [prefs, setPrefs] = React.useState({});
// React.useEffect(() => {
// if (!loadering && authed && agent && agent.did) {
// const run = async () => {
// try {
// if (!agent.did) return;
// const prefs = await cachedGetPrefs({
// did: agent.did,
// agent,
// get,
// set,
// });
// // /*mass comment*/ console.log("alistoffeeds", prefs);
// setPrefs(prefs || {});
// } catch (err) {
// console.error("alistoffeeds Fetch error in preferences effect:", err);
// }
// };
// run();
// }
// }, [loadering, authed, agent]);
// const savedFeedsPref = React.useMemo(() => {
// if (!prefs?.preferences) return null;
// return prefs.preferences.find(
// (p: any) => p?.$type === "app.bsky.actor.defs#savedFeedsPrefV2",
// );
// }, [prefs]);
// const savedFeeds = savedFeedsPref?.items || [];
const [quickAuth, setQuickAuth] = useAtom(quickAuthAtom);
const isAuthRestoring = quickAuth ? status === "loading" : false;
const identityresultmaybe = useQueryIdentity(!isAuthRestoring ? agent?.did : undefined);
const identity = identityresultmaybe?.data;
const prefsresultmaybe = useQueryPreferences({
agent: !isAuthRestoring ? (agent ?? undefined) : undefined,
pdsUrl: !isAuthRestoring ? (identity?.pds) : undefined,
});
const prefs = prefsresultmaybe?.data;
const savedFeeds = React.useMemo(() => {
const savedFeedsPref = prefs?.preferences?.find(
(p: any) => p?.$type === "app.bsky.actor.defs#savedFeedsPrefV2"
);
return savedFeedsPref?.items || [];
}, [prefs]);
const [persistentSelectedFeed, setPersistentSelectedFeed] = useAtom(selectedFeedUriAtom);
const [unauthedSelectedFeed, setUnauthedSelectedFeed] = useState(persistentSelectedFeed);
const selectedFeed = agent?.did
? persistentSelectedFeed
: unauthedSelectedFeed;
const setSelectedFeed = agent?.did
? setPersistentSelectedFeed
: setUnauthedSelectedFeed;
// /*mass comment*/ console.log("my selectedFeed is: ", selectedFeed);
React.useEffect(() => {
const fallbackFeed =
"at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot";
if (authed) {
if (selectedFeed) return;
if (savedFeeds.length > 0) {
setSelectedFeed((prev) =>
prev && savedFeeds.some((f: any) => f.value === prev)
? prev
: savedFeeds[0].value
);
} else {
if (selectedFeed) return;
setSelectedFeed(fallbackFeed);
}
} else {
if (selectedFeed) return;
setSelectedFeed(fallbackFeed);
}
}, [savedFeeds, authed, setSelectedFeed]);
// React.useEffect(() => {
// if (loadering || !selectedFeed) return;
// let ignore = false;
// const run = async () => {
// setLoading(true);
// setError(null);
// try {
// if (authed && agent) {
// if (!agent.did) return;
// const pdsurl = await cachedResolveIdentity({
// didOrHandle: agent.did,
// get,
// set,
// });
// const fetchstringcomplex = `${pdsurl.pdsUrl}/xrpc/app.bsky.feed.getFeedSkeleton?feed=${selectedFeed}`;
// // /*mass comment*/ console.log("fetching feed authed: " + fetchstringcomplex);
// const feeddef = await cachedGetRecord({
// atUri: selectedFeed,
// get,
// set,
// });
// const feedservicedid = feeddef.value.did;
// const res = await agent.fetchHandler(fetchstringcomplex, {
// method: "GET",
// headers: {
// "atproto-proxy": `${feedservicedid}#bsky_fg`,
// "Content-Type": "application/json",
// },
// });
// if (!res.ok) throw new Error("Failed to fetch feed");
// const data = await res.json();
// if (!ignore) setFeed(data.feed || []);
// } else {
// // /*mass comment*/ console.log("falling back");
// // always use fallback feed for not logged in
// const fallbackFeed =
// "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot";
// // const feeddef = await cachedGetRecord({
// // atUri: fallbackFeed,
// // get,
// // set,
// // });
// //const feedservicedid = "did:web:discover.bsky.app" //feeddef.did;
// const fetchstringsimple = `https://discover.bsky.app/xrpc/app.bsky.feed.getFeedSkeleton?feed=${fallbackFeed}`;
// // /*mass comment*/ console.log("fetching feed unauthed: " + fetchstringsimple);
// const res = await fetch(fetchstringsimple);
// if (!res.ok) throw new Error("Failed to fetch feed");
// const data = await res.json();
// if (!ignore) setFeed(data.feed || []);
// }
// } catch (e) {
// if (!ignore) {
// if (e instanceof Error) {
// setError(e.message);
// } else {
// setError("Unknown error");
// }
// }
// } finally {
// if (!ignore) setLoading(false);
// }
// };
// run();
// return () => {
// ignore = true;
// };
// }, [authed, agent, loadering, selectedFeed, get, set]);
const [scrollPositions, setScrollPositions] = useAtom(
feedScrollPositionsAtom
);
const scrollPositionsRef = React.useRef(scrollPositions);
React.useEffect(() => {
scrollPositionsRef.current = scrollPositions;
}, [scrollPositions]);
useLayoutEffect(() => {
if (isAuthRestoring) return;
const savedPosition = scrollPositions[selectedFeed ?? "null"] ?? 0;
window.scrollTo({ top: savedPosition, behavior: "instant" });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedFeed, isAuthRestoring]);
useLayoutEffect(() => {
if (!selectedFeed || isAuthRestoring) return;
const handleScroll = () => {
scrollPositionsRef.current = {
...scrollPositionsRef.current,
[selectedFeed]: window.scrollY,
};
};
window.addEventListener("scroll", handleScroll, { passive: true });
return () => {
window.removeEventListener("scroll", handleScroll);
setScrollPositions(scrollPositionsRef.current);
};
}, [isAuthRestoring, selectedFeed, setScrollPositions]);
const feedGengetrecordquery = useQueryArbitrary(!isAuthRestoring ? selectedFeed ?? undefined : undefined);
const feedServiceDid = !isAuthRestoring ? (feedGengetrecordquery?.data?.value as any)?.did as string | undefined : undefined;
// const {
// data: feedData,
// isLoading: isFeedLoading,
// error: feedError,
// } = useQueryFeedSkeleton({
// feedUri: selectedFeed!,
// agent: agent ?? undefined,
// isAuthed: authed ?? false,
// pdsUrl: identity?.pds,
// feedServiceDid: feedServiceDid,
// });
// const feed = feedData?.feed || [];
const isReadyForAuthedFeed = !isAuthRestoring && authed && agent && identity?.pds && feedServiceDid;
const isReadyForUnauthedFeed = !isAuthRestoring && !authed && selectedFeed;
const [isAtTop] = useAtom(isAtTopAtom);
return (
{!isAuthRestoring && savedFeeds.length > 0 ? (
{savedFeeds.map((item: any, idx: number) => {return })}
) : (
//
Home
)}
{/* {isFeedLoading &&
Loading...
}
{feedError &&
{feedError.message}
}
{!isFeedLoading && !feedError && feed.length === 0 && (
No posts found.
)} */}
{/* {feed.map((item, i) => (
))} */}
{isAuthRestoring || authed && (!identity?.pds || !feedServiceDid) && (
Preparing your feed...
)}
{!isAuthRestoring && (isReadyForAuthedFeed || isReadyForUnauthedFeed) ? (
) : (
Loading.......
)}
{/* {false && restoringScrollPosition && (
restoringScrollPosition
)} */}
);
}
// todo please use types this is dangerous very dangerous.
// todo fix this whenever proper preferences is handled
function FeedTabOnTop({item, idx}:{item: any, idx: number}) {
const [persistentSelectedFeed, setPersistentSelectedFeed] = useAtom(selectedFeedUriAtom);
const selectedFeed = persistentSelectedFeed
const setSelectedFeed = setPersistentSelectedFeed
const rkey = item.value.split("/").pop() || item.value;
const isActive = selectedFeed === item.value;
const { data: feedrecord } = useQueryArbitrary(item.value)
const label = feedrecord?.value?.displayName || rkey
return (
);
}
// not even used lmaooo
// export async function cachedResolveDIDWEBDOC({
// didweb,
// cacheTimeout = CACHE_TIMEOUT,
// get,
// set,
// }: {
// didweb: string;
// cacheTimeout?: number;
// get: (key: string) => any;
// set: (key: string, value: string) => void;
// }): Promise {
// const isDidInput = didweb.startsWith("did:web:");
// const cacheKey = `didwebdoc:${didweb}`;
// const now = Date.now();
// const cached = get(cacheKey);
// if (
// cached &&
// cached.value &&
// cached.time &&
// now - cached.time < cacheTimeout
// ) {
// try {
// return JSON.parse(cached.value);
// } catch (_e) {/* whatever*/ }
// }
// const url = `https://free-fly-24.deno.dev/resolve-did-web?did=${encodeURIComponent(
// didweb
// )}`;
// const res = await fetch(url);
// if (!res.ok) throw new Error("Failed to resolve didwebdoc");
// const data = await res.json();
// set(cacheKey, JSON.stringify(data));
// if (!isDidInput && data.did) {
// set(`didwebdoc:${data.did}`, JSON.stringify(data));
// }
// return data;
// }
// export async function cachedGetPrefs({
// did,
// agent,
// get,
// set,
// cacheTimeout = CACHE_TIMEOUT,
// }: {
// did: string;
// agent: any; // or type properly if available
// get: (key: string) => any;
// set: (key: string, value: string) => void;
// cacheTimeout?: number;
// }): Promise {
// const cacheKey = `prefs:${did}`;
// const cached = get(cacheKey);
// const now = Date.now();
// if (
// cached &&
// cached.value &&
// cached.time &&
// now - cached.time < cacheTimeout
// ) {
// try {
// return JSON.parse(cached.value);
// } catch {
// // fall through to fetch
// }
// }
// const resolved = await cachedResolveIdentity({
// didOrHandle: did,
// get,
// set,
// });
// if (!resolved?.pdsUrl) throw new Error("Missing resolved PDS info");
// const fetchUrl = `${resolved.pdsUrl}/xrpc/app.bsky.actor.getPreferences`;
// const res = await agent.fetchHandler(fetchUrl, {
// method: "GET",
// headers: {
// "Content-Type": "application/json",
// },
// });
// if (!res.ok) throw new Error(`Failed to fetch preferences: ${res.status}`);
// const text = await res.text();
// let data: any;
// try {
// data = JSON.parse(text);
// } catch (err) {
// console.error("Failed to parse preferences JSON:", err);
// throw err;
// }
// set(cacheKey, JSON.stringify(data));
// return data;
// }