loadmore+feed+my
This commit is contained in:
parent
4fe2768329
commit
8cce8d897e
|
@ -8,7 +8,6 @@ import { InviteMembers } from '~/components/_shared/InviteMembers'
|
||||||
import { Loading } from '~/components/_shared/Loading'
|
import { Loading } from '~/components/_shared/Loading'
|
||||||
import { ShareModal } from '~/components/_shared/ShareModal'
|
import { ShareModal } from '~/components/_shared/ShareModal'
|
||||||
import { useAuthors } from '~/context/authors'
|
import { useAuthors } from '~/context/authors'
|
||||||
import { useFeed } from '~/context/feed'
|
|
||||||
import { useGraphQL } from '~/context/graphql'
|
import { useGraphQL } from '~/context/graphql'
|
||||||
import { useLocalize } from '~/context/localize'
|
import { useLocalize } from '~/context/localize'
|
||||||
import { useReactions } from '~/context/reactions'
|
import { useReactions } from '~/context/reactions'
|
||||||
|
@ -35,8 +34,9 @@ export const FEED_PAGE_SIZE = 20
|
||||||
export type PeriodType = 'week' | 'month' | 'year'
|
export type PeriodType = 'week' | 'month' | 'year'
|
||||||
|
|
||||||
export type FeedProps = {
|
export type FeedProps = {
|
||||||
shouts?: Shout[]
|
shouts: Shout[]
|
||||||
mode?: '' | 'likes' | 'hot'
|
mode?: 'followed' | 'discussed' | 'coauthored' | 'unrated'
|
||||||
|
order?: '' | 'likes' | 'hot'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FeedView = (props: FeedProps) => {
|
export const FeedView = (props: FeedProps) => {
|
||||||
|
@ -54,7 +54,6 @@ export const FeedView = (props: FeedProps) => {
|
||||||
const [isLoading, setIsLoading] = createSignal(false)
|
const [isLoading, setIsLoading] = createSignal(false)
|
||||||
const [isRightColumnLoaded, setIsRightColumnLoaded] = createSignal(false)
|
const [isRightColumnLoaded, setIsRightColumnLoaded] = createSignal(false)
|
||||||
const { session } = useSession()
|
const { session } = useSession()
|
||||||
const { feed, setFeed } = useFeed()
|
|
||||||
const { loadReactionsBy } = useReactions()
|
const { loadReactionsBy } = useReactions()
|
||||||
const { topTopics } = useTopics()
|
const { topTopics } = useTopics()
|
||||||
const { topAuthors } = useAuthors()
|
const { topAuthors } = useAuthors()
|
||||||
|
@ -68,13 +67,13 @@ export const FeedView = (props: FeedProps) => {
|
||||||
setTopComments(comments.sort(byCreated).reverse())
|
setTopComments(comments.sort(byCreated).reverse())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// post-load
|
||||||
createEffect(
|
createEffect(
|
||||||
on(
|
on(
|
||||||
feed,
|
() => props.shouts,
|
||||||
(sss?: Shout[]) => {
|
(sss?: Shout[]) => {
|
||||||
if (sss && Array.isArray(sss)) {
|
if (sss && Array.isArray(sss)) {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
setFeed((prev) => [...prev, ...sss])
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
loadTopComments(),
|
loadTopComments(),
|
||||||
loadReactionsBy({ by: { shouts: sss.map((s: Shout) => s.slug) } })
|
loadReactionsBy({ by: { shouts: sss.map((s: Shout) => s.slug) } })
|
||||||
|
@ -107,15 +106,15 @@ export const FeedView = (props: FeedProps) => {
|
||||||
<Placeholder type={loc?.pathname} mode="feed" />
|
<Placeholder type={loc?.pathname} mode="feed" />
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
<Show when={(session() || loc?.pathname === 'feed') && feed()?.length}>
|
<Show when={(session() || loc?.pathname === 'feed') && props.shouts?.length}>
|
||||||
<div class={styles.filtersContainer}>
|
<div class={styles.filtersContainer}>
|
||||||
<ul class={clsx('view-switcher', styles.feedFilter)}>
|
<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>
|
<A href={loc.pathname}>{t('Recent')}</A>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
class={clsx({
|
class={clsx({
|
||||||
'view-switcher__item--selected': props.mode === 'likes'
|
'view-switcher__item--selected': props.order === 'likes'
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<A class="link" href={'/feed/likes'}>
|
<A class="link" href={'/feed/likes'}>
|
||||||
|
@ -124,7 +123,7 @@ export const FeedView = (props: FeedProps) => {
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
class={clsx({
|
class={clsx({
|
||||||
'view-switcher__item--selected': props.mode === 'hot'
|
'view-switcher__item--selected': props.order === 'hot'
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<A class="link" href={'/feed/hot'}>
|
<A class="link" href={'/feed/hot'}>
|
||||||
|
@ -153,8 +152,8 @@ export const FeedView = (props: FeedProps) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Show when={!isLoading()} fallback={<Loading />}>
|
<Show when={!isLoading()} fallback={<Loading />}>
|
||||||
<Show when={(feed() || []).length > 0}>
|
<Show when={(props.shouts || []).length > 0}>
|
||||||
<For each={(feed() || []).slice(0, 4)}>
|
<For each={(props.shouts || []).slice(0, 4)}>
|
||||||
{(article) => (
|
{(article) => (
|
||||||
<ArticleCard
|
<ArticleCard
|
||||||
onShare={(shared) => handleShare(shared)}
|
onShare={(shared) => handleShare(shared)}
|
||||||
|
@ -186,7 +185,7 @@ export const FeedView = (props: FeedProps) => {
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<For each={(feed() || []).slice(4)}>
|
<For each={(props.shouts || []).slice(4)}>
|
||||||
{(article) => (
|
{(article) => (
|
||||||
<ArticleCard article={article} settings={{ isFeedMode: true }} desktopCoverSize="M" />
|
<ArticleCard article={article} settings={{ isFeedMode: true }} desktopCoverSize="M" />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -113,7 +113,7 @@ export default function HomePage(props: RouteSectionProps<HomeViewProps>) {
|
||||||
<Show when={(featuredFeed() || []).length > 0} fallback={<Loading />}>
|
<Show when={(featuredFeed() || []).length > 0} fallback={<Loading />}>
|
||||||
<LoadMoreWrapper loadFunction={loadMoreFeatured} pageSize={SHOUTS_PER_PAGE}>
|
<LoadMoreWrapper loadFunction={loadMoreFeatured} pageSize={SHOUTS_PER_PAGE}>
|
||||||
<HomeView
|
<HomeView
|
||||||
featuredShouts={featuredFeed() || shouts() as Shout[]}
|
featuredShouts={featuredFeed() || (shouts() as Shout[])}
|
||||||
topMonthShouts={topMonthFeed() as Shout[]}
|
topMonthShouts={topMonthFeed() as Shout[]}
|
||||||
topViewedShouts={topViewedFeed() as Shout[]}
|
topViewedShouts={topViewedFeed() as Shout[]}
|
||||||
topRatedShouts={topRatedFeed() as Shout[]}
|
topRatedShouts={topRatedFeed() as Shout[]}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { RouteSectionProps, createAsync, useSearchParams } from '@solidjs/router'
|
import { RouteSectionProps, createAsync, useSearchParams } from '@solidjs/router'
|
||||||
import { Client } from '@urql/core'
|
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 { AUTHORS_PER_PAGE } from '~/components/Views/AllAuthors/AllAuthors'
|
||||||
import { Feed } from '~/components/Views/Feed'
|
import { Feed } from '~/components/Views/Feed'
|
||||||
|
import { FeedProps } from '~/components/Views/Feed/Feed'
|
||||||
import { LoadMoreItems, LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper'
|
import { LoadMoreItems, LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper'
|
||||||
import { PageLayout } from '~/components/_shared/PageLayout'
|
import { PageLayout } from '~/components/_shared/PageLayout'
|
||||||
import { useFeed } from '~/context/feed'
|
import { useFeed } from '~/context/feed'
|
||||||
|
@ -60,7 +61,7 @@ export const route = {
|
||||||
export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>) => {
|
export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>) => {
|
||||||
const [searchParams] = useSearchParams<FeedSearchParams>() // ?period=month
|
const [searchParams] = useSearchParams<FeedSearchParams>() // ?period=month
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const { setFeed } = useFeed()
|
const { feed, setFeed } = useFeed()
|
||||||
|
|
||||||
// preload all topics
|
// preload all topics
|
||||||
const { addTopics, sortedTopics } = useTopics()
|
const { addTopics, sortedTopics } = useTopics()
|
||||||
|
@ -106,6 +107,17 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
|
||||||
return (await loadMoreFeed()) as Shout[]
|
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 (
|
return (
|
||||||
<PageLayout
|
<PageLayout
|
||||||
withPadding={true}
|
withPadding={true}
|
||||||
|
@ -115,7 +127,7 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
|
||||||
>
|
>
|
||||||
<LoadMoreWrapper loadFunction={loadMoreFeed} pageSize={AUTHORS_PER_PAGE}>
|
<LoadMoreWrapper loadFunction={loadMoreFeed} pageSize={AUTHORS_PER_PAGE}>
|
||||||
<ReactionsProvider>
|
<ReactionsProvider>
|
||||||
<Feed />
|
<Feed shouts={feed() || (shouts() as Shout[])} order={order() as FeedProps['order']} />
|
||||||
</ReactionsProvider>
|
</ReactionsProvider>
|
||||||
</LoadMoreWrapper>
|
</LoadMoreWrapper>
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { RouteSectionProps, useSearchParams } from '@solidjs/router'
|
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 { AUTHORS_PER_PAGE } from '~/components/Views/AllAuthors/AllAuthors'
|
||||||
import { Feed } from '~/components/Views/Feed'
|
import { Feed } from '~/components/Views/Feed'
|
||||||
|
import { FeedProps } from '~/components/Views/Feed/Feed'
|
||||||
import { LoadMoreItems, LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper'
|
import { LoadMoreItems, LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper'
|
||||||
import { PageLayout } from '~/components/_shared/PageLayout'
|
import { PageLayout } from '~/components/_shared/PageLayout'
|
||||||
import { useFeed } from '~/context/feed'
|
import { useFeed } from '~/context/feed'
|
||||||
|
@ -52,7 +53,7 @@ const getFromDate = (period: FeedPeriod): number => {
|
||||||
export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>) => {
|
export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>) => {
|
||||||
const [searchParams] = useSearchParams<FeedSearchParams>() // ?period=month
|
const [searchParams] = useSearchParams<FeedSearchParams>() // ?period=month
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const { setFeed } = useFeed()
|
const { setFeed, feed } = useFeed()
|
||||||
// TODO: use const { requireAuthentication } = useSession()
|
// TODO: use const { requireAuthentication } = useSession()
|
||||||
const client = useGraphQL()
|
const client = useGraphQL()
|
||||||
|
|
||||||
|
@ -62,27 +63,32 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
|
||||||
!sortedTopics() && props.data.topics && addTopics(props.data.topics)
|
!sortedTopics() && props.data.topics && addTopics(props.data.topics)
|
||||||
})
|
})
|
||||||
|
|
||||||
// load more my feed
|
// /feed/my/:mode:
|
||||||
const loadMoreMyFeed = async (offset?: number) => {
|
const mode = createMemo(() => {
|
||||||
// /feed/my/:mode:
|
|
||||||
const paramModePattern = /^(followed|discussed|liked|coauthored|unrated)$/
|
const paramModePattern = /^(followed|discussed|liked|coauthored|unrated)$/
|
||||||
const mode =
|
return props.params.mode && paramModePattern.test(props.params.mode) ? props.params.mode : 'followed'
|
||||||
props.params.mode && paramModePattern.test(props.params.mode) ? props.params.mode : 'followed'
|
})
|
||||||
const gqlHandler = feeds[mode as keyof typeof feeds]
|
|
||||||
|
|
||||||
// /feed/my/:mode:/:order: - select order setting
|
const order = createMemo(() => {
|
||||||
const paramOrderPattern = /^(hot|likes)$/
|
const paramOrderPattern = /^(hot|likes)$/
|
||||||
const order =
|
return (
|
||||||
(paramOrderPattern.test(props.params.order)
|
(paramOrderPattern.test(props.params.order)
|
||||||
? props.params.order === 'hot'
|
? props.params.order === 'hot'
|
||||||
? 'last_comment'
|
? 'last_comment'
|
||||||
: props.params.order
|
: props.params.order
|
||||||
: 'created_at') || 'created_at'
|
: '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 = {
|
const options: LoadShoutsOptions = {
|
||||||
limit: 20,
|
limit: 20,
|
||||||
offset,
|
offset,
|
||||||
order_by: order
|
order_by: order()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ?period=month - time period filter
|
// ?period=month - time period filter
|
||||||
|
@ -106,7 +112,11 @@ export default (props: RouteSectionProps<{ shouts: Shout[]; topics: Topic[] }>)
|
||||||
>
|
>
|
||||||
<LoadMoreWrapper loadFunction={loadMoreMyFeed} pageSize={AUTHORS_PER_PAGE}>
|
<LoadMoreWrapper loadFunction={loadMoreMyFeed} pageSize={AUTHORS_PER_PAGE}>
|
||||||
<ReactionsProvider>
|
<ReactionsProvider>
|
||||||
<Feed />
|
<Feed
|
||||||
|
shouts={feed() || []}
|
||||||
|
mode={(mode() || 'followed') as FeedProps['mode']}
|
||||||
|
order={order() as FeedProps['order']}
|
||||||
|
/>
|
||||||
</ReactionsProvider>
|
</ReactionsProvider>
|
||||||
</LoadMoreWrapper>
|
</LoadMoreWrapper>
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user