import { A, useLocation, useParams } from '@solidjs/router' import { clsx } from 'clsx' import { For, Match, Show, Switch, createEffect, createMemo, createSignal, on } from 'solid-js' import { LoadMoreItems, LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper' import { Loading } from '~/components/_shared/Loading' import { coreApiUrl } from '~/config' import { useAuthors } from '~/context/authors' import { SHOUTS_PER_PAGE, useFeed } from '~/context/feed' import { useFollowing } from '~/context/following' import { useLocalize } from '~/context/localize' import { useReactions } from '~/context/reactions' import { useSession } from '~/context/session' import { loadReactions, loadShouts } from '~/graphql/api/public' import { graphqlClientCreate } from '~/graphql/client' import getAuthorFollowersQuery from '~/graphql/query/core/author-followers' import getAuthorFollowsQuery from '~/graphql/query/core/author-follows' import type { Author, Reaction, Shout, Topic } from '~/graphql/schema/core.gen' import { restoreScrollPosition, saveScrollPosition } from '~/utils/scroll' import { byCreated } from '~/utils/sort' import stylesArticle from '../../Article/Article.module.scss' import { Comment } from '../../Article/Comment' import { AuthorCard } from '../../Author/AuthorCard' import { AuthorShoutsRating } from '../../Author/AuthorShoutsRating' import { Placeholder } from '../../Feed/Placeholder' import { Row1 } from '../../Feed/Row1' import { Row2 } from '../../Feed/Row2' import { Row3 } from '../../Feed/Row3' import styles from './Author.module.scss' type AuthorViewProps = { authorSlug: string shouts: Shout[] author?: Author } export const PRERENDERED_ARTICLES_COUNT = 12 const COMMENTS_PER_PAGE = 12 // const LOAD_MORE_PAGE_SIZE = 9 export const AuthorView = (props: AuthorViewProps) => { // contexts const { t } = useLocalize() const loc = useLocation() const params = useParams() const [currentTab, setCurrentTab] = createSignal(params.tab) const { session } = useSession() const client = createMemo(() => graphqlClientCreate(coreApiUrl, session()?.access_token)) const { loadAuthor, authorsEntities } = useAuthors() const { followers: myFollowers, follows: myFollows } = useFollowing() // signals const [isBioExpanded, setIsBioExpanded] = createSignal(false) const [author, setAuthor] = createSignal() const [followers, setFollowers] = createSignal([] as Author[]) const [following, changeFollowing] = createSignal>([] as Array) // flat AuthorFollowsResult const [showExpandBioControl, setShowExpandBioControl] = createSignal(false) const [commented, setCommented] = createSignal([]) const [followersLoaded, setFollowersLoaded] = createSignal(false) const [followingsLoaded, setFollowingsLoaded] = createSignal(false) // derivatives const me = createMemo(() => session()?.user?.app_data?.profile as Author) // Объединенный эффект для загрузки автора и его подписок createEffect(async () => { const meData = session()?.user?.app_data?.profile as Author const slug = props.authorSlug if (slug && meData?.slug === slug) { setAuthor(meData) setFollowers(myFollowers() || []) setFollowersLoaded(true) changeFollowing([...(myFollows?.topics || []), ...(myFollows?.authors || [])]) } else if (slug && !author()) { await loadAuthor({ slug }) const foundAuthor = authorsEntities()[slug] setAuthor(foundAuthor) if (foundAuthor) { const followsResp = await client() ?.query(getAuthorFollowsQuery, { slug: foundAuthor.slug }) .toPromise() const follows = followsResp?.data?.get_author_followers || {} changeFollowing([...(follows?.authors || []), ...(follows?.topics || [])]) setFollowingsLoaded(true) const followersResp = await client() ?.query(getAuthorFollowersQuery, { slug: foundAuthor.slug }) .toPromise() setFollowers(followersResp?.data?.get_author_followers || []) setFollowersLoaded(true) } } }) // Обработка биографии let bioContainerRef: HTMLDivElement let bioWrapperRef: HTMLDivElement const checkBioHeight = () => { if (bioWrapperRef && bioContainerRef) { const showExpand = bioContainerRef.offsetHeight > bioWrapperRef.offsetHeight setShowExpandBioControl(showExpand) } } createEffect(() => { checkBioHeight() }) const handleDeleteComment = (id: number) => { setCommented((prev) => (prev || []).filter((comment) => comment.id !== id)) } const TabNavigator = () => ( ) const { feedByAuthor, addFeed } = useFeed() const [sortedFeed, setSortedFeed] = createSignal([]) const [loadMoreHidden, setLoadMoreHidden] = createSignal(false) const loadMore = async () => { saveScrollPosition() const authorhoutsFetcher = loadShouts({ filters: { author: props.authorSlug }, limit: SHOUTS_PER_PAGE, offset: feedByAuthor()?.[props.authorSlug]?.length || 0 }) const result = await authorhoutsFetcher() result && addFeed(result) restoreScrollPosition() return result as LoadMoreItems } // fx to update author's feed createEffect( on( feedByAuthor, (byAuthor) => { const feed = byAuthor[props.authorSlug] as Shout[] if (!feed) return setSortedFeed(feed) }, {} ) ) const [loadMoreCommentsHidden, setLoadMoreCommentsHidden] = createSignal(false) const { commentsByAuthor, addReactions } = useReactions() const loadMoreComments = async () => { if (!author()) return [] as LoadMoreItems saveScrollPosition() const aid = author()?.id || 0 const authorCommentsFetcher = loadReactions({ by: { comment: true, author: author()?.slug }, limit: COMMENTS_PER_PAGE, offset: commentsByAuthor()[aid]?.length || 0 }) const result = await authorCommentsFetcher() result && addReactions(result) restoreScrollPosition() return result as LoadMoreItems } createEffect(() => setCurrentTab(params.tab)) createEffect( on( [author, commentsByAuthor], ([a, ccc]) => { if (a && ccc && ccc[a.id]) { setCommented(ccc[a.id]) setLoadMoreCommentsHidden(ccc[a.id]?.length === a.stat?.comments) } }, {} ) ) createEffect( on( [author, feedByAuthor], ([a, feed]) => a && feed[props.authorSlug] && setLoadMoreHidden(feed[props.authorSlug]?.length === a.stat?.shouts), {} ) ) return (
}> <>
{t('All posts rating')}
(bioWrapperRef = el)} class={styles.longBio} classList={{ [styles.longBioExpanded]: isBioExpanded() }} >
(bioContainerRef = el)} innerHTML={author()?.about || ''} />
) }