loadmore+feed+my

This commit is contained in:
Untone 2024-07-15 23:56:40 +03:00
parent 4fe2768329
commit 8cce8d897e
4 changed files with 50 additions and 29 deletions

View File

@ -8,7 +8,6 @@ import { InviteMembers } from '~/components/_shared/InviteMembers'
import { Loading } from '~/components/_shared/Loading'
import { ShareModal } from '~/components/_shared/ShareModal'
import { useAuthors } from '~/context/authors'
import { useFeed } from '~/context/feed'
import { useGraphQL } from '~/context/graphql'
import { useLocalize } from '~/context/localize'
import { useReactions } from '~/context/reactions'
@ -35,8 +34,9 @@ export const FEED_PAGE_SIZE = 20
export type PeriodType = 'week' | 'month' | 'year'
export type FeedProps = {
shouts?: Shout[]
mode?: '' | 'likes' | 'hot'
shouts: Shout[]
mode?: 'followed' | 'discussed' | 'coauthored' | 'unrated'
order?: '' | 'likes' | 'hot'
}
export const FeedView = (props: FeedProps) => {
@ -54,7 +54,6 @@ export const FeedView = (props: FeedProps) => {
const [isLoading, setIsLoading] = createSignal(false)
const [isRightColumnLoaded, setIsRightColumnLoaded] = createSignal(false)
const { session } = useSession()
const { feed, setFeed } = useFeed()
const { loadReactionsBy } = useReactions()
const { topTopics } = useTopics()
const { topAuthors } = useAuthors()
@ -68,13 +67,13 @@ export const FeedView = (props: FeedProps) => {
setTopComments(comments.sort(byCreated).reverse())
}
// post-load
createEffect(
on(
feed,
() => props.shouts,
(sss?: Shout[]) => {
if (sss && Array.isArray(sss)) {
setIsLoading(true)
setFeed((prev) => [...prev, ...sss])
Promise.all([
loadTopComments(),
loadReactionsBy({ by: { shouts: sss.map((s: Shout) => s.slug) } })
@ -107,15 +106,15 @@ export const FeedView = (props: FeedProps) => {
<Placeholder type={loc?.pathname} mode="feed" />
</Show>
<Show when={(session() || loc?.pathname === 'feed') && feed()?.length}>
<Show when={(session() || loc?.pathname === 'feed') && props.shouts?.length}>
<div class={styles.filtersContainer}>
<ul class={clsx('view-switcher', styles.feedFilter)}>
<li class={clsx({ 'view-switcher__item--selected': !props.mode })}>
<li class={clsx({ 'view-switcher__item--selected': !props.order })}>
<A href={loc.pathname}>{t('Recent')}</A>
</li>
<li
class={clsx({
'view-switcher__item--selected': props.mode === 'likes'
'view-switcher__item--selected': props.order === 'likes'
})}
>
<A class="link" href={'/feed/likes'}>
@ -124,7 +123,7 @@ export const FeedView = (props: FeedProps) => {
</li>
<li
class={clsx({
'view-switcher__item--selected': props.mode === 'hot'
'view-switcher__item--selected': props.order === 'hot'
})}
>
<A class="link" href={'/feed/hot'}>
@ -153,8 +152,8 @@ export const FeedView = (props: FeedProps) => {
</div>
<Show when={!isLoading()} fallback={<Loading />}>
<Show when={(feed() || []).length > 0}>
<For each={(feed() || []).slice(0, 4)}>
<Show when={(props.shouts || []).length > 0}>
<For each={(props.shouts || []).slice(0, 4)}>
{(article) => (
<ArticleCard
onShare={(shared) => handleShare(shared)}
@ -186,7 +185,7 @@ export const FeedView = (props: FeedProps) => {
</ul>
</div>
<For each={(feed() || []).slice(4)}>
<For each={(props.shouts || []).slice(4)}>
{(article) => (
<ArticleCard article={article} settings={{ isFeedMode: true }} desktopCoverSize="M" />
)}

View File

@ -113,7 +113,7 @@ export default function HomePage(props: RouteSectionProps<HomeViewProps>) {
<Show when={(featuredFeed() || []).length > 0} fallback={<Loading />}>
<LoadMoreWrapper loadFunction={loadMoreFeatured} pageSize={SHOUTS_PER_PAGE}>
<HomeView
featuredShouts={featuredFeed() || shouts() as Shout[]}
featuredShouts={featuredFeed() || (shouts() as Shout[])}
topMonthShouts={topMonthFeed() as Shout[]}
topViewedShouts={topViewedFeed() as Shout[]}
topRatedShouts={topRatedFeed() as Shout[]}

View File

@ -1,8 +1,9 @@
import { RouteSectionProps, createAsync, useSearchParams } from '@solidjs/router'
import { Client } from '@urql/core'
import { createEffect } from 'solid-js'
import { createEffect, createMemo } from 'solid-js'
import { AUTHORS_PER_PAGE } from '~/components/Views/AllAuthors/AllAuthors'
import { Feed } from '~/components/Views/Feed'
import { FeedProps } from '~/components/Views/Feed/Feed'
import { LoadMoreItems, LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper'
import { PageLayout } from '~/components/_shared/PageLayout'
import { useFeed } from '~/context/feed'
@ -60,7 +61,7 @@ export const route = {
export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>) => {
const [searchParams] = useSearchParams<FeedSearchParams>() // ?period=month
const { t } = useLocalize()
const { setFeed } = useFeed()
const { feed, setFeed } = useFeed()
// preload all topics
const { addTopics, sortedTopics } = useTopics()
@ -106,6 +107,17 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
return (await loadMoreFeed()) as Shout[]
})
const order = createMemo(() => {
const paramOrderPattern = /^(hot|likes)$/
return (
(paramOrderPattern.test(props.params.order)
? props.params.order === 'hot'
? 'last_comment'
: props.params.order
: 'created_at') || 'created_at'
)
})
return (
<PageLayout
withPadding={true}
@ -115,7 +127,7 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
>
<LoadMoreWrapper loadFunction={loadMoreFeed} pageSize={AUTHORS_PER_PAGE}>
<ReactionsProvider>
<Feed />
<Feed shouts={feed() || (shouts() as Shout[])} order={order() as FeedProps['order']} />
</ReactionsProvider>
</LoadMoreWrapper>
</PageLayout>

View File

@ -1,7 +1,8 @@
import { RouteSectionProps, useSearchParams } from '@solidjs/router'
import { createEffect } from 'solid-js'
import { createEffect, createMemo } from 'solid-js'
import { AUTHORS_PER_PAGE } from '~/components/Views/AllAuthors/AllAuthors'
import { Feed } from '~/components/Views/Feed'
import { FeedProps } from '~/components/Views/Feed/Feed'
import { LoadMoreItems, LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper'
import { PageLayout } from '~/components/_shared/PageLayout'
import { useFeed } from '~/context/feed'
@ -52,7 +53,7 @@ const getFromDate = (period: FeedPeriod): number => {
export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>) => {
const [searchParams] = useSearchParams<FeedSearchParams>() // ?period=month
const { t } = useLocalize()
const { setFeed } = useFeed()
const { setFeed, feed } = useFeed()
// TODO: use const { requireAuthentication } = useSession()
const client = useGraphQL()
@ -62,27 +63,32 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
!sortedTopics() && props.data.topics && addTopics(props.data.topics)
})
// load more my feed
const loadMoreMyFeed = async (offset?: number) => {
// /feed/my/:mode:
// /feed/my/:mode:
const mode = createMemo(() => {
const paramModePattern = /^(followed|discussed|liked|coauthored|unrated)$/
const mode =
props.params.mode && paramModePattern.test(props.params.mode) ? props.params.mode : 'followed'
const gqlHandler = feeds[mode as keyof typeof feeds]
return props.params.mode && paramModePattern.test(props.params.mode) ? props.params.mode : 'followed'
})
// /feed/my/:mode:/:order: - select order setting
const order = createMemo(() => {
const paramOrderPattern = /^(hot|likes)$/
const order =
return (
(paramOrderPattern.test(props.params.order)
? props.params.order === 'hot'
? 'last_comment'
: props.params.order
: 'created_at') || 'created_at'
)
})
// load more my feed
const loadMoreMyFeed = async (offset?: number) => {
const gqlHandler = feeds[mode() as keyof typeof feeds]
// /feed/my/:mode:/:order: - select order setting
const options: LoadShoutsOptions = {
limit: 20,
offset,
order_by: order
order_by: order()
}
// ?period=month - time period filter
@ -106,7 +112,11 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
>
<LoadMoreWrapper loadFunction={loadMoreMyFeed} pageSize={AUTHORS_PER_PAGE}>
<ReactionsProvider>
<Feed />
<Feed
shouts={feed() || []}
mode={(mode() || 'followed') as FeedProps['mode']}
order={order() as FeedProps['order']}
/>
</ReactionsProvider>
</LoadMoreWrapper>
</PageLayout>