import type { Author, Reaction, Shout, Topic, } from "../../../graphql/schema/core.gen"; import { getPagePath } from "@nanostores/router"; import { Meta, Title } from "@solidjs/meta"; import { clsx } from "clsx"; import { For, Match, Show, Switch, createEffect, createMemo, createSignal, onMount, } from "solid-js"; import { useFollowing } from "../../../context/following"; import { useLocalize } from "../../../context/localize"; import { useSession } from "../../../context/session"; import { apiClient } from "../../../graphql/client/core"; import { router, useRouter } from "../../../stores/router"; import { loadShouts, useArticlesStore } from "../../../stores/zine/articles"; import { loadAuthor, useAuthorsStore } from "../../../stores/zine/authors"; import { getImageUrl } from "../../../utils/getImageUrl"; import { getDescription } from "../../../utils/meta"; import { restoreScrollPosition, saveScrollPosition, } from "../../../utils/scroll"; import { splitToPages } from "../../../utils/splitToPages"; import { Comment } from "../../Article/Comment"; import { AuthorCard } from "../../Author/AuthorCard"; import { AuthorShoutsRating } from "../../Author/AuthorShoutsRating"; import { Row1 } from "../../Feed/Row1"; import { Row2 } from "../../Feed/Row2"; import { Row3 } from "../../Feed/Row3"; import { Loading } from "../../_shared/Loading"; import { MODALS, hideModal } from "../../../stores/ui"; import { byCreated } from "../../../utils/sortby"; import stylesArticle from "../../Article/Article.module.scss"; import styles from "./Author.module.scss"; type Props = { authorSlug: string; shouts?: Shout[]; author?: Author; }; export const PRERENDERED_ARTICLES_COUNT = 12; const LOAD_MORE_PAGE_SIZE = 9; export const AuthorView = (props: Props) => { const { t } = useLocalize(); const { subscriptions, followers: myFollowers, loadSubscriptions, } = useFollowing(); const { session } = useSession(); const { sortedArticles } = useArticlesStore({ shouts: props.shouts }); const { authorEntities } = useAuthorsStore({ authors: [props.author] }); const { page: getPage, searchParams } = useRouter(); const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false); const [isBioExpanded, setIsBioExpanded] = createSignal(false); const [author, setAuthor] = createSignal(); const [followers, setFollowers] = createSignal([]); const [following, setFollowing] = createSignal>([]); // flat AuthorFollowsResult const [showExpandBioControl, setShowExpandBioControl] = createSignal(false); const [commented, setCommented] = createSignal(); const modal = MODALS[searchParams().m]; // current author createEffect(() => { if (props.authorSlug) { if (session()?.user?.app_data?.profile?.slug === props.authorSlug) { console.info("my own profile"); const { profile, authors, topics } = session().user.app_data; setFollowers(myFollowers); setAuthor(profile); setFollowing([...authors, ...topics]); } } else { try { const a = authorEntities()[props.authorSlug]; setAuthor(a); // TODO: add following data retrieval console.debug("[Author] expecting following data fetched"); } catch (error) { console.debug(error); } } }); createEffect(async () => { if (author()?.id && !author().stat) { const a = await loadAuthor({ slug: "", author_id: author().id }); console.debug("[AuthorView] loaded author:", a); } }); const bioContainerRef: { current: HTMLDivElement } = { current: null }; const bioWrapperRef: { current: HTMLDivElement } = { current: null }; const fetchData = async (slug) => { try { const [subscriptionsResult, followersResult] = await Promise.all([ apiClient.getAuthorFollows({ slug }), apiClient.getAuthorFollowers({ slug }), ]); const { authors, topics } = subscriptionsResult; setFollowing([...(authors || []), ...(topics || [])]); setFollowers(followersResult || []); console.info("[components.Author] following data loaded"); } catch (error) { console.error("[components.Author] fetch error", error); } }; const checkBioHeight = () => { if (bioContainerRef.current) { setShowExpandBioControl( bioContainerRef.current.offsetHeight > bioWrapperRef.current.offsetHeight, ); } }; onMount(() => { fetchData(props.authorSlug); if (!modal) { hideModal(); } }); const loadMore = async () => { saveScrollPosition(); const { hasMore } = await loadShouts({ filters: { author: props.authorSlug }, limit: LOAD_MORE_PAGE_SIZE, offset: sortedArticles().length, }); setIsLoadMoreButtonVisible(hasMore); restoreScrollPosition(); }; onMount(() => { checkBioHeight(); // pagination if (sortedArticles().length === PRERENDERED_ARTICLES_COUNT) { loadMore(); loadSubscriptions(); } }); const pages = createMemo(() => splitToPages( sortedArticles(), PRERENDERED_ARTICLES_COUNT, LOAD_MORE_PAGE_SIZE, ), ); const fetchComments = async (commenter: Author) => { const data = await apiClient.getReactionsBy({ by: { comment: false, created_by: commenter.id }, }); setCommented(data); }; createEffect(() => { if (author()) { fetchComments(author()); } }); const ogImage = createMemo(() => author()?.pic ? getImageUrl(author()?.pic, { width: 1200 }) : getImageUrl("production/image/logo_image.png"), ); const description = createMemo(() => getDescription(author()?.bio)); const handleDeleteComment = (id: number) => { setCommented((prev) => prev.filter((comment) => comment.id !== id)); }; return (
{author().name}
(bioWrapperRef.current = el)} class={styles.longBio} classList={{ [styles.longBioExpanded]: isBioExpanded() }} >
(bioContainerRef.current = el)} innerHTML={author().about} />
    {(comment) => ( handleDeleteComment(id)} /> )}
3}> {(page) => ( <> )}

); };