import type { Author, Reaction, Shout, Topic } from '../../../graphql/schema/core.gen' import { getPagePath } from '@nanostores/router' import { clsx } from 'clsx' import { For, Match, Show, Switch, createEffect, createMemo, createSignal, on, onMount } from 'solid-js' import { useFollowing } from '../../../context/following' import { useLocalize } from '../../../context/localize' import { Meta, Title } from '../../../context/meta' 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 } 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 { Placeholder } from '../../Feed/Placeholder' 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 { followers: myFollowers, follows: myFollows } = useFollowing() const { author: me } = useSession() const { sortedArticles } = useArticlesStore({ shouts: props.shouts }) const { page: getPage, searchParams } = useRouter() const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false) const [isBioExpanded, setIsBioExpanded] = createSignal(false) const [author, setAuthor] = createSignal(props.author) const [followers, setFollowers] = createSignal([]) const [following, changeFollowing] = createSignal>([]) // flat AuthorFollowsResult const [showExpandBioControl, setShowExpandBioControl] = createSignal(false) const [commented, setCommented] = createSignal() const modal = MODALS[searchParams().m] // пагинация загрузки ленты постов const loadMore = async () => { saveScrollPosition() const { hasMore } = await loadShouts({ filters: { author: props.authorSlug }, limit: LOAD_MORE_PAGE_SIZE, offset: sortedArticles().length, }) setIsLoadMoreButtonVisible(hasMore) restoreScrollPosition() } // загружает профиль и подписки const [isFetching, setIsFetching] = createSignal(false) const fetchData = async (slug) => { setIsFetching(true) const authorResult = await loadAuthor({ slug }) setAuthor(authorResult) console.info(`[Author] profile for @${slug} fetched`) const followsResult = await apiClient.getAuthorFollows({ slug }) const { authors, topics } = followsResult changeFollowing([...(authors || []), ...(topics || [])]) console.info(`[Author] follows for @${slug} fetched`) const followersResult = await apiClient.getAuthorFollowers({ slug }) setFollowers(followersResult || []) console.info(`[Author] followers for @${slug} fetched`) setIsFetching(false) } // проверяет не собственный ли это профиль, иначе - загружает createEffect( on([() => me(), () => props.authorSlug], ([myProfile, slug]) => { const my = slug && myProfile?.slug === slug if (my) { console.debug('[Author] my profile precached') myProfile && setAuthor(myProfile) setFollowers(myFollowers() || []) changeFollowing([...(myFollows?.authors || []), ...(myFollows?.topics || [])]) } else if (slug && !isFetching()) { fetchData(slug) } }), { defer: true }, ) // догружает ленту и комментарии createEffect( on(author, async (profile) => { if (!commented() && profile) { await loadMore() const ccc = await apiClient.getReactionsBy({ by: { comment: true, created_by: profile.id }, }) setCommented(ccc) } }), ) const bioContainerRef: { current: HTMLDivElement } = { current: null } const bioWrapperRef: { current: HTMLDivElement } = { current: null } const checkBioHeight = () => { if (bioContainerRef.current) { setShowExpandBioControl(bioContainerRef.current.offsetHeight > bioWrapperRef.current.offsetHeight) } } onMount(() => { if (!modal) hideModal() checkBioHeight() }) const pages = createMemo(() => splitToPages(sortedArticles(), PRERENDERED_ARTICLES_COUNT, LOAD_MORE_PAGE_SIZE), ) 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)} /> )}
0}> 3}> {(page) => ( <> )}

) }