add missing loading states

This commit is contained in:
Tom (plebeius.eth)
2025-02-20 15:51:29 +01:00
parent 06988e354a
commit 869610c8a0
41 changed files with 236 additions and 64 deletions
+6
View File
@@ -5,6 +5,12 @@
position: relative;
}
.checkingSubscriptions {
font-size: var(--topbar-font-size);
color: var(--topbar-desktop-link-text-color);
text-transform: lowercase;
}
.boardNavDesktop a, .navTopRight span {
color: var(--topbar-desktop-link-text-color);
text-decoration: var(--topbar-desktop-link-text-decoration);
+4
View File
@@ -8,6 +8,7 @@ import styles from './topbar.module.css';
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import _, { debounce } from 'lodash';
import { TimeFilter } from '../board-buttons';
import { useAutoSubscribe } from '../../hooks/use-auto-subscribe';
const SearchBar = ({ setShowSearchBar }: { setShowSearchBar: (show: boolean) => void }) => {
const navigate = useNavigate();
@@ -197,12 +198,15 @@ const TopBarMobile = ({ subplebbitAddress }: { subplebbitAddress: string }) => {
};
const TopBar = () => {
const { t } = useTranslation();
const params = useParams();
const { isCheckingSubscriptions } = useAutoSubscribe();
const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any });
const subplebbitAddress = params?.subplebbitAddress || accountComment?.subplebbitAddress;
return (
<>
{isCheckingSubscriptions && <div className={styles.checkingSubscriptions}>{t('loading_subscriptions')}</div>}
<TopBarDesktop />
<TopBarMobile subplebbitAddress={subplebbitAddress} />
</>
+81 -7
View File
@@ -15,23 +15,42 @@ export interface MultisubSubplebbit {
plebchanAutoSubscribe?: boolean;
}
export interface DefaultSubplebbitsState {
subplebbits: MultisubSubplebbit[];
loading: boolean;
error: Error | null;
}
let cacheSubplebbits: MultisubSubplebbit[] | null = null;
let cacheMetadata: MultisubMetadata | null = null;
let cacheAutoSubscribeAddresses: string[] | null = null;
export const useDefaultSubplebbits = () => {
const [subplebbits, setSubplebbits] = useState<MultisubSubplebbit[]>([]);
const [state, setState] = useState<DefaultSubplebbitsState>({
subplebbits: [],
loading: true,
error: null,
});
useEffect(() => {
if (cacheSubplebbits) {
setState({
subplebbits: cacheSubplebbits,
loading: false,
error: null,
});
return;
}
(async () => {
try {
const multisub = await fetch(
'https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json',
// { cache: 'no-cache' }
).then((res) => res.json());
const multisub = await fetch('https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json').then((res) => {
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
return res.json();
});
cacheSubplebbits = multisub.subplebbits;
// Cache auto-subscribe addresses when we fetch subplebbits
@@ -39,14 +58,69 @@ export const useDefaultSubplebbits = () => {
.filter((sub: MultisubSubplebbit) => sub.plebchanAutoSubscribe && sub.address)
.map((sub: MultisubSubplebbit) => sub.address);
setSubplebbits(multisub.subplebbits);
setState({
subplebbits: multisub.subplebbits,
loading: false,
error: null,
});
} catch (e) {
console.warn(e);
setState((prev) => ({
...prev,
loading: false,
error: e instanceof Error ? e : new Error('Failed to fetch subplebbits'),
}));
}
})();
}, []);
return cacheSubplebbits || subplebbits;
// To maintain backward compatibility, return the subplebbits array directly
return cacheSubplebbits || state.subplebbits;
};
export const useDefaultSubplebbitsState = () => {
const [state, setState] = useState<DefaultSubplebbitsState>({
subplebbits: cacheSubplebbits || [],
loading: !cacheSubplebbits,
error: null,
});
useEffect(() => {
if (cacheSubplebbits) {
setState({
subplebbits: cacheSubplebbits,
loading: false,
error: null,
});
return;
}
(async () => {
try {
const multisub = await fetch('https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json').then((res) => {
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
return res.json();
});
setState({
subplebbits: multisub.subplebbits,
loading: false,
error: null,
});
} catch (e) {
console.warn(e);
setState((prev) => ({
...prev,
loading: false,
error: e instanceof Error ? e : new Error('Failed to fetch subplebbits'),
}));
}
})();
}, []);
return state;
};
export const useDefaultSubplebbitAddresses = () => {
+12 -22
View File
@@ -7,7 +7,6 @@ import styles from './board.module.css';
import { shouldShowSnow } from '../../lib/snow';
import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
import { useAutoSubscribe } from '../../hooks/use-auto-subscribe';
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import useFeedStateString from '../../hooks/use-feed-state-string';
import useReplyModal from '../../hooks/use-reply-modal';
@@ -32,7 +31,6 @@ const threadsWithoutImagesFilter = (comment: Comment) => {
};
const Board = () => {
const { isCheckingSubscriptions } = useAutoSubscribe();
const { t } = useTranslation();
const location = useLocation();
const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>();
@@ -298,26 +296,18 @@ const Board = () => {
/>
)}
{rules && !description && rules.length > 0 && <SubplebbitRules subplebbitAddress={subplebbitAddress} createdAt={createdAt} rules={rules} />}
{isCheckingSubscriptions ? (
<div className={styles.feed}>
<div className={styles.footer}>
<LoadingEllipsis string={t('loading_feed')} />
</div>
</div>
) : (
<Virtuoso
increaseViewportBy={{ bottom: 1200, top: 1200 }}
totalCount={combinedFeed.length}
data={combinedFeed}
itemContent={(index, post) => <Post index={index} post={post} openReplyModal={openReplyModal} />}
useWindowScroll={true}
components={{ Footer }}
endReached={loadMore}
ref={virtuosoRef}
restoreStateFrom={lastVirtuosoState}
initialScrollTop={lastVirtuosoState?.scrollTop}
/>
)}
<Virtuoso
increaseViewportBy={{ bottom: 1200, top: 1200 }}
totalCount={combinedFeed.length}
data={combinedFeed}
itemContent={(index, post) => <Post index={index} post={post} openReplyModal={openReplyModal} />}
useWindowScroll={true}
components={{ Footer }}
endReached={loadMore}
ref={virtuosoRef}
restoreStateFrom={lastVirtuosoState}
initialScrollTop={lastVirtuosoState?.scrollTop}
/>
</div>
</>
);
@@ -4,10 +4,12 @@ import { useTranslation } from 'react-i18next';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import { Subplebbit, useSubplebbit, useSubplebbitStats } from '@plebbit/plebbit-react-hooks';
import { useDefaultSubplebbitTags } from '../../../hooks/use-default-subplebbits-tags';
import { useDefaultSubplebbitsState } from '../../../hooks/use-default-subplebbits';
import useIsMobile from '../../../hooks/use-is-mobile';
import useIsSubplebbitOffline from '../../../hooks/use-is-subplebbit-offline';
import styles from '../home.module.css';
import { nsfwTags } from '../home';
import LoadingEllipsis from '../../../components/loading-ellipsis';
const Board = ({ subplebbit, isMobile }: { subplebbit: Subplebbit; isMobile: boolean }) => {
const { t } = useTranslation();
@@ -60,6 +62,7 @@ const BoardsList = ({ multisub }: { multisub: Subplebbit[] }) => {
const location = useLocation();
const [displayCount, setDisplayCount] = useState(15);
const isMobile = useIsMobile();
const { loading, error } = useDefaultSubplebbitsState();
const currentTag = location.pathname.split('/').filter(Boolean)[0];
const tags = useDefaultSubplebbitTags(multisub);
@@ -68,6 +71,24 @@ const BoardsList = ({ multisub }: { multisub: Subplebbit[] }) => {
setDisplayCount(15);
}, [currentTag]);
if (loading) {
return (
<div className={styles.boardsBox}>
<span className={styles.loading}>
<LoadingEllipsis string={t('loading_default_boards')} />
</span>
</div>
);
}
if (error) {
return (
<div className={styles.boardsBox}>
<div className='red'>{error.message}</div>
</div>
);
}
const filteredBoards = (currentTag && tags.includes(currentTag) ? multisub.filter((sub) => sub?.tags?.includes(currentTag)) : multisub).slice(0, displayCount);
const totalBoardCount = currentTag && tags.includes(currentTag) ? multisub.filter((sub) => sub?.tags?.includes(currentTag)).length : multisub.length;
+7
View File
@@ -34,6 +34,13 @@
min-height: 150px;
}
.loading {
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px;
}
.offlineIcon {
display: inline-block;
vertical-align: text-top;