diff --git a/src/components/Views/Feed/Feed.tsx b/src/components/Views/Feed/Feed.tsx index f9cf16ef..00f64d31 100644 --- a/src/components/Views/Feed/Feed.tsx +++ b/src/components/Views/Feed/Feed.tsx @@ -1,6 +1,6 @@ import { A, createAsync, useLocation, useNavigate, useSearchParams } from '@solidjs/router' import { clsx } from 'clsx' -import { For, Show, createEffect, createMemo, createSignal, on } from 'solid-js' +import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js' import { DropDown } from '~/components/_shared/DropDown' import { Option } from '~/components/_shared/DropDown/DropDown' import { Icon } from '~/components/_shared/Icon' @@ -8,6 +8,7 @@ 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' @@ -32,8 +33,9 @@ import styles from './Feed.module.scss' export const FEED_PAGE_SIZE = 20 export type PeriodType = 'week' | 'month' | 'year' + export type FeedProps = { - shouts: Shout[] + shouts?: Shout[] } export const FeedView = (props: FeedProps) => { @@ -51,6 +53,7 @@ export const FeedView = (props: FeedProps) => { const [isLoading, setIsLoading] = createSignal(false) const [isRightColumnLoaded, setIsRightColumnLoaded] = createSignal(false) const { session } = useSession() + const { nonfeaturedFeed, setNonFeaturedFeed } = useFeed() const { loadReactionsBy } = useReactions() const { topTopics } = useTopics() const { topAuthors } = useAuthors() @@ -64,16 +67,25 @@ export const FeedView = (props: FeedProps) => { setTopComments(comments.sort(byCreated).reverse()) } + onMount( + () => + props.shouts && + Array.isArray(props.shouts) && + setNonFeaturedFeed((prev) => [...prev, ...(props.shouts || [])]) && console.info(nonfeaturedFeed()) + ) + createEffect( on( - () => props.shouts, - (sss: Shout[]) => { - if (sss) { + () => nonfeaturedFeed(), + (sss?: Shout[]) => { + if (sss && Array.isArray(sss)) { setIsLoading(true) + setNonFeaturedFeed((prev) => [...prev, ...sss]) Promise.all([ loadTopComments(), loadReactionsBy({ by: { shouts: sss.map((s: Shout) => s.slug) } }) ]).finally(() => { + console.debug('[views.feed] finally loaded reactions, data loading finished') setIsRightColumnLoaded(true) setIsLoading(false) }) @@ -101,7 +113,7 @@ export const FeedView = (props: FeedProps) => { - +
  • {
}> - 0}> - + 0}> + {(article) => ( handleShare(shared)} @@ -187,7 +199,7 @@ export const FeedView = (props: FeedProps) => { - + {(article) => ( )} diff --git a/src/components/_shared/LoadMoreWrapper.tsx b/src/components/_shared/LoadMoreWrapper.tsx index 811b8a9c..43403fba 100644 --- a/src/components/_shared/LoadMoreWrapper.tsx +++ b/src/components/_shared/LoadMoreWrapper.tsx @@ -24,9 +24,10 @@ export const LoadMoreWrapper = (props: LoadMoreProps) => { saveScrollPosition() const newItems = await props.loadFunction(offset()) if (!Array.isArray(newItems)) return + console.debug('[_share] load more items', newItems) setItems((prev) => [...prev, ...newItems]) setOffset((prev) => prev + props.pageSize) - setIsLoadMoreButtonVisible(newItems.length >= props.pageSize) + setIsLoadMoreButtonVisible(newItems.length >= props.pageSize - 1) setIsLoading(false) restoreScrollPosition() } diff --git a/src/context/feed.tsx b/src/context/feed.tsx index e1fd3867..cb055318 100644 --- a/src/context/feed.tsx +++ b/src/context/feed.tsx @@ -18,8 +18,6 @@ export const PRERENDERED_ARTICLES_COUNT = 5 type FeedContextType = { sortedFeed: Accessor articleEntities: Accessor<{ [articleSlug: string]: Shout }> - topFeed: Accessor - topMonthFeed: Accessor feedByAuthor: Accessor<{ [authorSlug: string]: Shout[] }> feedByTopic: Accessor<{ [topicSlug: string]: Shout[] }> feedByLayout: Accessor<{ [layout: string]: Shout[] }> @@ -33,12 +31,26 @@ type FeedContextType = { options: QueryLoad_Shouts_SearchArgs ) => Promise<{ hasMore: boolean; newShouts: Shout[] }> resetSortedFeed: () => void - loadTopMonthFeed: () => Promise - loadTopFeed: () => Promise seen: Accessor<{ [slug: string]: number }> addSeen: (slug: string) => void + + // featured + nonfeaturedFeed: Accessor + setNonFeaturedFeed: Setter + + // featured featuredFeed: Accessor setFeaturedFeed: Setter + + // top month + loadTopMonthFeed: () => Promise + topMonthFeed: Accessor + + // top rated + loadTopFeed: () => Promise + topFeed: Accessor + + // expo expoFeed: Accessor setExpoFeed: Setter } @@ -50,6 +62,7 @@ export const useFeed = () => useContext(FeedContext) export const FeedProvider = (props: { children: JSX.Element }) => { const [sortedFeed, setSortedFeed] = createSignal([]) const [articleEntities, setArticleEntities] = createSignal<{ [articleSlug: string]: Shout }>({}) + const [nonfeaturedFeed, setNonFeaturedFeed] = createSignal([]) const [featuredFeed, setFeaturedFeed] = createSignal([]) const [expoFeed, setExpoFeed] = createSignal([]) const [topFeed, setTopFeed] = createSignal([]) @@ -246,7 +259,9 @@ export const FeedProvider = (props: { children: JSX.Element }) => { featuredFeed, setFeaturedFeed, expoFeed, - setExpoFeed + setExpoFeed, + nonfeaturedFeed, + setNonFeaturedFeed }} > {props.children} diff --git a/src/routes/(main).tsx b/src/routes/(main).tsx index b7e5dc18..d511d792 100644 --- a/src/routes/(main).tsx +++ b/src/routes/(main).tsx @@ -52,11 +52,10 @@ const fetchHomeTopData = async () => { order_by: 'likes_stat', limit: 10 }) - return { - topRatedShouts: await topRatedLoader(), - topMonthShouts: await topMonthLoader(), - topCommentedShouts: await topCommentedLoader() - } as Partial + const topRatedShouts = await topRatedLoader() + const topMonthShouts = await topMonthLoader() + const topCommentedShouts = await topCommentedLoader() + return { topCommentedShouts, topMonthShouts, topRatedShouts } as Partial } export const route = { @@ -91,6 +90,7 @@ export default function HomePage(props: RouteSectionProps) { const offset = prev?.featuredShouts?.length || 0 const featuredShoutsLoader = featuredLoader(offset) const loaded = await featuredShoutsLoader() + setFeaturedFeed((prev) => [...prev, ...loaded||[]]) const featuredShouts = [ ...(prev?.featuredShouts || []), ...(loaded || props.data?.featuredShouts || []) diff --git a/src/routes/feed/(feed).tsx b/src/routes/feed/(feed).tsx index 267abc95..3bf31a3a 100644 --- a/src/routes/feed/(feed).tsx +++ b/src/routes/feed/(feed).tsx @@ -5,6 +5,7 @@ import { AUTHORS_PER_PAGE } from '~/components/Views/AllAuthors/AllAuthors' import { Feed } from '~/components/Views/Feed' import { LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper' import { PageLayout } from '~/components/_shared/PageLayout' +import { useFeed } from '~/context/feed' import { useLocalize } from '~/context/localize' import { ReactionsProvider } from '~/context/reactions' import { loadShouts } from '~/graphql/api/public' @@ -59,8 +60,8 @@ export const route = { export default (props: RouteSectionProps) => { const [searchParams] = useSearchParams() const { t } = useLocalize() + const {setNonFeaturedFeed} = useFeed() const [offset, setOffset] = createSignal(0) - const shouts = createAsync(async () => ({ ...props.data }) || (await loadMore())) const loadMore = async () => { const newOffset = offset() + SHOUTS_PER_PAGE setOffset(newOffset) @@ -74,8 +75,12 @@ export default (props: RouteSectionProps) => { const period = searchParams?.by || 'month' options.filters = { after: getFromDate(period as FeedPeriod) } } - return await fetchPublishedShouts(newOffset) + const result = await fetchPublishedShouts(newOffset) + result && setNonFeaturedFeed(result) + return } + const shouts = createAsync(async () => props.data || await loadMore()) + return (