diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index 7d5e1318..014288ef 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -63,7 +63,7 @@ const scrollTo = (el: HTMLElement) => { } const imgSrcRegExp = /]+src\s*=\s*["']([^"']+)["']/gi -const COMMENTS_PER_PAGE = 30 +export const COMMENTS_PER_PAGE = 30 const VOTES_PER_PAGE = 50 export const FullArticle = (props: Props) => { diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index a459e9c4..b534aa44 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -30,6 +30,7 @@ import styles from './Author.module.scss' type AuthorViewProps = { authorSlug: string shouts: Shout[] + comments: Reaction[] author?: Author } @@ -56,7 +57,7 @@ export const AuthorView = (props: AuthorViewProps) => { const [followers, setFollowers] = createSignal([] as Author[]) const [following, changeFollowing] = createSignal>([] as Array) // flat AuthorFollowsResult const [showExpandBioControl, setShowExpandBioControl] = createSignal(false) - const [commented, setCommented] = createSignal([]) + const [commented, setCommented] = createSignal(props.comments || []) const [followersLoaded, setFollowersLoaded] = createSignal(false) const [followingsLoaded, setFollowingsLoaded] = createSignal(false) @@ -64,36 +65,41 @@ export const AuthorView = (props: AuthorViewProps) => { 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 + createEffect( + on( + () => session()?.user?.app_data?.profile, + async (meData?: 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 (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) + 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) - } - } - }) + const followersResp = await client() + ?.query(getAuthorFollowersQuery, { slug: foundAuthor.slug }) + .toPromise() + setFollowers(followersResp?.data?.get_author_followers || []) + setFollowersLoaded(true) + } + } + }, + {} + ) + ) // Обработка биографии let bioContainerRef: HTMLDivElement @@ -138,7 +144,7 @@ export const AuthorView = (props: AuthorViewProps) => { ) const { feedByAuthor, addFeed } = useFeed() - const [sortedFeed, setSortedFeed] = createSignal([]) + const [sortedFeed, setSortedFeed] = createSignal(props.shouts || []) const [loadMoreHidden, setLoadMoreHidden] = createSignal(false) const loadMore = async () => { saveScrollPosition() @@ -166,7 +172,9 @@ export const AuthorView = (props: AuthorViewProps) => { ) ) - const [loadMoreCommentsHidden, setLoadMoreCommentsHidden] = createSignal(false) + const [loadMoreCommentsHidden, setLoadMoreCommentsHidden] = createSignal( + Boolean(props.author?.stat && props.author?.stat?.comments === 0) + ) const { commentsByAuthor, addReactions } = useReactions() const loadMoreComments = async () => { if (!author()) return [] as LoadMoreItems @@ -188,16 +196,14 @@ export const AuthorView = (props: AuthorViewProps) => { createEffect(() => setCurrentTab(params.tab)) + createEffect( + on([author, commentsByAuthor], ([a, ccc]) => a && ccc && ccc[a.id] && setCommented(ccc[a.id]), {}) + ) + createEffect( on( - [author, commentsByAuthor], - ([a, ccc]) => { - if (a && ccc && ccc[a.id]) { - setCommented(ccc[a.id]) - setLoadMoreCommentsHidden(ccc[a.id]?.length === a.stat?.comments) - } - }, - {} + [author, commented], + ([a, ccc]) => a && ccc && setLoadMoreCommentsHidden((ccc || []).length === a.stat?.comments) ) ) diff --git a/src/routes/author/[slug]/[...tab].tsx b/src/routes/author/[slug]/[...tab].tsx index ab7490ed..06593047 100644 --- a/src/routes/author/[slug]/[...tab].tsx +++ b/src/routes/author/[slug]/[...tab].tsx @@ -1,5 +1,6 @@ import { RouteSectionProps, createAsync } from '@solidjs/router' import { ErrorBoundary, Suspense, createEffect, createSignal, on } from 'solid-js' +import { COMMENTS_PER_PAGE } from '~/components/Article/FullArticle' import { AuthorView } from '~/components/Views/Author' import { FourOuFourView } from '~/components/Views/FourOuFour' import { Loading } from '~/components/_shared/Loading' @@ -8,11 +9,13 @@ import { useAuthors } from '~/context/authors' import { SHOUTS_PER_PAGE } from '~/context/feed' import { useLocalize } from '~/context/localize' import { ReactionsProvider } from '~/context/reactions' -import { loadAuthors, loadShouts, loadTopics } from '~/graphql/api/public' +import { loadAuthors, loadReactions, loadShouts, loadTopics } from '~/graphql/api/public' import { Author, LoadShoutsOptions, QueryLoad_Authors_ByArgs, + QueryLoad_Reactions_ByArgs, + Reaction, Shout, Topic } from '~/graphql/schema/core.gen' @@ -24,6 +27,16 @@ const fetchAuthorShouts = async (slug: string, offset?: number) => { return await shoutsLoader() } +const fetchAuthorComments = async (slug: string, offset?: number) => { + const opts: QueryLoad_Reactions_ByArgs = { + by: { comment: true, author: slug }, + limit: COMMENTS_PER_PAGE, + offset + } + const shoutsLoader = loadReactions(opts) + return await shoutsLoader() +} + const fetchAllTopics = async () => { const topicsFetcher = loadTopics() return await topicsFetcher() @@ -47,7 +60,12 @@ export const route = { } } -export type AuthorPageProps = { articles?: Shout[]; author?: Author; topics?: Topic[] } +export type AuthorPageProps = { + articles?: Shout[] + author?: Author + topics?: Topic[] + comments?: Reaction[] +} export default function AuthorPage(props: RouteSectionProps) { const { t } = useLocalize() @@ -109,6 +127,11 @@ export default function AuthorPage(props: RouteSectionProps) { async () => (props.data.articles as Shout[]) || (await fetchAuthorShouts(props.params.slug, 0)) ) + // author's comments + const authorComments = createAsync( + async () => (props.data.comments as Reaction[]) || (await fetchAuthorComments(props.params.slug, 0)) + ) + return ( }> }> @@ -124,6 +147,7 @@ export default function AuthorPage(props: RouteSectionProps) { author={author() as Author} authorSlug={props.params.slug} shouts={authorShouts() || []} + comments={authorComments() || []} />