topic+author-loadmore-fix
This commit is contained in:
parent
22f44ee0ec
commit
f808bd2394
|
@ -1,6 +1,6 @@
|
|||
import { A, useLocation, useParams } from '@solidjs/router'
|
||||
import { clsx } from 'clsx'
|
||||
import { For, Match, Show, Switch, createEffect, createMemo, createSignal, on } from 'solid-js'
|
||||
import { For, Match, Show, Switch, createEffect, createMemo, createSignal } from 'solid-js'
|
||||
import { Loading } from '~/components/_shared/Loading'
|
||||
import { coreApiUrl } from '~/config'
|
||||
import { useAuthors } from '~/context/authors'
|
||||
|
@ -12,7 +12,6 @@ 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 { byCreated } from '~/lib/sort'
|
||||
import { paginate } from '~/utils/paginate'
|
||||
import stylesArticle from '../../Article/Article.module.scss'
|
||||
import { Comment } from '../../Article/Comment'
|
||||
import { AuthorCard } from '../../Author/AuthorCard'
|
||||
|
@ -25,20 +24,19 @@ import styles from './Author.module.scss'
|
|||
|
||||
type AuthorViewProps = {
|
||||
authorSlug: string
|
||||
selectedTab: string
|
||||
shouts?: Shout[]
|
||||
shouts: Shout[]
|
||||
author?: Author
|
||||
}
|
||||
|
||||
export const PRERENDERED_ARTICLES_COUNT = 12
|
||||
const LOAD_MORE_PAGE_SIZE = 9
|
||||
// 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<string>(props.selectedTab)
|
||||
const [currentTab, setCurrentTab] = createSignal<string>(params.tab)
|
||||
|
||||
const { session } = useSession()
|
||||
const client = createMemo(() => graphqlClientCreate(coreApiUrl, session()?.access_token))
|
||||
|
@ -56,21 +54,11 @@ export const AuthorView = (props: AuthorViewProps) => {
|
|||
|
||||
// derivatives
|
||||
const me = createMemo<Author>(() => session()?.user?.app_data?.profile as Author)
|
||||
const pages = createMemo<Shout[][]>(() =>
|
||||
paginate((props.shouts || []).slice(1), PRERENDERED_ARTICLES_COUNT, LOAD_MORE_PAGE_SIZE)
|
||||
)
|
||||
|
||||
// Переход по табам
|
||||
createEffect(
|
||||
on(
|
||||
() => params.tab,
|
||||
(tab: string) => {
|
||||
// Обновляем текущую вкладку
|
||||
setCurrentTab(tab || '')
|
||||
},
|
||||
{}
|
||||
)
|
||||
)
|
||||
createEffect(() => {
|
||||
setCurrentTab(params.tab)
|
||||
})
|
||||
|
||||
// Объединенный эффект для загрузки автора и его подписок
|
||||
createEffect(async () => {
|
||||
|
@ -171,7 +159,6 @@ export const AuthorView = (props: AuthorViewProps) => {
|
|||
</div>
|
||||
|
||||
<Switch>
|
||||
|
||||
<Match when={currentTab() === 'about'}>
|
||||
<div class="wide-container">
|
||||
<div class="row">
|
||||
|
@ -198,7 +185,6 @@ export const AuthorView = (props: AuthorViewProps) => {
|
|||
</Match>
|
||||
|
||||
<Match when={currentTab() === 'comments'}>
|
||||
|
||||
<Show when={me()?.slug === props.authorSlug && !me().stat?.comments}>
|
||||
<div class="wide-container">
|
||||
<Placeholder type={loc?.pathname} mode="profile" />
|
||||
|
@ -232,36 +218,29 @@ export const AuthorView = (props: AuthorViewProps) => {
|
|||
</div>
|
||||
</Show>
|
||||
|
||||
<Show when={Array.isArray(props.shouts) && props.shouts.length > 0 && props.shouts[0]}>
|
||||
<Row1 article={props.shouts?.[0] as Shout} noauthor={true} nodate={true} />
|
||||
|
||||
<Show when={props.shouts && props.shouts.length > 1}>
|
||||
<Switch>
|
||||
<Match when={props.shouts && props.shouts.length === 2}>
|
||||
<Row2 articles={props.shouts as Shout[]} isEqual={true} noauthor={true} nodate={true} />
|
||||
</Match>
|
||||
<Match when={props.shouts && props.shouts.length === 3}>
|
||||
<Row3 articles={props.shouts as Shout[]} noauthor={true} nodate={true} />
|
||||
</Match>
|
||||
<Match when={props.shouts && props.shouts.length > 3}>
|
||||
<For each={pages()}>
|
||||
{(page) => (
|
||||
<>
|
||||
<Row1 article={page[0]} noauthor={true} nodate={true} />
|
||||
<Row2 articles={page.slice(1, 3)} isEqual={true} noauthor={true} />
|
||||
<Row1 article={page[3]} noauthor={true} nodate={true} />
|
||||
<Row2 articles={page.slice(4, 6)} isEqual={true} noauthor={true} />
|
||||
<Row1 article={page[6]} noauthor={true} nodate={true} />
|
||||
<Row2 articles={page.slice(7, 9)} isEqual={true} noauthor={true} />
|
||||
</>
|
||||
)}
|
||||
</For>
|
||||
</Match>
|
||||
</Switch>
|
||||
</Show>
|
||||
<Show when={Array.isArray(props.shouts) && props.shouts.length > 0}>
|
||||
<For each={props.shouts.filter((_, i) => i % 3 === 0)}>
|
||||
{(_shout, index) => {
|
||||
const articles = props.shouts.slice(index() * 3, index() * 3 + 3);
|
||||
return (
|
||||
<>
|
||||
<Switch>
|
||||
<Match when={articles.length === 1}>
|
||||
<Row1 article={articles[0]} noauthor={true} nodate={true} />
|
||||
</Match>
|
||||
<Match when={articles.length === 2}>
|
||||
<Row2 articles={articles} noauthor={true} nodate={true} isEqual={true} />
|
||||
</Match>
|
||||
<Match when={articles.length === 3}>
|
||||
<Row3 articles={articles} noauthor={true} nodate={true} />
|
||||
</Match>
|
||||
</Switch>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</For>
|
||||
</Show>
|
||||
</Match>
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useSearchParams } from '@solidjs/router'
|
||||
import { clsx } from 'clsx'
|
||||
import { For, Show, Suspense, createEffect, createMemo, createSignal, on } from 'solid-js'
|
||||
import { For, Match, Show, Suspense, Switch, createEffect, createSignal, on } from 'solid-js'
|
||||
import { useAuthors } from '~/context/authors'
|
||||
import { useFeed } from '~/context/feed'
|
||||
import { useLocalize } from '~/context/localize'
|
||||
|
@ -9,7 +9,6 @@ import { loadAuthors, loadFollowersByTopic, loadShouts } from '~/graphql/api/pub
|
|||
import { Author, AuthorsBy, LoadShoutsOptions, Shout, Topic } from '~/graphql/schema/core.gen'
|
||||
import { SHOUTS_PER_PAGE } from '~/routes/(main)'
|
||||
import { getUnixtime } from '~/utils/date'
|
||||
import { paginate } from '~/utils/paginate'
|
||||
import { restoreScrollPosition, saveScrollPosition } from '~/utils/scroll'
|
||||
import styles from '../../styles/Topic.module.scss'
|
||||
import { Beside } from '../Feed/Beside'
|
||||
|
@ -21,7 +20,6 @@ import { LoadMoreItems, LoadMoreWrapper } from '../_shared/LoadMoreWrapper'
|
|||
import { Loading } from '../_shared/Loading'
|
||||
import { ArticleCardSwiper } from '../_shared/SolidSwiper/ArticleCardSwiper'
|
||||
|
||||
// FIXME: should be 'last_comment' and 'comments_stat' or just one?
|
||||
export type TopicFeedSortBy = 'comments' | '' | 'recent' | 'viewed' | 'rating' | 'last_comment'
|
||||
|
||||
interface Props {
|
||||
|
@ -33,7 +31,7 @@ interface Props {
|
|||
}
|
||||
|
||||
export const PRERENDERED_ARTICLES_COUNT = 28
|
||||
const LOAD_MORE_PAGE_SIZE = 9 // Row3 + Row3 + Row3
|
||||
// const LOAD_MORE_PAGE_SIZE = 9 // Row3 + Row3 + Row3
|
||||
|
||||
export const TopicView = (props: Props) => {
|
||||
const { t } = useLocalize()
|
||||
|
@ -49,13 +47,13 @@ export const TopicView = (props: Props) => {
|
|||
// TODO: filter + sort
|
||||
const [sortedFeed, setSortedFeed] = createSignal([] as Shout[])
|
||||
createEffect(on(([feedByTopic, () => props.topicSlug, topicEntities]), ([feed, slug, ttt]) => {
|
||||
if (Object.values(ttt).length === 0) return
|
||||
const sss = (feed[slug] || []) as Shout[]
|
||||
sss && setSortedFeed(sss)
|
||||
console.debug('topic slug loaded', slug)
|
||||
const tpc = ttt[slug]
|
||||
console.debug('topics loaded', ttt)
|
||||
tpc && setTopic(tpc)
|
||||
if (Object.values(ttt).length === 0) return
|
||||
const sss = (feed[slug] || []) as Shout[]
|
||||
sss && setSortedFeed(sss)
|
||||
console.debug('topic slug loaded', slug)
|
||||
const tpc = ttt[slug]
|
||||
console.debug('topics loaded', ttt)
|
||||
tpc && setTopic(tpc)
|
||||
}, {}))
|
||||
|
||||
const loadTopicFollowers = async () => {
|
||||
|
@ -104,12 +102,12 @@ export const TopicView = (props: Props) => {
|
|||
|
||||
// второй этап начальной загрузки данных
|
||||
createEffect(on(topic, (tpc) => {
|
||||
console.debug('topic loaded', tpc)
|
||||
if (!tpc) return
|
||||
loadFavoriteTopArticles()
|
||||
loadReactedTopMonthArticles()
|
||||
loadTopicAuthors()
|
||||
loadTopicFollowers()
|
||||
console.debug('topic loaded', tpc)
|
||||
if (!tpc) return
|
||||
loadFavoriteTopArticles()
|
||||
loadReactedTopMonthArticles()
|
||||
loadTopicAuthors()
|
||||
loadTopicFollowers()
|
||||
}, { defer: true }))
|
||||
|
||||
// дозагрузка
|
||||
|
@ -137,9 +135,6 @@ export const TopicView = (props: Props) => {
|
|||
})
|
||||
*/
|
||||
|
||||
const pages = createMemo<Shout[][]>(() =>
|
||||
paginate(sortedFeed(), PRERENDERED_ARTICLES_COUNT, LOAD_MORE_PAGE_SIZE)
|
||||
)
|
||||
return (
|
||||
<div class={styles.topicPage}>
|
||||
<Suspense fallback={<Loading />}>
|
||||
|
@ -223,15 +218,26 @@ export const TopicView = (props: Props) => {
|
|||
</Show>
|
||||
|
||||
<LoadMoreWrapper loadFunction={loadMore} pageSize={SHOUTS_PER_PAGE}>
|
||||
<For each={pages()}>
|
||||
{(page) => (
|
||||
<For each={sortedFeed().slice(19).filter((_, i) => i % 3 === 0)}>
|
||||
{(_shout, index) => {
|
||||
const articles = sortedFeed().slice(19).slice(index() * 3, index() * 3 + 3);
|
||||
return (
|
||||
<>
|
||||
<Row3 articles={page.slice(0, 3)} />
|
||||
<Row3 articles={page.slice(3, 6)} />
|
||||
<Row3 articles={page.slice(6, 9)} />
|
||||
<Switch>
|
||||
<Match when={articles.length === 1}>
|
||||
<Row1 article={articles[0]} noauthor={true} nodate={true} />
|
||||
</Match>
|
||||
<Match when={articles.length === 2}>
|
||||
<Row2 articles={articles} noauthor={true} nodate={true} isEqual={true} />
|
||||
</Match>
|
||||
<Match when={articles.length === 3}>
|
||||
<Row3 articles={articles} noauthor={true} nodate={true} />
|
||||
</Match>
|
||||
</Switch>
|
||||
</>
|
||||
)}
|
||||
</For>
|
||||
);
|
||||
}}
|
||||
</For>
|
||||
</LoadMoreWrapper>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
|
|
@ -138,9 +138,8 @@ export default function AuthorPage(props: RouteSectionProps<AuthorPageProps>) {
|
|||
>
|
||||
<AuthorView
|
||||
author={author() as Author}
|
||||
selectedTab={props.params.tab}
|
||||
authorSlug={props.params.slug}
|
||||
shouts={authorShouts()}
|
||||
shouts={authorShouts() || []}
|
||||
/>
|
||||
</LoadMoreWrapper>
|
||||
</ReactionsProvider>
|
||||
|
|
|
@ -62,34 +62,38 @@ export default function TopicPage(props: RouteSectionProps<TopicPageProps>) {
|
|||
const [desc, setDesc] = createSignal<string>('')
|
||||
const [cover, setCover] = createSignal<string>('')
|
||||
const [viewed, setViewed] = createSignal(false)
|
||||
createEffect(on([topics, () => window], ([ttt, win]) => {
|
||||
if (ttt && win) {
|
||||
// console.debug('all topics:', ttt)
|
||||
ttt && addTopics(ttt)
|
||||
const tpc = ttt.find((x) => x.slug === props.params.slug)
|
||||
if (!tpc) return
|
||||
setTopic(tpc)
|
||||
setTitle(() => `${t('Discours')}${topic()?.title ? ` :: ${topic()?.title}` : ''}`)
|
||||
setDesc(() =>
|
||||
topic()?.body
|
||||
? descFromBody(topic()?.body || '')
|
||||
: t('The most interesting publications on the topic', { topicName: title() })
|
||||
)
|
||||
setCover(() =>
|
||||
topic()?.pic ? getImageUrl(topic()?.pic || '', { width: 1200 }) : '/logo.png'
|
||||
)
|
||||
createEffect(
|
||||
on(
|
||||
[topics, () => window],
|
||||
([ttt, win]) => {
|
||||
if (ttt && win) {
|
||||
// console.debug('all topics:', ttt)
|
||||
ttt && addTopics(ttt)
|
||||
const tpc = ttt.find((x) => x.slug === props.params.slug)
|
||||
if (!tpc) return
|
||||
setTopic(tpc)
|
||||
setTitle(() => `${t('Discours')}${topic()?.title ? ` :: ${topic()?.title}` : ''}`)
|
||||
setDesc(() =>
|
||||
topic()?.body
|
||||
? descFromBody(topic()?.body || '')
|
||||
: t('The most interesting publications on the topic', { topicName: title() })
|
||||
)
|
||||
setCover(() => (topic()?.pic ? getImageUrl(topic()?.pic || '', { width: 1200 }) : '/logo.png'))
|
||||
|
||||
// views google counter increment
|
||||
if (viewed()) {
|
||||
window?.gtag?.('event', 'page_view', {
|
||||
page_title: tpc.title,
|
||||
page_location: window?.location.href,
|
||||
page_path: window?.location.pathname
|
||||
})
|
||||
setViewed(true)
|
||||
}
|
||||
}
|
||||
}, {}))
|
||||
// views google counter increment
|
||||
if (!viewed()) {
|
||||
window?.gtag?.('event', 'page_view', {
|
||||
page_title: tpc.title,
|
||||
page_location: window?.location.href,
|
||||
page_path: window?.location.pathname
|
||||
})
|
||||
setViewed(true)
|
||||
}
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
)
|
||||
|
||||
return (
|
||||
<Show
|
||||
|
|
Loading…
Reference in New Issue
Block a user