diff --git a/app.config.ts b/app.config.ts index 6ef50f1f..860366d2 100644 --- a/app.config.ts +++ b/app.config.ts @@ -8,7 +8,7 @@ import sassDts from 'vite-plugin-sass-dts' const isVercel = Boolean(process?.env.VERCEL) const isBun = Boolean(process.env.BUN) -console.info(`[app.config] build for ${isVercel ? 'vercel' : isBun? 'bun' : 'node'}!`) +console.info(`[app.config] build for ${isVercel ? 'vercel' : isBun ? 'bun' : 'node'}!`) const polyfillOptions = { include: ['path', 'stream', 'util'], diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index 221370fc..6cef65a1 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -117,7 +117,12 @@ export const AuthorView = (props: AuthorViewProps) => { // on load createEffect(on(() => bioContainerRef, checkBioHeight)) - createEffect(on(() => props.selectedTab, (tab) => tab && console.log('[views.Author] profile tab switched'))) + createEffect( + on( + () => props.selectedTab, + (tab) => tab && console.log('[views.Author] profile tab switched') + ) + ) return (
diff --git a/src/components/Views/Feed/Feed.tsx b/src/components/Views/Feed/Feed.tsx index ae1b39dd..45146e3d 100644 --- a/src/components/Views/Feed/Feed.tsx +++ b/src/components/Views/Feed/Feed.tsx @@ -40,9 +40,9 @@ export type FeedProps = { } const PERIODS = { - 'day': 24 * 60 * 60, - 'month': 30 * 24 * 60 * 60, - 'year': 365 * 24 * 60 * 60 + day: 24 * 60 * 60, + month: 30 * 24 * 60 * 60, + year: 365 * 24 * 60 * 60 } export const FeedView = (props: FeedProps) => { @@ -98,7 +98,7 @@ export const FeedView = (props: FeedProps) => { } const asOption = (o: string) => { - const value = Math.floor(Date.now()/1000) - PERIODS[o as keyof typeof PERIODS] + const value = Math.floor(Date.now() / 1000) - PERIODS[o as keyof typeof PERIODS] return { value, title: t(o) } } const asOptions = (opts: string[]) => opts.map(asOption) diff --git a/src/components/_shared/LoadMoreWrapper.tsx b/src/components/_shared/LoadMoreWrapper.tsx index fd22b1e5..9bb7887d 100644 --- a/src/components/_shared/LoadMoreWrapper.tsx +++ b/src/components/_shared/LoadMoreWrapper.tsx @@ -1,13 +1,15 @@ -import { JSX, Show, createSignal, onMount } from 'solid-js' +import { JSX, Show, createEffect, createSignal, on, onMount } from 'solid-js' import { Button } from '~/components/_shared/Button' import { useLocalize } from '~/context/localize' import { Author, Reaction, Shout } from '~/graphql/schema/core.gen' +import { byCreated } from '~/lib/sort' +import { SortFunction } from '~/types/common' import { restoreScrollPosition, saveScrollPosition } from '~/utils/scroll' export type LoadMoreItems = Shout[] | Author[] | Reaction[] type LoadMoreProps = { - loadFunction: (offset?: number) => Promise + loadFunction: (offset: number) => Promise pageSize: number hidden?: boolean children: JSX.Element @@ -17,18 +19,30 @@ export const LoadMoreWrapper = (props: LoadMoreProps) => { const { t } = useLocalize() const [items, setItems] = createSignal([]) const [offset, setOffset] = createSignal(0) - const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(true) + const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false) const [isLoading, setIsLoading] = createSignal(false) + createEffect( + on(items, (iii) => { + if (Array.isArray(iii)) { + setIsLoadMoreButtonVisible(iii.length - offset() >= 0) + setOffset(iii.length) + } + }) + ) + const loadItems = async () => { setIsLoading(true) saveScrollPosition() const newItems = await props.loadFunction(offset()) if (!Array.isArray(newItems)) return console.debug('[_share] load more items', newItems) - setItems((prev) => [...prev, ...newItems] as LoadMoreItems) - setOffset((prev) => prev + props.pageSize) - setIsLoadMoreButtonVisible(newItems.length >= props.pageSize - 1) + setItems( + (prev) => + Array.from(new Set([...prev, ...newItems])).sort( + byCreated as SortFunction + ) as LoadMoreItems + ) setIsLoading(false) restoreScrollPosition() } diff --git a/src/lib/sort.ts b/src/lib/sort.ts index d04bee34..8c34e79d 100644 --- a/src/lib/sort.ts +++ b/src/lib/sort.ts @@ -5,8 +5,8 @@ export const byFirstChar = (a: Author | Topic, b: Author | Topic) => (b as Author).name || (b as Topic).title || '' ) -export const byCreated = (a: Shout | Reaction, b: Shout | Reaction) => { - return a?.created_at - b?.created_at +export const byCreated = (a: { created_at?: number }, b: { created_at?: number }) => { + return (a?.created_at || 0) - (b?.created_at || 0) } export const byPublished = (a: Shout, b: Shout) => { diff --git a/src/routes/author/[slug]/[...tab].tsx b/src/routes/author/[slug]/[...tab].tsx index 11c0d5da..6f2d90c7 100644 --- a/src/routes/author/[slug]/[...tab].tsx +++ b/src/routes/author/[slug]/[...tab].tsx @@ -7,15 +7,12 @@ import { PageLayout } from '~/components/_shared/PageLayout' import { useAuthors } from '~/context/authors' import { useFeed } from '~/context/feed' import { useLocalize } from '~/context/localize' -import { ReactionsProvider, useReactions } from '~/context/reactions' -import { loadAuthors, loadReactions, loadShouts, loadTopics } from '~/graphql/api/public' +import { ReactionsProvider } from '~/context/reactions' +import { loadAuthors, loadShouts, loadTopics } from '~/graphql/api/public' import { Author, LoadShoutsOptions, QueryLoad_Authors_ByArgs, - QueryLoad_Reactions_ByArgs, - Reaction, - ReactionKind, Shout, Topic } from '~/graphql/schema/core.gen' @@ -28,16 +25,6 @@ const fetchAuthorShouts = async (slug: string, offset?: number) => { return await shoutsLoader() } -const fetchAuthorComments = async (slug: string, offset?: number) => { - const opts: QueryLoad_Reactions_ByArgs = { - by: { comment: true, author: slug }, - limit: SHOUTS_PER_PAGE, - offset - } - const shoutsLoader = loadReactions(opts) - return await shoutsLoader() -} - const fetchAllTopics = async () => { const topicsFetcher = loadTopics() return await topicsFetcher() @@ -86,13 +73,6 @@ export default function AuthorPage(props: RouteSectionProps) { : getImageUrl('production/image/logo_image.png') ) - // author comments - const { addReactions, reactionEntities } = useReactions() - const commentsByAuthor = createMemo(() => - Object.values(reactionEntities).filter( - (r: Reaction) => r.kind === ReactionKind.Comment && r.created_by.id === author()?.id - ) - ) // author shouts const { addFeed, feedByAuthor } = useFeed() const shoutsByAuthor = createMemo(() => feedByAuthor()[props.params.slug]) @@ -113,15 +93,8 @@ export default function AuthorPage(props: RouteSectionProps) { ) ) - const loadAuthorDataMore = async (offset = 0) => { - if (props.params.tab === 'comments') { - const commentsOffset = commentsByAuthor().length - const loadedComments = await fetchAuthorComments(props.params.slug, commentsOffset) - loadedComments && addReactions(loadedComments) - return (loadedComments || []) as LoadMoreItems - } - const shoutsOffset = shoutsByAuthor().length - const loadedShouts = await fetchAuthorShouts(props.params.slug, shoutsOffset) + const loadAuthorShoutsMore = async (offset: number) => { + const loadedShouts = await fetchAuthorShouts(props.params.slug, offset) loadedShouts && addFeed(loadedShouts) return (loadedShouts || []) as LoadMoreItems } @@ -136,11 +109,7 @@ export default function AuthorPage(props: RouteSectionProps) { cover={cover()} > -