loadmore-main-fix

This commit is contained in:
Untone 2024-07-18 13:22:58 +03:00
parent 7573c6334c
commit 1eb9c57f0d
7 changed files with 45 additions and 56 deletions

View File

@ -117,7 +117,12 @@ export const AuthorView = (props: AuthorViewProps) => {
// on load // on load
createEffect(on(() => bioContainerRef, checkBioHeight)) 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 ( return (
<div class={styles.authorPage}> <div class={styles.authorPage}>

View File

@ -40,9 +40,9 @@ export type FeedProps = {
} }
const PERIODS = { const PERIODS = {
'day': 24 * 60 * 60, day: 24 * 60 * 60,
'month': 30 * 24 * 60 * 60, month: 30 * 24 * 60 * 60,
'year': 365 * 24 * 60 * 60 year: 365 * 24 * 60 * 60
} }
export const FeedView = (props: FeedProps) => { export const FeedView = (props: FeedProps) => {

View File

@ -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 { Button } from '~/components/_shared/Button'
import { useLocalize } from '~/context/localize' import { useLocalize } from '~/context/localize'
import { Author, Reaction, Shout } from '~/graphql/schema/core.gen' 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' import { restoreScrollPosition, saveScrollPosition } from '~/utils/scroll'
export type LoadMoreItems = Shout[] | Author[] | Reaction[] export type LoadMoreItems = Shout[] | Author[] | Reaction[]
type LoadMoreProps = { type LoadMoreProps = {
loadFunction: (offset?: number) => Promise<LoadMoreItems> loadFunction: (offset: number) => Promise<LoadMoreItems>
pageSize: number pageSize: number
hidden?: boolean hidden?: boolean
children: JSX.Element children: JSX.Element
@ -17,18 +19,30 @@ export const LoadMoreWrapper = (props: LoadMoreProps) => {
const { t } = useLocalize() const { t } = useLocalize()
const [items, setItems] = createSignal<LoadMoreItems>([]) const [items, setItems] = createSignal<LoadMoreItems>([])
const [offset, setOffset] = createSignal(0) const [offset, setOffset] = createSignal(0)
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(true) const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const [isLoading, setIsLoading] = 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 () => { const loadItems = async () => {
setIsLoading(true) setIsLoading(true)
saveScrollPosition() saveScrollPosition()
const newItems = await props.loadFunction(offset()) const newItems = await props.loadFunction(offset())
if (!Array.isArray(newItems)) return if (!Array.isArray(newItems)) return
console.debug('[_share] load more items', newItems) console.debug('[_share] load more items', newItems)
setItems((prev) => [...prev, ...newItems] as LoadMoreItems) setItems(
setOffset((prev) => prev + props.pageSize) (prev) =>
setIsLoadMoreButtonVisible(newItems.length >= props.pageSize - 1) Array.from(new Set([...prev, ...newItems])).sort(
byCreated as SortFunction<unknown>
) as LoadMoreItems
)
setIsLoading(false) setIsLoading(false)
restoreScrollPosition() restoreScrollPosition()
} }

View File

@ -5,8 +5,8 @@ export const byFirstChar = (a: Author | Topic, b: Author | Topic) =>
(b as Author).name || (b as Topic).title || '' (b as Author).name || (b as Topic).title || ''
) )
export const byCreated = (a: Shout | Reaction, b: Shout | Reaction) => { export const byCreated = (a: { created_at?: number }, b: { created_at?: number }) => {
return a?.created_at - b?.created_at return (a?.created_at || 0) - (b?.created_at || 0)
} }
export const byPublished = (a: Shout, b: Shout) => { export const byPublished = (a: Shout, b: Shout) => {

View File

@ -7,15 +7,12 @@ import { PageLayout } from '~/components/_shared/PageLayout'
import { useAuthors } from '~/context/authors' import { useAuthors } from '~/context/authors'
import { useFeed } from '~/context/feed' import { useFeed } from '~/context/feed'
import { useLocalize } from '~/context/localize' import { useLocalize } from '~/context/localize'
import { ReactionsProvider, useReactions } from '~/context/reactions' import { ReactionsProvider } from '~/context/reactions'
import { loadAuthors, loadReactions, loadShouts, loadTopics } from '~/graphql/api/public' import { loadAuthors, loadShouts, loadTopics } from '~/graphql/api/public'
import { import {
Author, Author,
LoadShoutsOptions, LoadShoutsOptions,
QueryLoad_Authors_ByArgs, QueryLoad_Authors_ByArgs,
QueryLoad_Reactions_ByArgs,
Reaction,
ReactionKind,
Shout, Shout,
Topic Topic
} from '~/graphql/schema/core.gen' } from '~/graphql/schema/core.gen'
@ -28,16 +25,6 @@ const fetchAuthorShouts = async (slug: string, offset?: number) => {
return await shoutsLoader() 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 fetchAllTopics = async () => {
const topicsFetcher = loadTopics() const topicsFetcher = loadTopics()
return await topicsFetcher() return await topicsFetcher()
@ -86,13 +73,6 @@ export default function AuthorPage(props: RouteSectionProps<AuthorPageProps>) {
: getImageUrl('production/image/logo_image.png') : 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 // author shouts
const { addFeed, feedByAuthor } = useFeed() const { addFeed, feedByAuthor } = useFeed()
const shoutsByAuthor = createMemo(() => feedByAuthor()[props.params.slug]) const shoutsByAuthor = createMemo(() => feedByAuthor()[props.params.slug])
@ -113,15 +93,8 @@ export default function AuthorPage(props: RouteSectionProps<AuthorPageProps>) {
) )
) )
const loadAuthorDataMore = async (offset = 0) => { const loadAuthorShoutsMore = async (offset: number) => {
if (props.params.tab === 'comments') { const loadedShouts = await fetchAuthorShouts(props.params.slug, offset)
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)
loadedShouts && addFeed(loadedShouts) loadedShouts && addFeed(loadedShouts)
return (loadedShouts || []) as LoadMoreItems return (loadedShouts || []) as LoadMoreItems
} }
@ -136,11 +109,7 @@ export default function AuthorPage(props: RouteSectionProps<AuthorPageProps>) {
cover={cover()} cover={cover()}
> >
<ReactionsProvider> <ReactionsProvider>
<LoadMoreWrapper <LoadMoreWrapper loadFunction={loadAuthorShoutsMore} pageSize={SHOUTS_PER_PAGE}>
loadFunction={loadAuthorDataMore}
pageSize={SHOUTS_PER_PAGE}
hidden={!props.params.tab || props.params.tab !== 'comments'}
>
<AuthorView <AuthorView
author={author() as Author} author={author() as Author}
selectedTab={props.params.tab} selectedTab={props.params.tab}

View File

@ -23,7 +23,8 @@ export default () => {
if (result) { if (result) {
console.debug(result) console.debug(result)
const { shout, error } = result.data.create_shout const { shout, error } = result.data.create_shout
if (error) showSnackbar({ if (error)
showSnackbar({
body: `${t('Error')}: ${t(error)}`, body: `${t('Error')}: ${t(error)}`,
type: 'error' type: 'error'
}) })