fix(board status): resolve offline indicators with strict community refs

This commit is contained in:
Tommaso Casaburi
2026-04-17 12:51:14 +07:00
parent 1c2be5a172
commit 4cae9c3caa
7 changed files with 86 additions and 64 deletions
@@ -49,8 +49,14 @@ let latestValue: ReturnType<typeof useIsCommunityOffline>;
let container: HTMLDivElement;
let root: Root;
const HookHarness = ({ community }: { community?: { address?: string; state?: string; updatedAt?: number; updatingState?: string } }) => {
latestValue = useIsCommunityOffline(community as never);
const HookHarness = ({
community,
communityAddressHint,
}: {
community?: { address?: string; name?: string; publicKey?: string; state?: string; updatedAt?: number; updatingState?: string };
communityAddressHint?: string;
}) => {
latestValue = useIsCommunityOffline(community as never, communityAddressHint);
return null;
};
@@ -62,9 +68,12 @@ const flushEffects = async (count = 3) => {
}
};
const renderHook = async (community?: { address?: string; state?: string; updatedAt?: number; updatingState?: string }) => {
const renderHook = async (
community?: { address?: string; name?: string; publicKey?: string; state?: string; updatedAt?: number; updatingState?: string },
communityAddressHint?: string,
) => {
await act(async () => {
root.render(createElement(HookHarness, { community }));
root.render(createElement(HookHarness, { community, communityAddressHint }));
});
await flushEffects();
};
@@ -153,6 +162,24 @@ describe('useIsCommunityOffline', () => {
});
});
it('tracks strict-community objects with a canonical address hint instead of the undefined key', async () => {
await renderHook({ name: 'music.eth', publicKey: '12D3KooWBoardKey', state: 'updating', updatingState: 'fetching' }, 'music.eth');
expect(testState.requestedAddresses).toEqual(['music.eth']);
expect(testState.initializeMock).toHaveBeenCalledWith('music.eth');
expect(testState.setOfflineStateMock).toHaveBeenCalledWith('music.eth', {
state: 'updating',
updatedAt: undefined,
updatingState: 'fetching',
});
expect(latestValue).toEqual({
isOffline: false,
isOnlineStatusLoading: true,
offlineIconClass: 'yellowOfflineIcon',
offlineTitle: 'downloading board...',
});
});
it('treats recently updated boards as online', async () => {
const freshUpdatedAt = 1_704_067_205;
testState.communityOfflineState = {
+18 -10
View File
@@ -5,25 +5,33 @@ import { getFormattedTimeAgo } from '../lib/utils/time-utils';
import useCommunityOfflineStore from '../stores/use-community-offline-store';
import useCommunitiesLoadingStartTimestamps from '../stores/use-communities-loading-start-timestamps-store';
const useIsCommunityOffline = (community?: Community | undefined) => {
const getCommunityOfflineKey = (community?: Community, communityAddressHint?: string) =>
communityAddressHint || community?.address || community?.name || community?.publicKey;
const useIsCommunityOffline = (community?: Community | undefined, communityAddressHint?: string) => {
const { t } = useTranslation();
const { address, state, updatedAt, updatingState } = community || {};
const { state, updatedAt, updatingState } = community || {};
const communityKey = getCommunityOfflineKey(community, communityAddressHint);
const { communityOfflineState, setCommunityOfflineState, initializeCommunityOfflineState } = useCommunityOfflineStore();
const communitiesLoadingStartTimestamps = useCommunitiesLoadingStartTimestamps([address]);
const communitiesLoadingStartTimestamps = useCommunitiesLoadingStartTimestamps(communityKey ? [communityKey] : undefined);
useEffect(() => {
if (address && !communityOfflineState[address]) {
initializeCommunityOfflineState(address);
if (communityKey && !communityOfflineState[communityKey]) {
initializeCommunityOfflineState(communityKey);
}
}, [address, communityOfflineState, initializeCommunityOfflineState]);
}, [communityKey, communityOfflineState, initializeCommunityOfflineState]);
useEffect(() => {
if (address) {
setCommunityOfflineState(address, { state, updatedAt, updatingState });
if (communityKey) {
setCommunityOfflineState(communityKey, { state, updatedAt, updatingState });
}
}, [address, state, updatedAt, updatingState, setCommunityOfflineState]);
}, [communityKey, state, updatedAt, updatingState, setCommunityOfflineState]);
const offlineState = communityOfflineState[address] || { initialLoad: true };
if (!communityKey) {
return { isOffline: false, isOnlineStatusLoading: false, offlineIconClass: '', offlineTitle: false };
}
const offlineState = communityOfflineState[communityKey] || { initialLoad: true };
const loadingStartTimestamp = communitiesLoadingStartTimestamps[0] || 0;
const isLoading = offlineState.initialLoad && (!updatedAt || Date.now() / 1000 - updatedAt >= 120 * 120) && Date.now() / 1000 - loadingStartTimestamp < 30;
const isOffline = !isLoading && ((updatedAt && updatedAt < Date.now() / 1000 - 120 * 120) || (!updatedAt && Date.now() / 1000 - loadingStartTimestamp >= 30));