mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
refactor(core): remove legacy plebbit terminology
This commit is contained in:
@@ -2,8 +2,8 @@ import * as React from 'react';
|
||||
import { createElement } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { useAccountSubplebbitAddresses } from '../use-account-subplebbit-addresses';
|
||||
import { useAccountSubplebbitsWithMetadata } from '../use-account-subplebbits-with-metadata';
|
||||
import { useAccountCommunityAddresses } from '../use-account-community-addresses';
|
||||
import { useAccountCommunitiesWithMetadata } from '../use-account-communities-with-metadata';
|
||||
import useAuthorPrivileges from '../use-author-privileges';
|
||||
import { useBoardFeedPageSize } from '../use-board-feed-page-size';
|
||||
import { useBoardPseudonymityMode } from '../use-board-pseudonymity-mode';
|
||||
@@ -16,16 +16,16 @@ const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise
|
||||
|
||||
const testState = vi.hoisted(() => ({
|
||||
account: undefined as unknown,
|
||||
accountSubplebbits: {} as Record<string, unknown>,
|
||||
accountCommunities: {} as Record<string, unknown>,
|
||||
directories: [] as Array<{ address: string; nsfw?: boolean }>,
|
||||
directoryLookup: {} as Record<string, unknown>,
|
||||
flattenedReplies: [] as unknown[],
|
||||
subplebbitSnapshot: undefined as unknown,
|
||||
communitySnapshot: undefined as unknown,
|
||||
}));
|
||||
|
||||
vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
|
||||
useAccount: () => testState.account,
|
||||
useAccountCommunities: () => ({ accountCommunities: testState.accountSubplebbits }),
|
||||
useAccountCommunities: () => ({ accountCommunities: testState.accountCommunities }),
|
||||
}));
|
||||
|
||||
vi.mock('@bitsocialnet/bitsocial-react-hooks/dist/lib/utils', () => ({
|
||||
@@ -38,7 +38,7 @@ vi.mock('../use-directories', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('../use-stable-community', () => ({
|
||||
useCommunityField: (_address: string | undefined, selector: (community: unknown) => unknown) => selector(testState.subplebbitSnapshot),
|
||||
useCommunityField: (_address: string | undefined, selector: (community: unknown) => unknown) => selector(testState.communitySnapshot),
|
||||
}));
|
||||
|
||||
let latestValue: unknown;
|
||||
@@ -67,11 +67,11 @@ describe('selector hooks', () => {
|
||||
localStorage.clear();
|
||||
vi.clearAllMocks();
|
||||
testState.account = undefined;
|
||||
testState.accountSubplebbits = {};
|
||||
testState.accountCommunities = {};
|
||||
testState.directories = [];
|
||||
testState.directoryLookup = {};
|
||||
testState.flattenedReplies = [];
|
||||
testState.subplebbitSnapshot = undefined;
|
||||
testState.communitySnapshot = undefined;
|
||||
useAllFeedFilterStore.getState().setFilter('all');
|
||||
|
||||
container = document.createElement('div');
|
||||
@@ -84,14 +84,14 @@ describe('selector hooks', () => {
|
||||
container.remove();
|
||||
});
|
||||
|
||||
it('derives account board addresses and metadata from cached account subplebbits', () => {
|
||||
testState.accountSubplebbits = {
|
||||
it('derives account board addresses and metadata from cached account communities', () => {
|
||||
testState.accountCommunities = {
|
||||
'music.eth': { address: 'music.eth', title: '/mu/ - Music' },
|
||||
'tech.eth': { address: 'tech.eth', title: '/g/ - Technology' },
|
||||
};
|
||||
|
||||
expect(renderHookValue(() => useAccountSubplebbitAddresses())).toEqual(['music.eth', 'tech.eth']);
|
||||
expect(renderHookValue(() => useAccountSubplebbitsWithMetadata())).toEqual([
|
||||
expect(renderHookValue(() => useAccountCommunityAddresses())).toEqual(['music.eth', 'tech.eth']);
|
||||
expect(renderHookValue(() => useAccountCommunitiesWithMetadata())).toEqual([
|
||||
{ address: 'music.eth', title: '/mu/ - Music' },
|
||||
{ address: 'tech.eth', title: '/g/ - Technology' },
|
||||
]);
|
||||
@@ -99,14 +99,14 @@ describe('selector hooks', () => {
|
||||
|
||||
it('computes moderator privileges and whether the current account authored the comment', () => {
|
||||
testState.account = { author: { address: '0xme' } };
|
||||
testState.subplebbitSnapshot = {
|
||||
testState.communitySnapshot = {
|
||||
roles: {
|
||||
'0xauthor': { role: 'moderator' },
|
||||
'0xme': { role: 'admin' },
|
||||
},
|
||||
};
|
||||
|
||||
expect(renderHookValue(() => useAuthorPrivileges({ commentAuthorAddress: '0xauthor', subplebbitAddress: 'music.eth' }))).toEqual({
|
||||
expect(renderHookValue(() => useAuthorPrivileges({ commentAuthorAddress: '0xauthor', communityAddress: 'music.eth' }))).toEqual({
|
||||
isCommentAuthorMod: true,
|
||||
isAccountMod: true,
|
||||
isAccountCommentAuthor: false,
|
||||
@@ -114,7 +114,7 @@ describe('selector hooks', () => {
|
||||
accountAuthorRole: 'admin',
|
||||
});
|
||||
|
||||
expect(renderHookValue(() => useAuthorPrivileges({ commentAuthorAddress: '0xme', subplebbitAddress: 'music.eth' }))).toEqual({
|
||||
expect(renderHookValue(() => useAuthorPrivileges({ commentAuthorAddress: '0xme', communityAddress: 'music.eth' }))).toEqual({
|
||||
isCommentAuthorMod: true,
|
||||
isAccountMod: true,
|
||||
isAccountCommentAuthor: true,
|
||||
@@ -146,13 +146,13 @@ describe('selector hooks', () => {
|
||||
features: { pseudonymityMode: 'directory-mode' },
|
||||
},
|
||||
};
|
||||
testState.subplebbitSnapshot = {
|
||||
testState.communitySnapshot = {
|
||||
features: { pseudonymityMode: 'live-mode' },
|
||||
};
|
||||
|
||||
expect(renderHookValue(() => useBoardPseudonymityMode('music.eth'))).toBe('live-mode');
|
||||
|
||||
testState.subplebbitSnapshot = {
|
||||
testState.communitySnapshot = {
|
||||
features: {},
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ type TestComment = {
|
||||
content?: string;
|
||||
index?: number;
|
||||
number?: number;
|
||||
subplebbitAddress?: string;
|
||||
communityAddress?: string;
|
||||
};
|
||||
|
||||
const testState = vi.hoisted(() => ({
|
||||
@@ -79,12 +79,12 @@ describe('useFreshReplies', () => {
|
||||
content: 'stale reply',
|
||||
index: 3,
|
||||
number: undefined,
|
||||
subplebbitAddress: 'music.eth',
|
||||
communityAddress: 'music.eth',
|
||||
},
|
||||
{
|
||||
cid: 'network-reply-cid',
|
||||
content: 'network reply',
|
||||
subplebbitAddress: 'music.eth',
|
||||
communityAddress: 'music.eth',
|
||||
},
|
||||
];
|
||||
testState.accountComments = [
|
||||
@@ -93,7 +93,7 @@ describe('useFreshReplies', () => {
|
||||
content: 'fresh reply',
|
||||
index: 3,
|
||||
number: 27,
|
||||
subplebbitAddress: 'music.eth',
|
||||
communityAddress: 'music.eth',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -121,12 +121,12 @@ describe('useFreshReplies', () => {
|
||||
{
|
||||
content: 'stale failed reply',
|
||||
index: 0,
|
||||
subplebbitAddress: 'music.eth',
|
||||
communityAddress: 'music.eth',
|
||||
},
|
||||
{
|
||||
content: 'duplicate stale failed reply',
|
||||
index: 0,
|
||||
subplebbitAddress: 'music.eth',
|
||||
communityAddress: 'music.eth',
|
||||
},
|
||||
];
|
||||
testState.accountComments = [
|
||||
@@ -134,7 +134,7 @@ describe('useFreshReplies', () => {
|
||||
content: 'retried pending reply',
|
||||
index: 0,
|
||||
number: 99,
|
||||
subplebbitAddress: 'music.eth',
|
||||
communityAddress: 'music.eth',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
+14
-14
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { createElement } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import useIsSubplebbitOffline from '../use-is-subplebbit-offline';
|
||||
import useIsCommunityOffline from '../use-is-community-offline';
|
||||
|
||||
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise<void> }).act as (cb: () => void | Promise<void>) => void | Promise<void>;
|
||||
@@ -12,7 +12,7 @@ const testState = vi.hoisted(() => ({
|
||||
loadingTimestamps: [0] as number[],
|
||||
requestedAddresses: undefined as string[] | undefined,
|
||||
setOfflineStateMock: vi.fn(),
|
||||
subplebbitOfflineState: {} as Record<string, { initialLoad: boolean; state?: string; updatedAt?: number; updatingState?: string }>,
|
||||
communityOfflineState: {} as Record<string, { initialLoad: boolean; state?: string; updatedAt?: number; updatingState?: string }>,
|
||||
}));
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
@@ -30,7 +30,7 @@ vi.mock('../../stores/use-community-offline-store', () => ({
|
||||
default: () => ({
|
||||
initializeCommunityOfflineState: testState.initializeMock,
|
||||
setCommunityOfflineState: testState.setOfflineStateMock,
|
||||
communityOfflineState: testState.subplebbitOfflineState,
|
||||
communityOfflineState: testState.communityOfflineState,
|
||||
}),
|
||||
}));
|
||||
|
||||
@@ -45,12 +45,12 @@ vi.mock('../../lib/utils/time-utils', () => ({
|
||||
getFormattedTimeAgo: (timestamp: number) => `ago:${timestamp}`,
|
||||
}));
|
||||
|
||||
let latestValue: ReturnType<typeof useIsSubplebbitOffline>;
|
||||
let latestValue: ReturnType<typeof useIsCommunityOffline>;
|
||||
let container: HTMLDivElement;
|
||||
let root: Root;
|
||||
|
||||
const HookHarness = ({ subplebbit }: { subplebbit?: { address?: string; state?: string; updatedAt?: number; updatingState?: string } }) => {
|
||||
latestValue = useIsSubplebbitOffline(subplebbit as never);
|
||||
const HookHarness = ({ community }: { community?: { address?: string; state?: string; updatedAt?: number; updatingState?: string } }) => {
|
||||
latestValue = useIsCommunityOffline(community as never);
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -62,14 +62,14 @@ const flushEffects = async (count = 3) => {
|
||||
}
|
||||
};
|
||||
|
||||
const renderHook = async (subplebbit?: { address?: string; state?: string; updatedAt?: number; updatingState?: string }) => {
|
||||
const renderHook = async (community?: { address?: string; state?: string; updatedAt?: number; updatingState?: string }) => {
|
||||
await act(async () => {
|
||||
root.render(createElement(HookHarness, { subplebbit }));
|
||||
root.render(createElement(HookHarness, { community }));
|
||||
});
|
||||
await flushEffects();
|
||||
};
|
||||
|
||||
describe('useIsSubplebbitOffline', () => {
|
||||
describe('useIsCommunityOffline', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.useFakeTimers();
|
||||
@@ -83,7 +83,7 @@ describe('useIsSubplebbitOffline', () => {
|
||||
};
|
||||
testState.loadingTimestamps = [1_704_067_200];
|
||||
testState.requestedAddresses = undefined;
|
||||
testState.subplebbitOfflineState = {};
|
||||
testState.communityOfflineState = {};
|
||||
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
@@ -116,7 +116,7 @@ describe('useIsSubplebbitOffline', () => {
|
||||
|
||||
it('reports boards with stale updates as offline and includes the last synced time', async () => {
|
||||
const staleUpdatedAt = 1_704_052_000;
|
||||
testState.subplebbitOfflineState = {
|
||||
testState.communityOfflineState = {
|
||||
'music.eth': {
|
||||
initialLoad: false,
|
||||
updatedAt: staleUpdatedAt,
|
||||
@@ -136,7 +136,7 @@ describe('useIsSubplebbitOffline', () => {
|
||||
});
|
||||
|
||||
it('marks boards without an update timestamp as offline once the loading timeout has elapsed', async () => {
|
||||
testState.subplebbitOfflineState = {
|
||||
testState.communityOfflineState = {
|
||||
'music.eth': {
|
||||
initialLoad: false,
|
||||
},
|
||||
@@ -149,13 +149,13 @@ describe('useIsSubplebbitOffline', () => {
|
||||
isOffline: true,
|
||||
isOnlineStatusLoading: false,
|
||||
offlineIconClass: 'redOfflineIcon',
|
||||
offlineTitle: 'subplebbit_offline_info',
|
||||
offlineTitle: 'community_offline_info',
|
||||
});
|
||||
});
|
||||
|
||||
it('treats recently updated boards as online', async () => {
|
||||
const freshUpdatedAt = 1_704_067_205;
|
||||
testState.subplebbitOfflineState = {
|
||||
testState.communityOfflineState = {
|
||||
'music.eth': {
|
||||
initialLoad: false,
|
||||
updatedAt: freshUpdatedAt,
|
||||
@@ -39,13 +39,13 @@ const createPost = (boardAddress: string, suffix: string, replyCount: number, ti
|
||||
content: `${suffix} content`,
|
||||
link: `https://cdn.example/${boardAddress}/${suffix}.jpg`,
|
||||
replyCount,
|
||||
subplebbitAddress: boardAddress,
|
||||
communityAddress: boardAddress,
|
||||
thumbnailUrl: `https://cdn.example/${boardAddress}/${suffix}.thumb.jpg`,
|
||||
timestamp,
|
||||
title: `${suffix} title`,
|
||||
}) as never;
|
||||
|
||||
const createSubplebbit = (boardAddress: string, posts: Array<{ cid: string }>, updatedAt = 1_704_067_150) =>
|
||||
const createCommunity = (boardAddress: string, posts: Array<{ cid: string }>, updatedAt = 1_704_067_150) =>
|
||||
({
|
||||
address: boardAddress,
|
||||
updatedAt,
|
||||
@@ -58,14 +58,14 @@ const createSubplebbit = (boardAddress: string, posts: Array<{ cid: string }>, u
|
||||
},
|
||||
}) as never;
|
||||
|
||||
const HookHarness = ({ addresses, subplebbits }: { addresses: string[]; subplebbits: Array<unknown> }) => {
|
||||
latestValue = usePopularPosts(subplebbits as never, addresses);
|
||||
const HookHarness = ({ addresses, communities }: { addresses: string[]; communities: Array<unknown> }) => {
|
||||
latestValue = usePopularPosts(communities as never, addresses);
|
||||
return null;
|
||||
};
|
||||
|
||||
const renderHook = async (addresses: string[], subplebbits: Array<unknown>) => {
|
||||
const renderHook = async (addresses: string[], communities: Array<unknown>) => {
|
||||
await act(async () => {
|
||||
root.render(createElement(HookHarness, { addresses, subplebbits }));
|
||||
root.render(createElement(HookHarness, { addresses, communities }));
|
||||
});
|
||||
};
|
||||
|
||||
@@ -112,8 +112,8 @@ describe('usePopularPosts', () => {
|
||||
testState.loadingTimestamps = addresses.map(() => 1_704_067_180);
|
||||
|
||||
await renderHook(addresses, [
|
||||
createSubplebbit(addresses[0], [createPost(addresses[0], 'top', 20), createPost(addresses[0], 'backup', 10)]),
|
||||
createSubplebbit(addresses[1], [createPost(addresses[1], 'top', 18), createPost(addresses[1], 'backup', 9)]),
|
||||
createCommunity(addresses[0], [createPost(addresses[0], 'top', 20), createPost(addresses[0], 'backup', 10)]),
|
||||
createCommunity(addresses[1], [createPost(addresses[1], 'top', 18), createPost(addresses[1], 'backup', 9)]),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
@@ -128,12 +128,12 @@ describe('usePopularPosts', () => {
|
||||
|
||||
await renderHook(
|
||||
addresses,
|
||||
addresses.map((address, index) => createSubplebbit(address, [createPost(address, 'top', 20 - index), createPost(address, 'backup', 5 - index)])),
|
||||
addresses.map((address, index) => createCommunity(address, [createPost(address, 'top', 20 - index), createPost(address, 'backup', 5 - index)])),
|
||||
);
|
||||
|
||||
expect(latestValue.isLoading).toBe(false);
|
||||
expect(latestValue.popularPosts).toHaveLength(8);
|
||||
expect(new Set(latestValue.popularPosts.map((post) => post.subplebbitAddress)).size).toBe(8);
|
||||
expect(new Set(latestValue.popularPosts.map((post) => post.communityAddress)).size).toBe(8);
|
||||
expect(latestValue.popularPosts.every((post) => post.cid.endsWith('-top'))).toBe(true);
|
||||
});
|
||||
|
||||
@@ -143,7 +143,7 @@ describe('usePopularPosts', () => {
|
||||
|
||||
await renderHook(
|
||||
addresses,
|
||||
addresses.map((address, index) => createSubplebbit(address, [createPost(address, 'initial', 30 - index)])),
|
||||
addresses.map((address, index) => createCommunity(address, [createPost(address, 'initial', 30 - index)])),
|
||||
);
|
||||
|
||||
const initialCids = latestValue.popularPosts.map((post) => post.cid);
|
||||
@@ -151,7 +151,7 @@ describe('usePopularPosts', () => {
|
||||
|
||||
await renderHook(
|
||||
addresses,
|
||||
addresses.map((address, index) => createSubplebbit(address, [createPost(address, 'replacement', 100 - index), createPost(address, 'initial', 30 - index)])),
|
||||
addresses.map((address, index) => createCommunity(address, [createPost(address, 'replacement', 100 - index), createPost(address, 'initial', 30 - index)])),
|
||||
);
|
||||
|
||||
expect(latestValue.isLoading).toBe(false);
|
||||
@@ -162,13 +162,13 @@ describe('usePopularPosts', () => {
|
||||
const addresses = ['board-0.eth', 'board-1.eth'];
|
||||
testState.loadingTimestamps = [1_704_067_180, 1_704_067_180];
|
||||
|
||||
await renderHook(addresses, [createSubplebbit(addresses[0], [createPost(addresses[0], 'only', 12)]), undefined]);
|
||||
await renderHook(addresses, [createCommunity(addresses[0], [createPost(addresses[0], 'only', 12)]), undefined]);
|
||||
|
||||
expect(latestValue.isLoading).toBe(true);
|
||||
expect(latestValue.popularPosts).toEqual([]);
|
||||
|
||||
testState.currentTime = 1_704_067_211;
|
||||
await renderHook(addresses, [createSubplebbit(addresses[0], [createPost(addresses[0], 'only', 12)]), undefined]);
|
||||
await renderHook(addresses, [createCommunity(addresses[0], [createPost(addresses[0], 'only', 12)]), undefined]);
|
||||
|
||||
expect(latestValue.isLoading).toBe(false);
|
||||
expect(latestValue.popularPosts.map((post) => post.cid)).toEqual([`${addresses[0]}-only`]);
|
||||
@@ -187,23 +187,23 @@ describe('usePopularPosts', () => {
|
||||
|
||||
it('reshuffles the selected boards on each mount while keeping one top thread per board', async () => {
|
||||
const addresses = Array.from({ length: 10 }, (_, index) => `board-${index}.eth`);
|
||||
const subplebbits = addresses.map((address, index) => createSubplebbit(address, [createPost(address, 'top', 30 - index), createPost(address, 'backup', 10 - index)]));
|
||||
const communities = addresses.map((address, index) => createCommunity(address, [createPost(address, 'top', 30 - index), createPost(address, 'backup', 10 - index)]));
|
||||
const keepOrderRandom = mockRandomSequence(Array.from({ length: addresses.length - 1 }, () => 0.999_999));
|
||||
|
||||
await renderHook(addresses, subplebbits);
|
||||
await renderHook(addresses, communities);
|
||||
|
||||
expect(latestValue.isLoading).toBe(false);
|
||||
expect(latestValue.popularPosts.map((post) => post.subplebbitAddress)).toEqual(addresses.slice(0, 8));
|
||||
expect(latestValue.popularPosts.map((post) => post.communityAddress)).toEqual(addresses.slice(0, 8));
|
||||
expect(latestValue.popularPosts.every((post) => post.cid.endsWith('-top'))).toBe(true);
|
||||
|
||||
keepOrderRandom.mockRestore();
|
||||
resetHookRoot();
|
||||
|
||||
const rotateOrderRandom = mockRandomSequence(Array.from({ length: addresses.length - 1 }, () => 0));
|
||||
await renderHook(addresses, subplebbits);
|
||||
await renderHook(addresses, communities);
|
||||
|
||||
expect(latestValue.isLoading).toBe(false);
|
||||
expect(latestValue.popularPosts.map((post) => post.subplebbitAddress)).toEqual(addresses.slice(1, 9));
|
||||
expect(latestValue.popularPosts.map((post) => post.communityAddress)).toEqual(addresses.slice(1, 9));
|
||||
expect(latestValue.popularPosts.every((post) => post.cid.endsWith('-top'))).toBe(true);
|
||||
|
||||
rotateOrderRandom.mockRestore();
|
||||
|
||||
@@ -48,12 +48,12 @@ let latestValue: number | undefined;
|
||||
let container: HTMLDivElement;
|
||||
let root: Root;
|
||||
|
||||
const HookHarness = ({ enabled = true, postCid, subplebbitAddress }: { enabled?: boolean; postCid?: string; subplebbitAddress?: string }) => {
|
||||
latestValue = usePostPageNumber({ enabled, postCid, subplebbitAddress });
|
||||
const HookHarness = ({ enabled = true, postCid, communityAddress }: { enabled?: boolean; postCid?: string; communityAddress?: string }) => {
|
||||
latestValue = usePostPageNumber({ enabled, postCid, communityAddress });
|
||||
return null;
|
||||
};
|
||||
|
||||
const renderHook = (props: { enabled?: boolean; postCid?: string; subplebbitAddress?: string }) => {
|
||||
const renderHook = (props: { enabled?: boolean; postCid?: string; communityAddress?: string }) => {
|
||||
act(() => {
|
||||
root.render(createElement(HookHarness, props));
|
||||
});
|
||||
@@ -95,7 +95,7 @@ describe('usePostPageNumber', () => {
|
||||
boardFeed: [{ cid: 'post-1' }, { cid: 'post-2' }, { cid: 'post-3' }],
|
||||
};
|
||||
|
||||
expect(renderHook({ postCid: 'post-3', subplebbitAddress: 'music.eth' })).toBe(2);
|
||||
expect(renderHook({ postCid: 'post-3', communityAddress: 'music.eth' })).toBe(2);
|
||||
expect(testState.preloadOptions).toEqual({
|
||||
communities: [{ name: 'music.eth' }],
|
||||
postsPerPage: 20,
|
||||
@@ -106,7 +106,7 @@ describe('usePostPageNumber', () => {
|
||||
it('falls back to the preloaded feed when cached feeds do not contain the post yet', () => {
|
||||
testState.preloadFeed = [{ cid: 'post-1' }, { cid: 'post-2' }, { cid: 'post-3' }, { cid: 'post-4' }];
|
||||
|
||||
expect(renderHook({ postCid: 'post-4', subplebbitAddress: 'music.eth' })).toBe(2);
|
||||
expect(renderHook({ postCid: 'post-4', communityAddress: 'music.eth' })).toBe(2);
|
||||
expect(testState.preloadOptions).toEqual({
|
||||
communities: [{ name: 'music.eth' }],
|
||||
postsPerPage: 20,
|
||||
@@ -117,10 +117,10 @@ describe('usePostPageNumber', () => {
|
||||
it('skips resolution entirely when the hook is disabled or required inputs are missing', () => {
|
||||
testState.preloadFeed = [{ cid: 'post-1' }];
|
||||
|
||||
expect(renderHook({ enabled: false, postCid: 'post-1', subplebbitAddress: 'music.eth' })).toBeUndefined();
|
||||
expect(renderHook({ enabled: false, postCid: 'post-1', communityAddress: 'music.eth' })).toBeUndefined();
|
||||
expect(testState.preloadOptions).toBeUndefined();
|
||||
|
||||
expect(renderHook({ enabled: true, postCid: undefined, subplebbitAddress: 'music.eth' })).toBeUndefined();
|
||||
expect(renderHook({ enabled: true, postCid: undefined, communityAddress: 'music.eth' })).toBeUndefined();
|
||||
expect(testState.preloadOptions).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ describe('useQuotedByMap', () => {
|
||||
cid: 'reply-cid',
|
||||
content: 'replying to >>1',
|
||||
state: 'succeeded',
|
||||
subplebbitAddress: 'music.eth',
|
||||
communityAddress: 'music.eth',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('useQuotedByMap', () => {
|
||||
content: 'replying to >>1',
|
||||
number: 42,
|
||||
state: 'succeeded',
|
||||
subplebbitAddress: 'music.bso',
|
||||
communityAddress: 'music.bso',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { createElement } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { useStableSubplebbit, useSubplebbitField } from '../use-stable-subplebbit';
|
||||
import { useStableCommunity, useCommunityField } from '../use-stable-community';
|
||||
|
||||
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise<void> }).act as (cb: () => void | Promise<void>) => void | Promise<void>;
|
||||
@@ -36,7 +36,7 @@ const renderHookValue = (useValue: () => unknown) => {
|
||||
return latestValue;
|
||||
};
|
||||
|
||||
describe('use-stable-subplebbit', () => {
|
||||
describe('use-stable-community', () => {
|
||||
beforeEach(() => {
|
||||
latestValue = undefined;
|
||||
renderCount = 0;
|
||||
@@ -63,11 +63,11 @@ describe('use-stable-subplebbit', () => {
|
||||
},
|
||||
};
|
||||
|
||||
expect(renderHookValue(() => useSubplebbitField('international-sfw.eth', (subplebbit) => subplebbit?.roles))).toEqual({
|
||||
expect(renderHookValue(() => useCommunityField('international-sfw.eth', (community) => community?.roles))).toEqual({
|
||||
'plebeius.eth': { role: 'owner' },
|
||||
});
|
||||
|
||||
expect(renderHookValue(() => useStableSubplebbit('international-sfw.eth'))).toMatchObject({
|
||||
expect(renderHookValue(() => useStableCommunity('international-sfw.eth'))).toMatchObject({
|
||||
address: 'international-sfw.bso',
|
||||
title: '/int/ - International',
|
||||
});
|
||||
@@ -85,6 +85,6 @@ describe('use-stable-subplebbit', () => {
|
||||
},
|
||||
};
|
||||
|
||||
expect(renderHookValue(() => useSubplebbitField('business.eth', (subplebbit) => subplebbit?.title))).toBe('/biz/ - Exact');
|
||||
expect(renderHookValue(() => useCommunityField('business.eth', (community) => community?.title))).toBe('/biz/ - Exact');
|
||||
});
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
export { useAccountCommunityAddresses as useAccountSubplebbitAddresses } from './use-account-community-addresses';
|
||||
@@ -1 +0,0 @@
|
||||
export { useAccountCommunitiesWithMetadata as useAccountSubplebbitsWithMetadata } from './use-account-communities-with-metadata';
|
||||
@@ -4,17 +4,15 @@ import { useCommunityField } from './use-stable-community';
|
||||
|
||||
interface AuthorPrivilegesProps {
|
||||
commentAuthorAddress: string;
|
||||
subplebbitAddress?: string;
|
||||
communityAddress?: string;
|
||||
postCid?: string;
|
||||
}
|
||||
|
||||
const useAuthorPrivileges = ({ commentAuthorAddress, subplebbitAddress, communityAddress }: AuthorPrivilegesProps) => {
|
||||
const useAuthorPrivileges = ({ commentAuthorAddress, communityAddress }: AuthorPrivilegesProps) => {
|
||||
const account = useAccount();
|
||||
const targetAddress = communityAddress ?? subplebbitAddress;
|
||||
const accountAuthorAddress = account?.author?.address;
|
||||
// Only subscribe to roles field to avoid rerenders from updatingState changes
|
||||
const roles = useCommunityField(targetAddress, (community) => community?.roles);
|
||||
const roles = useCommunityField(communityAddress, (community) => community?.roles);
|
||||
const { isCommentAuthorMod, isAccountMod, isAccountCommentAuthor, commentAuthorRole, accountAuthorRole } = useMemo(() => {
|
||||
const commentAuthorRole = roles?.[commentAuthorAddress]?.role;
|
||||
const isCommentAuthorMod = commentAuthorRole === 'admin' || commentAuthorRole === 'owner' || commentAuthorRole === 'moderator';
|
||||
|
||||
@@ -29,9 +29,3 @@ export const CommunityStatsCollector = ({ communityAddress }: { communityAddress
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Back-compat exports for old naming.
|
||||
*/
|
||||
export const useSubplebbitsStatsStore = useCommunitiesStatsStore;
|
||||
export const SubplebbitStatsCollector = CommunityStatsCollector;
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { ChallengeVerification, Comment, PublishCommentOptions, deleteComment, usePublishComment } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
|
||||
import useChallengesStore from '../stores/use-challenges-store';
|
||||
import { getCommentCommunityAddress } from '../lib/utils/comment-utils';
|
||||
|
||||
const retryExcludedFields = new Set([
|
||||
'accountId',
|
||||
@@ -57,9 +58,11 @@ export const getFailedPostRetryPublishOptions = (post?: FailedPost): PublishComm
|
||||
retryOptions.author = author;
|
||||
}
|
||||
|
||||
if (!retryOptions.communityAddress && !retryOptions.subplebbitAddress) {
|
||||
const communityAddress = retryOptions.communityAddress ?? getCommentCommunityAddress(post);
|
||||
if (!communityAddress) {
|
||||
return undefined;
|
||||
}
|
||||
retryOptions.communityAddress = communityAddress;
|
||||
|
||||
return retryOptions;
|
||||
};
|
||||
|
||||
@@ -35,11 +35,9 @@ const useIsCommunityOffline = (community?: Community | undefined) => {
|
||||
? 'downloading board...'
|
||||
: updatedAt
|
||||
? isOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } })
|
||||
: t('subplebbit_offline_info');
|
||||
: t('community_offline_info');
|
||||
|
||||
return { isOffline: !isOnline && isOffline, isOnlineStatusLoading: !isOnline && isLoading, offlineIconClass, offlineTitle };
|
||||
};
|
||||
|
||||
export const useIsSubplebbitOffline = useIsCommunityOffline;
|
||||
|
||||
export default useIsCommunityOffline;
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import useIsCommunityOffline from './use-is-community-offline';
|
||||
|
||||
export { useIsCommunityOffline as useIsSubplebbitOffline };
|
||||
export default useIsCommunityOffline;
|
||||
@@ -7,10 +7,7 @@ import { useCommunityIdentifier } from './use-community-identifiers';
|
||||
import { findPostPageInFeed, findPostPageInLoadedBoardFeeds, type FeedsOptionsLike, type LoadedFeedsLike } from '../lib/utils/post-page-resolution';
|
||||
|
||||
interface UsePostPageNumberOptions {
|
||||
/** Canonical name. Kept for backward compatibility with older call sites. */
|
||||
communityAddress?: string;
|
||||
/** Legacy name kept for backwards compatibility. */
|
||||
subplebbitAddress?: string;
|
||||
postCid: string | undefined;
|
||||
/** When false, page segment is excluded (e.g. pending-post view). When true, resolve and show page. */
|
||||
enabled?: boolean;
|
||||
@@ -23,13 +20,7 @@ interface UsePostPageNumberOptions {
|
||||
*
|
||||
* @returns 1-based page number, or undefined when unresolved (render as "?")
|
||||
*/
|
||||
export function usePostPageNumber({
|
||||
communityAddress: requestedCommunityAddress,
|
||||
subplebbitAddress: legacyCommunityAddress,
|
||||
postCid,
|
||||
enabled = true,
|
||||
}: UsePostPageNumberOptions): number | undefined {
|
||||
const communityAddress = requestedCommunityAddress ?? legacyCommunityAddress;
|
||||
export function usePostPageNumber({ communityAddress, postCid, enabled = true }: UsePostPageNumberOptions): number | undefined {
|
||||
const communityIdentifier = useCommunityIdentifier(communityAddress);
|
||||
|
||||
const community = useDirectoryByAddress(communityAddress);
|
||||
|
||||
@@ -5,14 +5,12 @@ import { getCommunityAddress, getBoardPath } from '../lib/utils/route-utils';
|
||||
|
||||
/**
|
||||
* Resolve a board identifier from URL params to canonical community address.
|
||||
* Supports both current route params (`boardIdentifier`) and legacy
|
||||
* compatibility params (`subplebbitAddress`).
|
||||
*/
|
||||
export const useResolvedCommunityAddress = (): string | undefined => {
|
||||
const params = useParams<{ boardIdentifier?: string; subplebbitAddress?: string }>();
|
||||
const params = useParams<{ boardIdentifier?: string }>();
|
||||
const directories = useDirectories();
|
||||
|
||||
const boardIdentifier = params.boardIdentifier || params.subplebbitAddress;
|
||||
const boardIdentifier = params.boardIdentifier;
|
||||
|
||||
return useMemo(() => {
|
||||
if (!boardIdentifier) {
|
||||
@@ -23,11 +21,6 @@ export const useResolvedCommunityAddress = (): string | undefined => {
|
||||
}, [boardIdentifier, directories]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Back-compat export kept for callers still importing the legacy hook name.
|
||||
*/
|
||||
export const useResolvedSubplebbitAddress = useResolvedCommunityAddress;
|
||||
|
||||
/**
|
||||
* Resolve a community address to board path (directory code or address) for links.
|
||||
*/
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { useBoardPath, useResolvedSubplebbitAddress } from './use-resolved-community-address';
|
||||
@@ -72,9 +72,3 @@ export const useCommunityField = <T>(communityAddress: string | undefined, selec
|
||||
|
||||
return field;
|
||||
};
|
||||
|
||||
/**
|
||||
* Back-compat exports for old hook names.
|
||||
*/
|
||||
export const useStableSubplebbit = useStableCommunity;
|
||||
export const useSubplebbitField = useCommunityField;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { useStableSubplebbit, useSubplebbitField } from './use-stable-community';
|
||||
@@ -27,12 +27,9 @@ const friendlyStateNames: Record<string, string> = {
|
||||
'fetching-ipfs': 'downloading thread',
|
||||
'fetching-community-ipns': 'downloading board',
|
||||
'fetching-community-ipfs': 'downloading board',
|
||||
'fetching-subplebbit-ipns': 'downloading board',
|
||||
'fetching-subplebbit-ipfs': 'downloading board',
|
||||
'fetching-update-ipfs': 'downloading update',
|
||||
'resolving-address': 'resolving address',
|
||||
'resolving-community-address': 'resolving board address',
|
||||
'resolving-subplebbit-address': 'resolving board address',
|
||||
'resolving-author-address': 'resolving author address',
|
||||
};
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { SubplebbitStatsCollector, useSubplebbitsStatsStore } from './use-communities-stats';
|
||||
@@ -8,6 +8,7 @@ import useSpecialThemeStore from '../stores/use-special-theme-store';
|
||||
import { isChristmas } from '../lib/utils/time-utils';
|
||||
import { isSfwBoard, updateFavicon } from '../lib/update-favicon';
|
||||
import useSafeAccountComment from './use-safe-account-comment';
|
||||
import { getCommentCommunityAddress } from '../lib/utils/comment-utils';
|
||||
|
||||
const themeClasses = ['yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'tomorrow', 'photon'];
|
||||
|
||||
@@ -20,14 +21,11 @@ const updateThemeClass = (newTheme: string) => {
|
||||
|
||||
const useTheme = (): [string, (theme: string) => void] => {
|
||||
const location = useLocation();
|
||||
const params = useParams<{ boardIdentifier?: string; subplebbitAddress?: string }>();
|
||||
const params = useParams<{ boardIdentifier?: string }>();
|
||||
const pendingPostParams = useParams<{ accountCommentIndex?: string }>();
|
||||
const pendingPostCommentIndex = pendingPostParams?.accountCommentIndex ? parseInt(pendingPostParams.accountCommentIndex, 10) : undefined;
|
||||
const pendingPost = useSafeAccountComment({ commentIndex: pendingPostCommentIndex });
|
||||
const pendingPostCommunityAddress =
|
||||
(pendingPost as { communityAddress?: string }).communityAddress ||
|
||||
// compatibility fallback for legacy inbound/persisted comment payloads
|
||||
(pendingPost as { subplebbitAddress?: string }).subplebbitAddress;
|
||||
const pendingPostCommunityAddress = getCommentCommunityAddress(pendingPost);
|
||||
|
||||
const { isEnabled, setIsEnabled } = useSpecialThemeStore();
|
||||
|
||||
@@ -38,7 +36,7 @@ const useTheme = (): [string, (theme: string) => void] => {
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInSubscriptionsView = isSubscriptionsView(location.pathname, params);
|
||||
const isInModView = isModView(location.pathname);
|
||||
const routeIdentifier = params.boardIdentifier || params.subplebbitAddress;
|
||||
const routeIdentifier = params.boardIdentifier;
|
||||
const resolvedAddress = useResolvedCommunityAddress();
|
||||
const communityAddress = resolvedAddress || pendingPostCommunityAddress || routeIdentifier;
|
||||
|
||||
@@ -86,7 +84,7 @@ const useTheme = (): [string, (theme: string) => void] => {
|
||||
isInAllView,
|
||||
isInSubscriptionsView,
|
||||
isInModView,
|
||||
subplebbitAddress: communityAddress,
|
||||
communityAddress,
|
||||
directories,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user