mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
Merge branch 'codex/fix/board-empty-loading-state'
This commit is contained in:
@@ -34,7 +34,8 @@ const testState = vi.hoisted(() => ({
|
|||||||
} as Record<string, { address: string; features?: Record<string, unknown> }>,
|
} as Record<string, { address: string; features?: Record<string, unknown> }>,
|
||||||
feed: [] as TestComment[],
|
feed: [] as TestComment[],
|
||||||
feedOptionsCalls: [] as Array<{ communitiesLength?: number; newerThan?: number; postsPerPage?: number; sortType?: string }>,
|
feedOptionsCalls: [] as Array<{ communitiesLength?: number; newerThan?: number; postsPerPage?: number; sortType?: string }>,
|
||||||
feedStateString: 'syncing',
|
feedState: undefined as string | undefined,
|
||||||
|
feedStateString: 'syncing' as string | undefined,
|
||||||
filteredDirectoryAddresses: ['music-posting.eth'] as string[],
|
filteredDirectoryAddresses: ['music-posting.eth'] as string[],
|
||||||
hasMore: false,
|
hasMore: false,
|
||||||
respectPostsPerPageForNewerThan: new Set<number>(),
|
respectPostsPerPageForNewerThan: new Set<number>(),
|
||||||
@@ -136,6 +137,7 @@ vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
|
|||||||
return {
|
return {
|
||||||
feed: getScopedFeed(options),
|
feed: getScopedFeed(options),
|
||||||
hasMore: testState.hasMore,
|
hasMore: testState.hasMore,
|
||||||
|
state: testState.feedState ?? (testState.hasMore ? 'fetching-ipns' : 'succeeded'),
|
||||||
expandTimeWindow: testState.expandTimeWindowMock,
|
expandTimeWindow: testState.expandTimeWindowMock,
|
||||||
loadMore: testState.loadMoreMock,
|
loadMore: testState.loadMoreMock,
|
||||||
reset: testState.resetMock,
|
reset: testState.resetMock,
|
||||||
@@ -326,6 +328,7 @@ describe('Board', () => {
|
|||||||
};
|
};
|
||||||
testState.feed = [];
|
testState.feed = [];
|
||||||
testState.feedOptionsCalls = [];
|
testState.feedOptionsCalls = [];
|
||||||
|
testState.feedState = undefined;
|
||||||
testState.feedStateString = 'syncing';
|
testState.feedStateString = 'syncing';
|
||||||
testState.filteredDirectoryAddresses = ['music-posting.eth'];
|
testState.filteredDirectoryAddresses = ['music-posting.eth'];
|
||||||
testState.hasMore = false;
|
testState.hasMore = false;
|
||||||
@@ -642,4 +645,50 @@ describe('Board', () => {
|
|||||||
expect(container.querySelector('[data-testid="error-display"]')?.textContent).toBe('board failed');
|
expect(container.querySelector('[data-testid="error-display"]')?.textContent).toBe('board failed');
|
||||||
expect(container.textContent).toContain('failed');
|
expect(container.textContent).toContain('failed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not show no threads while a board is still loading', async () => {
|
||||||
|
testState.feedStateString = undefined;
|
||||||
|
testState.community = {
|
||||||
|
error: undefined,
|
||||||
|
shortAddress: 'music-posting.eth',
|
||||||
|
state: 'fetching-community-ipfs',
|
||||||
|
title: '/mu/ - Music',
|
||||||
|
};
|
||||||
|
|
||||||
|
await renderBoard({ initialEntry: '/mu', routePath: '/:boardIdentifier/*' });
|
||||||
|
|
||||||
|
expect(container.textContent).not.toContain('no_threads');
|
||||||
|
expect(container.querySelector('[data-testid="loading-ellipsis"]')?.textContent).toBe('loading_feed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not show no threads while an empty board feed is still loading', async () => {
|
||||||
|
testState.feedStateString = undefined;
|
||||||
|
testState.hasMore = true;
|
||||||
|
testState.community = {
|
||||||
|
error: undefined,
|
||||||
|
shortAddress: 'music-posting.eth',
|
||||||
|
state: 'succeeded',
|
||||||
|
title: '/mu/ - Music',
|
||||||
|
};
|
||||||
|
|
||||||
|
await renderBoard({ initialEntry: '/mu', routePath: '/:boardIdentifier/*' });
|
||||||
|
|
||||||
|
expect(container.textContent).not.toContain('no_threads');
|
||||||
|
expect(container.querySelector('[data-testid="loading-ellipsis"]')?.textContent).toBe('loading_feed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows no threads after an empty board feed finishes loading', async () => {
|
||||||
|
testState.feedStateString = undefined;
|
||||||
|
testState.community = {
|
||||||
|
error: undefined,
|
||||||
|
shortAddress: 'music-posting.eth',
|
||||||
|
state: 'succeeded',
|
||||||
|
title: '/mu/ - Music',
|
||||||
|
};
|
||||||
|
|
||||||
|
await renderBoard({ initialEntry: '/mu', routePath: '/:boardIdentifier/*' });
|
||||||
|
|
||||||
|
expect(container.textContent).toContain('no_threads');
|
||||||
|
expect(container.querySelector('[data-testid="loading-ellipsis"]')).toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ const BOARD_SORT_TYPE = 'active' as const;
|
|||||||
interface BoardFooterProps {
|
interface BoardFooterProps {
|
||||||
communityAddresses: string[];
|
communityAddresses: string[];
|
||||||
hasMore: boolean;
|
hasMore: boolean;
|
||||||
|
feedState: string | undefined;
|
||||||
combinedFeedLength: number;
|
combinedFeedLength: number;
|
||||||
|
isSingleCommunityBoard: boolean;
|
||||||
isInSubscriptionsView: boolean;
|
isInSubscriptionsView: boolean;
|
||||||
isInModView: boolean;
|
isInModView: boolean;
|
||||||
currentTimeFilterName: string;
|
currentTimeFilterName: string;
|
||||||
@@ -69,7 +71,9 @@ interface BoardFooterProps {
|
|||||||
const BoardFooter = ({
|
const BoardFooter = ({
|
||||||
communityAddresses,
|
communityAddresses,
|
||||||
hasMore,
|
hasMore,
|
||||||
|
feedState,
|
||||||
combinedFeedLength,
|
combinedFeedLength,
|
||||||
|
isSingleCommunityBoard,
|
||||||
isInSubscriptionsView,
|
isInSubscriptionsView,
|
||||||
isInModView,
|
isInModView,
|
||||||
currentTimeFilterName,
|
currentTimeFilterName,
|
||||||
@@ -85,6 +89,9 @@ const BoardFooter = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const loadingStateString = useFeedStateString(communityAddresses) || (combinedFeedLength === 0 ? t('loading_feed') : t('looking_for_more_posts'));
|
const loadingStateString = useFeedStateString(communityAddresses) || (combinedFeedLength === 0 ? t('loading_feed') : t('looking_for_more_posts'));
|
||||||
|
const isLoadedCommunityState = communityState === 'succeeded' || communityState === 'ready';
|
||||||
|
const canShowNoThreads = !isSingleCommunityBoard || (isLoadedCommunityState && feedState === 'succeeded');
|
||||||
|
const isEmptyBoardLoading = isSingleCommunityBoard && combinedFeedLength === 0 && !canShowNoThreads && communityState !== 'failed';
|
||||||
|
|
||||||
let footerContent;
|
let footerContent;
|
||||||
if (moreThreadsSuggestion && moreThreadsSuggestionPathname) {
|
if (moreThreadsSuggestion && moreThreadsSuggestionPathname) {
|
||||||
@@ -112,7 +119,7 @@ const BoardFooter = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (combinedFeedLength === 0) {
|
} else if (combinedFeedLength === 0 && canShowNoThreads) {
|
||||||
footerContent = t('no_threads');
|
footerContent = t('no_threads');
|
||||||
}
|
}
|
||||||
if (communityAddresses && communityAddresses.length === 0) {
|
if (communityAddresses && communityAddresses.length === 0) {
|
||||||
@@ -129,7 +136,7 @@ const BoardFooter = ({
|
|||||||
) : isInModView && accountCommunityAddressesLength === 0 ? (
|
) : isInModView && accountCommunityAddressesLength === 0 ? (
|
||||||
<span className='red'>{t('not_mod_of_any_board')}</span>
|
<span className='red'>{t('not_mod_of_any_board')}</span>
|
||||||
) : (
|
) : (
|
||||||
showLoadingEllipsis && hasMore && <LoadingEllipsis string={loadingStateString} />
|
showLoadingEllipsis && (hasMore || isEmptyBoardLoading) && <LoadingEllipsis string={loadingStateString} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -213,7 +220,7 @@ const Board = ({ feedCacheKey, viewType, boardIdentifier: boardIdentifierProp, t
|
|||||||
[communities, effectiveInfiniteScroll, infiniteFeedPostsPerPage, paginationFeedPostsPerPage, excludeArchivedFilter, multiboardTimeFilterSeconds],
|
[communities, effectiveInfiniteScroll, infiniteFeedPostsPerPage, paginationFeedPostsPerPage, excludeArchivedFilter, multiboardTimeFilterSeconds],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { feed, hasMore, loadMore, reset, expandTimeWindow } = useFeed(feedOptions);
|
const { feed, hasMore, loadMore, reset, expandTimeWindow, state: feedState } = useFeed(feedOptions);
|
||||||
const { currentTimeFilterName, currentTimeFilterSeconds, expandSuggestionTimeWindow } = useExpandedTimeFilter({
|
const { currentTimeFilterName, currentTimeFilterSeconds, expandSuggestionTimeWindow } = useExpandedTimeFilter({
|
||||||
timeFilterName,
|
timeFilterName,
|
||||||
timeFilterSeconds: multiboardTimeFilterSeconds,
|
timeFilterSeconds: multiboardTimeFilterSeconds,
|
||||||
@@ -422,7 +429,9 @@ const Board = ({ feedCacheKey, viewType, boardIdentifier: boardIdentifierProp, t
|
|||||||
<BoardFooter
|
<BoardFooter
|
||||||
communityAddresses={communityAddresses}
|
communityAddresses={communityAddresses}
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
|
feedState={feedState}
|
||||||
combinedFeedLength={combinedFeed.length}
|
combinedFeedLength={combinedFeed.length}
|
||||||
|
isSingleCommunityBoard={!isInAllView && !isInSubscriptionsView && !isInModView}
|
||||||
isInSubscriptionsView={isInSubscriptionsView}
|
isInSubscriptionsView={isInSubscriptionsView}
|
||||||
isInModView={isInModView}
|
isInModView={isInModView}
|
||||||
currentTimeFilterName={currentTimeFilterName}
|
currentTimeFilterName={currentTimeFilterName}
|
||||||
@@ -509,6 +518,7 @@ const Board = ({ feedCacheKey, viewType, boardIdentifier: boardIdentifierProp, t
|
|||||||
moreThreadsSuggestionPathname,
|
moreThreadsSuggestionPathname,
|
||||||
expandSuggestionTimeWindow,
|
expandSuggestionTimeWindow,
|
||||||
communityState,
|
communityState,
|
||||||
|
feedState,
|
||||||
communityAddress,
|
communityAddress,
|
||||||
subscriptions?.length,
|
subscriptions?.length,
|
||||||
accountCommunityAddresses?.length,
|
accountCommunityAddresses?.length,
|
||||||
|
|||||||
Reference in New Issue
Block a user