fix(quotes): keep same-thread board previews local

This commit is contained in:
Tommaso Casaburi
2026-04-16 15:33:12 +07:00
parent f6ce2ba018
commit e366dac25c
16 changed files with 293 additions and 64 deletions
@@ -41,7 +41,7 @@ let latestValue: ReturnType<typeof usePublishPost>;
let root: Root;
const HookHarness = () => {
latestValue = usePublishPost({ subplebbitAddress: 'music.eth' });
latestValue = usePublishPost({ communityAddress: 'music.eth' });
return null;
};
@@ -92,7 +92,6 @@ describe('usePublishPost', () => {
spoiler: true,
title: 'Hello world',
});
expect('subplebbitAddress' in latestValue.publishPostOptions).toBe(false);
expect(typeof latestValue.publishPostOptions.onChallengeVerification).toBe('function');
expect(typeof latestValue.publishPostOptions.onError).toBe('function');
});
@@ -41,6 +41,7 @@ vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
vi.mock('../../hooks/use-directories', () => ({
useDirectories: () => testState.directories,
normalizeBoardAddress: (address?: string) => address?.replace(/(\.bso|\.eth)$/u, ''),
}));
vi.mock('../../lib/utils/external-quote-resolver', () => ({
@@ -60,7 +61,7 @@ let latestValue: ReturnType<typeof usePublishReply>;
let root: Root;
const HookHarness = () => {
latestValue = usePublishReply({ cid: 'parent-cid', subplebbitAddress: 'music.eth' });
latestValue = usePublishReply({ cid: 'parent-cid', communityAddress: 'music.eth' });
return null;
};
@@ -122,14 +123,13 @@ describe('usePublishReply', () => {
quotedCids: ['quoted-cid'],
spoiler: true,
});
expect('subplebbitAddress' in (testState.lastPublishOptions || {})).toBe(false);
});
it('resolves same-board external quote references before triggering publish', async () => {
testState.resolveExternalQuoteTargetMock.mockResolvedValue({
cid: 'external-cid',
route: '/music/thread/external-cid',
subplebbitAddress: 'music.eth',
communityAddress: 'music.eth',
});
await act(async () => {
@@ -72,4 +72,32 @@ describe('useQuotedByMap', () => {
expect(latestValue.get('op-cid')?.[0]?.number).toBe(42);
});
it('matches same-board quote numbers across .eth and .bso aliases', () => {
usePostNumberStore.setState({
cidToNumber: { 'op-cid': 1 },
numberToCid: { 'music.eth': { 1: 'op-cid' } },
});
testState.replies = [
{
cid: 'reply-cid',
content: 'replying to >>1',
number: 42,
state: 'succeeded',
subplebbitAddress: 'music.bso',
},
];
act(() => {
root.render(
createElement(() => {
latestValue = useQuotedByMap(testState.replies as never, 'music.bso');
return null;
}),
);
});
expect(latestValue.get('op-cid')?.[0]?.cid).toBe('reply-cid');
});
});
+3 -11
View File
@@ -6,11 +6,9 @@ import usePublishAuthorDomainGuard, { getPublishAuthorDomainErrorMessage } from
type UsePublishPostOptions = {
communityAddress?: string;
/** legacy compatibility */
subplebbitAddress?: string;
};
const usePublishPost = ({ communityAddress: requestedCommunityAddress, subplebbitAddress }: UsePublishPostOptions) => {
const usePublishPost = ({ communityAddress }: UsePublishPostOptions) => {
const { author, title, content, link, spoiler, publishCommentOptions } = usePublishPostStore((state) => ({
author: state.author,
title: state.title || undefined,
@@ -30,8 +28,6 @@ const usePublishPost = ({ communityAddress: requestedCommunityAddress, subplebbi
await abandonPublishRef.current?.();
}, []);
const communityAddress = requestedCommunityAddress ?? subplebbitAddress;
const createBaseOptions = useCallback(() => {
const baseOptions: Comment = {
communityAddress,
@@ -60,12 +56,8 @@ const usePublishPost = ({ communityAddress: requestedCommunityAddress, subplebbi
{} as Partial<Comment>,
);
const {
communityAddress: nextCommunityAddress,
subplebbitAddress: legacyCommunityAddress,
...restOptions
} = sanitizedOptions as Partial<Comment> & { subplebbitAddress?: string };
const resolvedCommunityAddress = nextCommunityAddress ?? legacyCommunityAddress ?? baseOptions.communityAddress;
const { communityAddress: nextCommunityAddress, ...restOptions } = sanitizedOptions;
const resolvedCommunityAddress = nextCommunityAddress ?? baseOptions.communityAddress;
const newOptions = {
...baseOptions,
...restOptions,
+5 -13
View File
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { Comment, useAccount, usePublishComment } from '@bitsocialnet/bitsocial-react-hooks';
import { useDirectories } from './use-directories';
import usePublishReplyStore from '../stores/use-publish-reply-store';
import usePostNumberStore from '../stores/use-post-number-store';
import usePostNumberStore, { getScopedNumberToCidMap } from '../stores/use-post-number-store';
import { getQuotedCidsFromContent, mergeQuotedCids } from '../lib/utils/reply-quote-utils';
import { extractUnresolvedExternalQuoteReferences, getExternalQuoteStatusMessage } from '../lib/utils/external-quote-utils';
import { resolveExternalQuoteTarget } from '../lib/utils/external-quote-resolver';
@@ -13,14 +13,10 @@ import usePublishAuthorDomainGuard, { getPublishAuthorDomainErrorMessage } from
type UsePublishReplyOptions = {
cid: string;
communityAddress?: string;
/** legacy compatibility */
subplebbitAddress?: string;
postCid?: string;
};
const usePublishReply = ({ cid, communityAddress: requestedCommunityAddress, subplebbitAddress, postCid }: UsePublishReplyOptions) => {
const communityAddress = requestedCommunityAddress ?? subplebbitAddress;
const usePublishReply = ({ cid, communityAddress, postCid }: UsePublishReplyOptions) => {
const { t } = useTranslation();
const parentCid = cid;
const account = useAccount();
@@ -78,12 +74,8 @@ const usePublishReply = ({ cid, communityAddress: requestedCommunityAddress, sub
{} as Partial<Comment>,
);
const {
communityAddress: nextCommunityAddress,
subplebbitAddress: legacyCommunityAddress,
...restOptions
} = sanitizedOptions as Partial<Comment> & { subplebbitAddress?: string };
const resolvedCommunityAddress = nextCommunityAddress ?? legacyCommunityAddress ?? baseOptions.communityAddress;
const { communityAddress: nextCommunityAddress, ...restOptions } = sanitizedOptions;
const resolvedCommunityAddress = nextCommunityAddress ?? baseOptions.communityAddress;
const newOptions = {
...baseOptions,
...restOptions,
@@ -96,7 +88,7 @@ const usePublishReply = ({ cid, communityAddress: requestedCommunityAddress, sub
const resetPublishReplyOptions = useCallback(() => resetPublishReplyStore(parentCid), [parentCid, resetPublishReplyStore]);
const scopedNumberToCid = usePostNumberStore((state) => (communityAddress ? state.numberToCid[communityAddress] : undefined));
const scopedNumberToCid = usePostNumberStore((state) => getScopedNumberToCidMap(state.numberToCid, communityAddress));
const quotedCids = useMemo(() => getQuotedCidsFromContent(content, scopedNumberToCid), [content, scopedNumberToCid]);
const unresolvedExternalQuoteReferences = useMemo(
() =>
+7 -7
View File
@@ -1,7 +1,7 @@
import { useCallback, useMemo, useRef } from 'react';
import { Comment } from '@bitsocialnet/bitsocial-react-hooks';
import { QUOTE_NUMBER_REGEX } from '../lib/utils/url-utils';
import usePostNumberStore from '../stores/use-post-number-store';
import usePostNumberStore, { getScopedNumberToCidMap } from '../stores/use-post-number-store';
interface ReplyQuoteTargets {
reply: Comment;
@@ -61,27 +61,27 @@ const extractReplyQuoteTargets = (replies: Comment[]) => {
};
};
const useQuotedByMap = (replies: Comment[] = [], subplebbitAddress?: string) => {
const useQuotedByMap = (replies: Comment[] = [], communityAddress?: string) => {
const stableQuotedByMapRef = useRef<Map<string, Comment[]>>(new Map());
const { replyQuoteTargets, quotedPostNumbers } = useMemo(() => extractReplyQuoteTargets(replies), [replies]);
const quotedNumbersSignature = usePostNumberStore(
useCallback(
(state) => {
const scoped = subplebbitAddress ? state.numberToCid[subplebbitAddress] : undefined;
const scoped = getScopedNumberToCidMap(state.numberToCid, communityAddress);
return quotedPostNumbers.map((postNumber) => `${postNumber}:${scoped?.[postNumber] ?? ''}`).join('|');
},
[quotedPostNumbers, subplebbitAddress],
[quotedPostNumbers, communityAddress],
),
);
const quotedNumberToCid = useMemo(() => {
if (quotedPostNumbers.length === 0 || !subplebbitAddress) {
if (quotedPostNumbers.length === 0 || !communityAddress) {
return {} as Record<number, string>;
}
const { numberToCid } = usePostNumberStore.getState();
const scoped = numberToCid[subplebbitAddress];
const scoped = getScopedNumberToCidMap(numberToCid, communityAddress);
if (!scoped) return {} as Record<number, string>;
const nextQuotedNumberToCid: Record<number, string> = {};
@@ -94,7 +94,7 @@ const useQuotedByMap = (replies: Comment[] = [], subplebbitAddress?: string) =>
}
return nextQuotedNumberToCid;
}, [quotedPostNumbers, subplebbitAddress, quotedNumbersSignature]);
}, [quotedPostNumbers, communityAddress, quotedNumbersSignature]);
return useMemo(() => {
const map = new Map<string, Comment[]>();