comments-view-fix

This commit is contained in:
Untone 2024-09-03 19:50:26 +03:00
parent a2999e3851
commit 7a2043f223
3 changed files with 71 additions and 41 deletions

View File

@ -63,7 +63,7 @@ const scrollTo = (el: HTMLElement) => {
} }
const imgSrcRegExp = /<img[^>]+src\s*=\s*["']([^"']+)["']/gi const imgSrcRegExp = /<img[^>]+src\s*=\s*["']([^"']+)["']/gi
const COMMENTS_PER_PAGE = 30 export const COMMENTS_PER_PAGE = 30
const VOTES_PER_PAGE = 50 const VOTES_PER_PAGE = 50
export const FullArticle = (props: Props) => { export const FullArticle = (props: Props) => {

View File

@ -30,6 +30,7 @@ import styles from './Author.module.scss'
type AuthorViewProps = { type AuthorViewProps = {
authorSlug: string authorSlug: string
shouts: Shout[] shouts: Shout[]
comments: Reaction[]
author?: Author author?: Author
} }
@ -56,7 +57,7 @@ export const AuthorView = (props: AuthorViewProps) => {
const [followers, setFollowers] = createSignal<Author[]>([] as Author[]) const [followers, setFollowers] = createSignal<Author[]>([] as Author[])
const [following, changeFollowing] = createSignal<Array<Author | Topic>>([] as Array<Author | Topic>) // flat AuthorFollowsResult const [following, changeFollowing] = createSignal<Array<Author | Topic>>([] as Array<Author | Topic>) // flat AuthorFollowsResult
const [showExpandBioControl, setShowExpandBioControl] = createSignal(false) const [showExpandBioControl, setShowExpandBioControl] = createSignal(false)
const [commented, setCommented] = createSignal<Reaction[]>([]) const [commented, setCommented] = createSignal<Reaction[]>(props.comments || [])
const [followersLoaded, setFollowersLoaded] = createSignal(false) const [followersLoaded, setFollowersLoaded] = createSignal(false)
const [followingsLoaded, setFollowingsLoaded] = createSignal(false) const [followingsLoaded, setFollowingsLoaded] = createSignal(false)
@ -64,36 +65,41 @@ export const AuthorView = (props: AuthorViewProps) => {
const me = createMemo<Author>(() => session()?.user?.app_data?.profile as Author) const me = createMemo<Author>(() => session()?.user?.app_data?.profile as Author)
// Объединенный эффект для загрузки автора и его подписок // Объединенный эффект для загрузки автора и его подписок
createEffect(async () => { createEffect(
const meData = session()?.user?.app_data?.profile as Author on(
const slug = props.authorSlug () => session()?.user?.app_data?.profile,
async (meData?: Author) => {
const slug = props.authorSlug
if (slug && meData?.slug === slug) { if (slug && meData?.slug === slug) {
setAuthor(meData) setAuthor(meData)
setFollowers(myFollowers() || []) setFollowers(myFollowers() || [])
setFollowersLoaded(true) setFollowersLoaded(true)
changeFollowing([...(myFollows?.topics || []), ...(myFollows?.authors || [])]) changeFollowing([...(myFollows?.topics || []), ...(myFollows?.authors || [])])
} else if (slug && !author()) { } else if (slug && !author()) {
await loadAuthor({ slug }) await loadAuthor({ slug })
const foundAuthor = authorsEntities()[slug] const foundAuthor = authorsEntities()[slug]
setAuthor(foundAuthor) setAuthor(foundAuthor)
if (foundAuthor) { if (foundAuthor) {
const followsResp = await client() const followsResp = await client()
?.query(getAuthorFollowsQuery, { slug: foundAuthor.slug }) ?.query(getAuthorFollowsQuery, { slug: foundAuthor.slug })
.toPromise() .toPromise()
const follows = followsResp?.data?.get_author_followers || {} const follows = followsResp?.data?.get_author_followers || {}
changeFollowing([...(follows?.authors || []), ...(follows?.topics || [])]) changeFollowing([...(follows?.authors || []), ...(follows?.topics || [])])
setFollowingsLoaded(true) setFollowingsLoaded(true)
const followersResp = await client() const followersResp = await client()
?.query(getAuthorFollowersQuery, { slug: foundAuthor.slug }) ?.query(getAuthorFollowersQuery, { slug: foundAuthor.slug })
.toPromise() .toPromise()
setFollowers(followersResp?.data?.get_author_followers || []) setFollowers(followersResp?.data?.get_author_followers || [])
setFollowersLoaded(true) setFollowersLoaded(true)
} }
} }
}) },
{}
)
)
// Обработка биографии // Обработка биографии
let bioContainerRef: HTMLDivElement let bioContainerRef: HTMLDivElement
@ -138,7 +144,7 @@ export const AuthorView = (props: AuthorViewProps) => {
) )
const { feedByAuthor, addFeed } = useFeed() const { feedByAuthor, addFeed } = useFeed()
const [sortedFeed, setSortedFeed] = createSignal<Shout[]>([]) const [sortedFeed, setSortedFeed] = createSignal<Shout[]>(props.shouts || [])
const [loadMoreHidden, setLoadMoreHidden] = createSignal(false) const [loadMoreHidden, setLoadMoreHidden] = createSignal(false)
const loadMore = async () => { const loadMore = async () => {
saveScrollPosition() 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 { commentsByAuthor, addReactions } = useReactions()
const loadMoreComments = async () => { const loadMoreComments = async () => {
if (!author()) return [] as LoadMoreItems if (!author()) return [] as LoadMoreItems
@ -188,16 +196,14 @@ export const AuthorView = (props: AuthorViewProps) => {
createEffect(() => setCurrentTab(params.tab)) createEffect(() => setCurrentTab(params.tab))
createEffect(
on([author, commentsByAuthor], ([a, ccc]) => a && ccc && ccc[a.id] && setCommented(ccc[a.id]), {})
)
createEffect( createEffect(
on( on(
[author, commentsByAuthor], [author, commented],
([a, ccc]) => { ([a, ccc]) => a && ccc && setLoadMoreCommentsHidden((ccc || []).length === a.stat?.comments)
if (a && ccc && ccc[a.id]) {
setCommented(ccc[a.id])
setLoadMoreCommentsHidden(ccc[a.id]?.length === a.stat?.comments)
}
},
{}
) )
) )

View File

@ -1,5 +1,6 @@
import { RouteSectionProps, createAsync } from '@solidjs/router' import { RouteSectionProps, createAsync } from '@solidjs/router'
import { ErrorBoundary, Suspense, createEffect, createSignal, on } from 'solid-js' import { ErrorBoundary, Suspense, createEffect, createSignal, on } from 'solid-js'
import { COMMENTS_PER_PAGE } from '~/components/Article/FullArticle'
import { AuthorView } from '~/components/Views/Author' import { AuthorView } from '~/components/Views/Author'
import { FourOuFourView } from '~/components/Views/FourOuFour' import { FourOuFourView } from '~/components/Views/FourOuFour'
import { Loading } from '~/components/_shared/Loading' import { Loading } from '~/components/_shared/Loading'
@ -8,11 +9,13 @@ import { useAuthors } from '~/context/authors'
import { SHOUTS_PER_PAGE } from '~/context/feed' import { SHOUTS_PER_PAGE } from '~/context/feed'
import { useLocalize } from '~/context/localize' import { useLocalize } from '~/context/localize'
import { ReactionsProvider } from '~/context/reactions' import { ReactionsProvider } from '~/context/reactions'
import { loadAuthors, loadShouts, loadTopics } from '~/graphql/api/public' import { loadAuthors, loadReactions, loadShouts, loadTopics } from '~/graphql/api/public'
import { import {
Author, Author,
LoadShoutsOptions, LoadShoutsOptions,
QueryLoad_Authors_ByArgs, QueryLoad_Authors_ByArgs,
QueryLoad_Reactions_ByArgs,
Reaction,
Shout, Shout,
Topic Topic
} from '~/graphql/schema/core.gen' } from '~/graphql/schema/core.gen'
@ -24,6 +27,16 @@ const fetchAuthorShouts = async (slug: string, offset?: number) => {
return await shoutsLoader() 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 fetchAllTopics = async () => {
const topicsFetcher = loadTopics() const topicsFetcher = loadTopics()
return await topicsFetcher() 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<AuthorPageProps>) { export default function AuthorPage(props: RouteSectionProps<AuthorPageProps>) {
const { t } = useLocalize() const { t } = useLocalize()
@ -109,6 +127,11 @@ export default function AuthorPage(props: RouteSectionProps<AuthorPageProps>) {
async () => (props.data.articles as Shout[]) || (await fetchAuthorShouts(props.params.slug, 0)) 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 ( return (
<ErrorBoundary fallback={(_err) => <FourOuFourView />}> <ErrorBoundary fallback={(_err) => <FourOuFourView />}>
<Suspense fallback={<Loading />}> <Suspense fallback={<Loading />}>
@ -124,6 +147,7 @@ export default function AuthorPage(props: RouteSectionProps<AuthorPageProps>) {
author={author() as Author} author={author() as Author}
authorSlug={props.params.slug} authorSlug={props.params.slug}
shouts={authorShouts() || []} shouts={authorShouts() || []}
comments={authorComments() || []}
/> />
</ReactionsProvider> </ReactionsProvider>
</PageLayout> </PageLayout>