mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(hooks): handle pkc rebrand regressions
This commit is contained in:
+16
-16
@@ -9,20 +9,20 @@ const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise
|
||||
const testState = vi.hoisted(() => ({
|
||||
account: {
|
||||
mediaIpfsGatewayUrl: 'https://media.old.example',
|
||||
plebbitOptions: {
|
||||
pkcOptions: {
|
||||
chainProviders: {
|
||||
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
||||
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
||||
},
|
||||
httpRoutersOptions: ['https://router.old.example'],
|
||||
ipfsGatewayUrls: ['https://ipfs.old.example'],
|
||||
plebbitRpcClientsOptions: ['ws://old.example/key'],
|
||||
pubsubHttpClientsOptions: ['https://pubsub.old.example'],
|
||||
pkcRpcClientsOptions: ['ws://old.example/key'],
|
||||
pubsubKuboRpcClientsOptions: ['https://pubsub.old.example'],
|
||||
},
|
||||
} as Record<string, any>,
|
||||
rpcSettings: {
|
||||
plebbitRpcSettings: {
|
||||
plebbitOptions: {
|
||||
pkcRpcSettings: {
|
||||
pkcOptions: {
|
||||
dataPath: '/tmp/plebbit-data',
|
||||
},
|
||||
},
|
||||
@@ -40,7 +40,7 @@ vi.mock('react-i18next', () => ({
|
||||
vi.mock('@bitsocialnet/bitsocial-react-hooks', () => ({
|
||||
setAccount: (account: unknown) => testState.setAccountMock(account),
|
||||
useAccount: () => testState.account,
|
||||
usePlebbitRpcSettings: () => testState.rpcSettings,
|
||||
usePkcRpcSettings: () => testState.rpcSettings,
|
||||
}));
|
||||
|
||||
let alertSpy: ReturnType<typeof vi.spyOn>;
|
||||
@@ -86,20 +86,20 @@ describe('AdvancedSettings', () => {
|
||||
vi.clearAllMocks();
|
||||
testState.account = {
|
||||
mediaIpfsGatewayUrl: 'https://media.old.example',
|
||||
plebbitOptions: {
|
||||
pkcOptions: {
|
||||
chainProviders: {
|
||||
eth: { chainId: 1, urls: ['https://eth.old.example'] },
|
||||
sol: { chainId: 101, urls: ['https://sol.old.example'] },
|
||||
},
|
||||
httpRoutersOptions: ['https://router.old.example'],
|
||||
ipfsGatewayUrls: ['https://ipfs.old.example'],
|
||||
plebbitRpcClientsOptions: ['ws://old.example/key'],
|
||||
pubsubHttpClientsOptions: ['https://pubsub.old.example'],
|
||||
pkcRpcClientsOptions: ['ws://old.example/key'],
|
||||
pubsubKuboRpcClientsOptions: ['https://pubsub.old.example'],
|
||||
},
|
||||
};
|
||||
testState.rpcSettings = {
|
||||
plebbitRpcSettings: {
|
||||
plebbitOptions: {
|
||||
pkcRpcSettings: {
|
||||
pkcOptions: {
|
||||
dataPath: '/tmp/plebbit-data',
|
||||
},
|
||||
},
|
||||
@@ -154,7 +154,7 @@ describe('AdvancedSettings', () => {
|
||||
|
||||
expect(testState.setAccountMock).toHaveBeenCalledWith({
|
||||
mediaIpfsGatewayUrl: 'https://media.new.example',
|
||||
plebbitOptions: {
|
||||
pkcOptions: {
|
||||
chainProviders: {
|
||||
eth: { chainId: 1, urls: ['https://eth.one.example'] },
|
||||
sol: { chainId: 101, urls: ['https://sol.one.example'] },
|
||||
@@ -162,8 +162,8 @@ describe('AdvancedSettings', () => {
|
||||
dataPath: '/tmp/next-plebbit',
|
||||
httpRoutersOptions: ['https://router.one.example'],
|
||||
ipfsGatewayUrls: ['https://ipfs.one.example', 'https://ipfs.two.example'],
|
||||
plebbitRpcClientsOptions: ['ws://127.0.0.1:9138/secret'],
|
||||
pubsubHttpClientsOptions: ['https://pubsub.one.example'],
|
||||
pkcRpcClientsOptions: ['ws://127.0.0.1:9138/secret'],
|
||||
pubsubKuboRpcClientsOptions: ['https://pubsub.one.example'],
|
||||
},
|
||||
});
|
||||
expect(alertSpy).toHaveBeenCalledWith('Options saved, reloading...');
|
||||
@@ -172,8 +172,8 @@ describe('AdvancedSettings', () => {
|
||||
|
||||
it('disables remote-managed textareas and shows the electron data path when RPC is connected', async () => {
|
||||
testState.rpcSettings = {
|
||||
plebbitRpcSettings: {
|
||||
plebbitOptions: {
|
||||
pkcRpcSettings: {
|
||||
pkcOptions: {
|
||||
dataPath: '/tmp/connected-node',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { memo, RefObject, useRef, useState } from 'react';
|
||||
import { setAccount, useAccount, usePlebbitRpcSettings } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import { setAccount, useAccount, usePkcRpcSettings } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styles from './advanced-settings.module.css';
|
||||
|
||||
@@ -14,12 +14,47 @@ interface SettingsProps {
|
||||
p2pDataPathRef?: RefObject<HTMLInputElement>;
|
||||
}
|
||||
|
||||
type AccountProtocolOptions = {
|
||||
chainProviders?: Record<string, { urls?: string[]; chainId: number }>;
|
||||
dataPath?: string;
|
||||
httpRoutersOptions?: string[];
|
||||
ipfsGatewayUrls?: string[];
|
||||
pkcRpcClientsOptions?: string[];
|
||||
plebbitRpcClientsOptions?: string[];
|
||||
pubsubHttpClientsOptions?: string[];
|
||||
pubsubKuboRpcClientsOptions?: string[];
|
||||
};
|
||||
|
||||
type AccountShape = {
|
||||
chainProviders?: AccountProtocolOptions['chainProviders'];
|
||||
mediaIpfsGatewayUrl?: string;
|
||||
pkcOptions?: AccountProtocolOptions;
|
||||
plebbitOptions?: AccountProtocolOptions;
|
||||
};
|
||||
|
||||
type RpcSettingsShape = {
|
||||
pkcOptions?: { dataPath?: string };
|
||||
plebbitOptions?: { dataPath?: string };
|
||||
};
|
||||
|
||||
const getProtocolOptions = (account?: AccountShape) => account?.pkcOptions ?? account?.plebbitOptions;
|
||||
|
||||
const getChainProviders = (account?: AccountShape) => account?.chainProviders ?? getProtocolOptions(account)?.chainProviders;
|
||||
|
||||
const getNodeRpcClientsOptions = (protocolOptions?: AccountProtocolOptions) => protocolOptions?.pkcRpcClientsOptions ?? protocolOptions?.plebbitRpcClientsOptions;
|
||||
|
||||
const getPubsubRpcClientsOptions = (protocolOptions?: AccountProtocolOptions) =>
|
||||
protocolOptions?.pubsubKuboRpcClientsOptions ?? protocolOptions?.pubsubHttpClientsOptions;
|
||||
|
||||
const getRpcSettingsDataPath = (rpcSettings?: RpcSettingsShape) => rpcSettings?.pkcOptions?.dataPath ?? rpcSettings?.plebbitOptions?.dataPath ?? '';
|
||||
|
||||
const IPFSGatewaysSettings = ({ ipfsGatewayUrlsRef, mediaIpfsGatewayUrlRef }: SettingsProps) => {
|
||||
const account = useAccount();
|
||||
const { plebbitOptions, mediaIpfsGatewayUrl } = account || {};
|
||||
const { ipfsGatewayUrls } = plebbitOptions || {};
|
||||
const plebbitRpc = usePlebbitRpcSettings();
|
||||
const isConnectedToRpc = plebbitRpc?.state === 'connected';
|
||||
const account = useAccount() as AccountShape | undefined;
|
||||
const protocolOptions = getProtocolOptions(account);
|
||||
const { ipfsGatewayUrls } = protocolOptions || {};
|
||||
const { mediaIpfsGatewayUrl } = account || {};
|
||||
const pkcRpc = usePkcRpcSettings();
|
||||
const isConnectedToRpc = pkcRpc?.state === 'connected';
|
||||
const ipfsGatewayUrlsDefaultValue = ipfsGatewayUrls?.join('\n');
|
||||
|
||||
return (
|
||||
@@ -52,12 +87,12 @@ const IPFSGatewaysSettings = ({ ipfsGatewayUrlsRef, mediaIpfsGatewayUrlRef }: Se
|
||||
};
|
||||
|
||||
const PubsubProvidersSettings = ({ pubsubProvidersRef }: SettingsProps) => {
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const { pubsubHttpClientsOptions } = plebbitOptions || {};
|
||||
const plebbitRpc = usePlebbitRpcSettings();
|
||||
const isConnectedToRpc = plebbitRpc?.state === 'connected';
|
||||
const pubsubProvidersDefaultValue = pubsubHttpClientsOptions?.join('\n');
|
||||
const account = useAccount() as AccountShape | undefined;
|
||||
const protocolOptions = getProtocolOptions(account);
|
||||
const pubsubKuboRpcClientsOptions = getPubsubRpcClientsOptions(protocolOptions);
|
||||
const pkcRpc = usePkcRpcSettings();
|
||||
const isConnectedToRpc = pkcRpc?.state === 'connected';
|
||||
const pubsubProvidersDefaultValue = pubsubKuboRpcClientsOptions?.join('\n');
|
||||
|
||||
return (
|
||||
<div className={styles.pubsubProvidersSettings}>
|
||||
@@ -69,18 +104,18 @@ const PubsubProvidersSettings = ({ pubsubProvidersRef }: SettingsProps) => {
|
||||
autoCapitalize='off'
|
||||
autoComplete='off'
|
||||
spellCheck='false'
|
||||
rows={pubsubHttpClientsOptions?.length || 1}
|
||||
rows={pubsubKuboRpcClientsOptions?.length || 1}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const HttpRoutersSettings = ({ httpRoutersRef }: SettingsProps) => {
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const { httpRoutersOptions } = plebbitOptions || {};
|
||||
const plebbitRpc = usePlebbitRpcSettings();
|
||||
const isConnectedToRpc = plebbitRpc?.state === 'connected';
|
||||
const account = useAccount() as AccountShape | undefined;
|
||||
const protocolOptions = getProtocolOptions(account);
|
||||
const { httpRoutersOptions } = protocolOptions || {};
|
||||
const pkcRpc = usePkcRpcSettings();
|
||||
const isConnectedToRpc = pkcRpc?.state === 'connected';
|
||||
const httpRoutersDefaultValue = httpRoutersOptions?.join('\n');
|
||||
|
||||
return (
|
||||
@@ -100,11 +135,10 @@ const HttpRoutersSettings = ({ httpRoutersRef }: SettingsProps) => {
|
||||
};
|
||||
|
||||
const BlockchainProvidersSettings = ({ ethRpcRef, solRpcRef }: SettingsProps) => {
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const { chainProviders } = plebbitOptions || {};
|
||||
const ethRpcDefaultValue = chainProviders?.['eth']?.urls.join('\n');
|
||||
const solRpcDefaultValue = chainProviders?.['sol']?.urls.join('\n');
|
||||
const account = useAccount() as AccountShape | undefined;
|
||||
const chainProviders = getChainProviders(account);
|
||||
const ethRpcDefaultValue = chainProviders?.['eth']?.urls?.join('\n');
|
||||
const solRpcDefaultValue = chainProviders?.['sol']?.urls?.join('\n');
|
||||
|
||||
return (
|
||||
<div className={styles.blockchainProvidersSettings}>
|
||||
@@ -136,14 +170,14 @@ const BlockchainProvidersSettings = ({ ethRpcRef, solRpcRef }: SettingsProps) =>
|
||||
|
||||
const P2pRPCSettings = ({ p2pRpcRef }: SettingsProps) => {
|
||||
const [showInfo, setShowInfo] = useState(false);
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const { plebbitRpcClientsOptions } = plebbitOptions || {};
|
||||
const account = useAccount() as AccountShape | undefined;
|
||||
const protocolOptions = getProtocolOptions(account);
|
||||
const pkcRpcClientsOptions = getNodeRpcClientsOptions(protocolOptions);
|
||||
|
||||
return (
|
||||
<div className={styles.p2pRPCSettings}>
|
||||
<div>
|
||||
<input type='text' defaultValue={plebbitRpcClientsOptions} ref={p2pRpcRef} autoCorrect='off' autoCapitalize='off' spellCheck='false' />
|
||||
<input type='text' defaultValue={pkcRpcClientsOptions} ref={p2pRpcRef} autoCorrect='off' autoCapitalize='off' spellCheck='false' />
|
||||
<button onClick={() => setShowInfo(!showInfo)}>{showInfo ? 'X' : '?'}</button>
|
||||
</div>
|
||||
{showInfo && (
|
||||
@@ -165,10 +199,10 @@ const P2pRPCSettings = ({ p2pRpcRef }: SettingsProps) => {
|
||||
};
|
||||
|
||||
const P2pDataPathSettings = ({ p2pDataPathRef }: SettingsProps) => {
|
||||
const plebbitRpc = usePlebbitRpcSettings();
|
||||
const { plebbitRpcSettings } = plebbitRpc || {};
|
||||
const isConnectedToRpc = plebbitRpc?.state === 'connected';
|
||||
const path = plebbitRpcSettings?.plebbitOptions?.dataPath || '';
|
||||
const pkcRpc = usePkcRpcSettings();
|
||||
const { pkcRpcSettings } = pkcRpc || {};
|
||||
const isConnectedToRpc = pkcRpc?.state === 'connected';
|
||||
const path = getRpcSettingsDataPath(pkcRpcSettings as RpcSettingsShape | undefined);
|
||||
|
||||
return (
|
||||
<div className={styles.p2pDataPathSettings}>
|
||||
@@ -183,8 +217,8 @@ const isElectron = window.electronApi?.isElectron === true;
|
||||
|
||||
const AdvancedSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
const { plebbitOptions } = account || {};
|
||||
const account = useAccount() as AccountShape | undefined;
|
||||
const protocolOptions = getProtocolOptions(account);
|
||||
|
||||
const ipfsGatewayUrlsRef = useRef<HTMLTextAreaElement>(null);
|
||||
const mediaIpfsGatewayUrlRef = useRef<HTMLInputElement>(null);
|
||||
@@ -223,7 +257,7 @@ const AdvancedSettings = () => {
|
||||
.map((url) => url.trim())
|
||||
.filter((url) => url !== '');
|
||||
|
||||
const plebbitRpcClientsOptions = p2pRpcRef.current?.value.trim() ? [p2pRpcRef.current.value.trim()] : undefined;
|
||||
const pkcRpcClientsOptions = p2pRpcRef.current?.value.trim() ? [p2pRpcRef.current.value.trim()] : undefined;
|
||||
const dataPath = p2pDataPathRef.current?.value.trim() || undefined;
|
||||
|
||||
const chainProviders: Record<string, { urls: string[] | undefined; chainId: number }> = {};
|
||||
@@ -238,13 +272,13 @@ const AdvancedSettings = () => {
|
||||
await setAccount({
|
||||
...account,
|
||||
mediaIpfsGatewayUrl,
|
||||
plebbitOptions: {
|
||||
...plebbitOptions,
|
||||
pkcOptions: {
|
||||
...protocolOptions,
|
||||
ipfsGatewayUrls,
|
||||
pubsubHttpClientsOptions,
|
||||
pubsubKuboRpcClientsOptions: pubsubHttpClientsOptions,
|
||||
chainProviders,
|
||||
httpRoutersOptions,
|
||||
plebbitRpcClientsOptions,
|
||||
pkcRpcClientsOptions,
|
||||
dataPath,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -76,10 +76,10 @@ describe('usePublishPost', () => {
|
||||
expect(latestValue.publishPost).toBe(testState.publishCommentMock);
|
||||
expect(latestValue.publishPostOptions).toMatchObject({
|
||||
author: { displayName: 'Alice' },
|
||||
communityAddress: 'music.eth',
|
||||
content: undefined,
|
||||
link: undefined,
|
||||
spoiler: true,
|
||||
subplebbitAddress: 'music.eth',
|
||||
title: 'Hello world',
|
||||
});
|
||||
expect(typeof latestValue.publishPostOptions.onChallengeVerification).toBe('function');
|
||||
|
||||
@@ -104,13 +104,13 @@ describe('usePublishReply', () => {
|
||||
expect(typeof latestValue.publishReply).toBe('function');
|
||||
expect(testState.lastPublishOptions).toMatchObject({
|
||||
author: { displayName: 'Bob' },
|
||||
communityAddress: 'music.eth',
|
||||
content: 'Replying to >>12',
|
||||
link: undefined,
|
||||
parentCid: 'parent-cid',
|
||||
postCid: 'parent-cid',
|
||||
quotedCids: ['quoted-cid'],
|
||||
spoiler: true,
|
||||
subplebbitAddress: 'music.eth',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ const usePublishPost = ({ communityAddress: requestedCommunityAddress, subplebbi
|
||||
const createBaseOptions = useCallback(() => {
|
||||
const baseOptions: Comment = {
|
||||
communityAddress,
|
||||
subplebbitAddress: communityAddress,
|
||||
title,
|
||||
content,
|
||||
link,
|
||||
@@ -58,7 +57,17 @@ const usePublishPost = ({ communityAddress: requestedCommunityAddress, subplebbi
|
||||
{} as Partial<Comment>,
|
||||
);
|
||||
|
||||
const newOptions = { ...baseOptions, ...sanitizedOptions };
|
||||
const {
|
||||
communityAddress: nextCommunityAddress,
|
||||
subplebbitAddress: legacyCommunityAddress,
|
||||
...restOptions
|
||||
} = sanitizedOptions as Partial<Comment> & { subplebbitAddress?: string };
|
||||
const resolvedCommunityAddress = nextCommunityAddress ?? legacyCommunityAddress ?? baseOptions.communityAddress;
|
||||
const newOptions = {
|
||||
...baseOptions,
|
||||
...restOptions,
|
||||
...(resolvedCommunityAddress ? { communityAddress: resolvedCommunityAddress } : {}),
|
||||
};
|
||||
setPublishPostStore(newOptions);
|
||||
},
|
||||
[createBaseOptions, setPublishPostStore],
|
||||
|
||||
@@ -50,7 +50,6 @@ const usePublishReply = ({ cid, communityAddress: requestedCommunityAddress, sub
|
||||
const createBaseOptions = useCallback(() => {
|
||||
const baseOptions: Comment = {
|
||||
communityAddress,
|
||||
subplebbitAddress: communityAddress,
|
||||
parentCid,
|
||||
postCid: postCid ?? parentCid,
|
||||
content,
|
||||
@@ -77,7 +76,17 @@ const usePublishReply = ({ cid, communityAddress: requestedCommunityAddress, sub
|
||||
{} as Partial<Comment>,
|
||||
);
|
||||
|
||||
const newOptions = { ...baseOptions, ...sanitizedOptions };
|
||||
const {
|
||||
communityAddress: nextCommunityAddress,
|
||||
subplebbitAddress: legacyCommunityAddress,
|
||||
...restOptions
|
||||
} = sanitizedOptions as Partial<Comment> & { subplebbitAddress?: string };
|
||||
const resolvedCommunityAddress = nextCommunityAddress ?? legacyCommunityAddress ?? baseOptions.communityAddress;
|
||||
const newOptions = {
|
||||
...baseOptions,
|
||||
...restOptions,
|
||||
...(resolvedCommunityAddress ? { communityAddress: resolvedCommunityAddress } : {}),
|
||||
};
|
||||
setPublishReplyStore(newOptions);
|
||||
},
|
||||
[createBaseOptions, setPublishReplyStore],
|
||||
|
||||
@@ -7,6 +7,8 @@ describe('buildEditableAccountJson', () => {
|
||||
id: 'abc',
|
||||
name: 'Account 1',
|
||||
author: { address: '0x123', shortAddress: '0x1...3', avatar: { url: 'https://example.com' } },
|
||||
pkc: { someOption: true },
|
||||
pkcReactOptions: { foo: 'baz' },
|
||||
plebbit: { someOption: true },
|
||||
karma: 42,
|
||||
plebbitReactOptions: { foo: 'bar' },
|
||||
@@ -17,6 +19,8 @@ describe('buildEditableAccountJson', () => {
|
||||
expect(result.account.name).toBe('Account 1');
|
||||
expect(result.account.author.address).toBe('0x123');
|
||||
expect(result.account.author.avatar).toBeUndefined();
|
||||
expect(result.account.pkc).toBeUndefined();
|
||||
expect(result.account.pkcReactOptions).toBeUndefined();
|
||||
expect(result.account.plebbit).toBeUndefined();
|
||||
expect(result.account.karma).toBeUndefined();
|
||||
expect(result.account.plebbitReactOptions).toBeUndefined();
|
||||
|
||||
@@ -50,6 +50,18 @@ describe('challenge-utils', () => {
|
||||
expect(alertMock).toHaveBeenCalledWith('Error from unknown-board.eth: first error second error');
|
||||
});
|
||||
|
||||
it('uses communityAddress when the upgraded publication no longer exposes subplebbitAddress', () => {
|
||||
alertChallengeVerificationFailed(
|
||||
{
|
||||
challengeErrors: ['first error'],
|
||||
challengeSuccess: false,
|
||||
} as never,
|
||||
{ communityAddress: 'business-and-finance.bso' },
|
||||
);
|
||||
|
||||
expect(alertMock).toHaveBeenCalledWith('Error from /biz/: first error');
|
||||
});
|
||||
|
||||
it('warns about invalid challenge error payloads and falls back to an unknown error', () => {
|
||||
alertChallengeVerificationFailed(
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@ type AccountLike = {
|
||||
id?: string;
|
||||
name?: string;
|
||||
author?: { address?: string; shortAddress?: string; avatar?: unknown };
|
||||
pkc?: unknown;
|
||||
pkcReactOptions?: unknown;
|
||||
plebbit?: unknown;
|
||||
karma?: unknown;
|
||||
plebbitReactOptions?: unknown;
|
||||
@@ -19,6 +21,8 @@ export const buildEditableAccountJson = (account: AccountLike | undefined): stri
|
||||
account: {
|
||||
...account,
|
||||
author: { ...account?.author, avatar: undefined },
|
||||
pkc: undefined,
|
||||
pkcReactOptions: undefined,
|
||||
plebbit: undefined,
|
||||
karma: undefined,
|
||||
plebbitReactOptions: undefined,
|
||||
|
||||
@@ -2,13 +2,13 @@ import { ChallengeVerification } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import directoriesData from '../../data/5chan-directories.json';
|
||||
import { getBoardPath } from './route-utils';
|
||||
|
||||
const resolveBoardIdentifier = (subplebbitAddress: unknown): string => {
|
||||
if (typeof subplebbitAddress !== 'string' || !subplebbitAddress) {
|
||||
const resolveBoardIdentifier = (communityAddress: unknown): string => {
|
||||
if (typeof communityAddress !== 'string' || !communityAddress) {
|
||||
return 'unknown board';
|
||||
}
|
||||
|
||||
const boardPath = getBoardPath(subplebbitAddress, directoriesData.communities);
|
||||
return boardPath === subplebbitAddress ? subplebbitAddress : `/${boardPath}/`;
|
||||
const boardPath = getBoardPath(communityAddress, directoriesData.communities);
|
||||
return boardPath === communityAddress ? communityAddress : `/${boardPath}/`;
|
||||
};
|
||||
|
||||
export const alertChallengeVerificationFailed = (challengeVerification: ChallengeVerification, publication: any) => {
|
||||
@@ -35,8 +35,9 @@ export const alertChallengeVerificationFailed = (challengeVerification: Challeng
|
||||
}
|
||||
|
||||
const finalMessage = errorMessages.filter(Boolean).join(' ');
|
||||
const publicationCommunityAddress = publication?.communityAddress || publication?.subplebbitAddress;
|
||||
|
||||
alert(`Error from ${resolveBoardIdentifier(publication?.subplebbitAddress)}: ${finalMessage || 'unknown error'}`);
|
||||
alert(`Error from ${resolveBoardIdentifier(publicationCommunityAddress)}: ${finalMessage || 'unknown error'}`);
|
||||
} else {
|
||||
console.log('Challenge verification succeeded:', challengeVerification);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('publish stores', () => {
|
||||
expect(state.displayName).toBe('Poster Alias');
|
||||
expect(state.author).toEqual({ address: '0x123', role: 'mod', displayName: 'Poster Alias' });
|
||||
expect(state.publishCommentOptions.author).toEqual({ address: '0x123', role: 'mod', displayName: 'Poster Alias' });
|
||||
expect(state.publishCommentOptions.subplebbitAddress).toBe('music-posting.eth');
|
||||
expect(state.publishCommentOptions.communityAddress).toBe('music-posting.eth');
|
||||
expect(state.publishCommentOptions.title).toBe('Hello');
|
||||
|
||||
state.publishCommentOptions.onChallengeVerification?.({} as never, comment);
|
||||
@@ -82,6 +82,7 @@ describe('publish stores', () => {
|
||||
const state = usePublishReplyStore.getState();
|
||||
expect(state.displayName['parent-1']).toBe('Reply Alias');
|
||||
expect(state.author['parent-1']).toEqual({ address: '0x123', role: 'mod', displayName: 'Reply Alias' });
|
||||
expect(state.publishCommentOptions['parent-1']?.communityAddress).toBe('music-posting.eth');
|
||||
expect(state.publishCommentOptions['parent-1']?.parentCid).toBe('parent-1');
|
||||
expect(state.publishCommentOptions['parent-1']?.postCid).toBe('parent-1');
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ const usePublishPostStore = create<SubmitState>((set) => ({
|
||||
|
||||
const publishCommentOptions: PublishCommentOptions = {
|
||||
communityAddress,
|
||||
subplebbitAddress: communityAddress,
|
||||
title,
|
||||
content,
|
||||
link,
|
||||
|
||||
@@ -35,7 +35,6 @@ const usePublishReplyStore = create<ReplyState>((set) => ({
|
||||
|
||||
const publishCommentOptions: PublishCommentOptions = {
|
||||
communityAddress,
|
||||
subplebbitAddress: communityAddress,
|
||||
parentCid,
|
||||
postCid: comment?.postCid || parentCid,
|
||||
content,
|
||||
|
||||
@@ -71,6 +71,8 @@ vi.mock('react-ace', async () => {
|
||||
|
||||
vi.mock('ace-builds/src-noconflict/mode-json', () => ({}));
|
||||
vi.mock('ace-builds/src-noconflict/theme-monokai', () => ({}));
|
||||
vi.mock('ace-builds/esm-resolver', () => ({}));
|
||||
vi.mock('ace-builds/src-noconflict/worker-json?url', () => ({ default: '/worker-json.js' }));
|
||||
|
||||
let root: Root;
|
||||
let container: HTMLDivElement;
|
||||
|
||||
@@ -7,12 +7,29 @@ import styles from './account-data-editor.module.css';
|
||||
|
||||
const DEFAULT_RETURN_TO = '/subs/settings#account-settings';
|
||||
|
||||
type AceModuleLoadResult = {
|
||||
Editor: React.ComponentType<any>;
|
||||
onBeforeLoad: (ace: { config?: { setModuleUrl?: (name: string, value: string) => void } }) => void;
|
||||
};
|
||||
|
||||
const loadAce = async () => {
|
||||
const aceModule = await import('react-ace');
|
||||
await Promise.all([import('ace-builds/src-noconflict/mode-json'), import('ace-builds/src-noconflict/theme-monokai')]);
|
||||
const [aceModule, workerJsonModule] = await Promise.all([
|
||||
import('react-ace'),
|
||||
import('ace-builds/src-noconflict/worker-json?url'),
|
||||
import('ace-builds/esm-resolver'),
|
||||
import('ace-builds/src-noconflict/mode-json'),
|
||||
import('ace-builds/src-noconflict/theme-monokai'),
|
||||
]);
|
||||
// Vite CJS interop can double-wrap the default export
|
||||
const mod = aceModule.default;
|
||||
return typeof mod === 'function' ? mod : (mod as unknown as { default: typeof mod }).default;
|
||||
const Editor = typeof mod === 'function' ? mod : (mod as unknown as { default: typeof mod }).default;
|
||||
|
||||
return {
|
||||
Editor,
|
||||
onBeforeLoad: (ace) => {
|
||||
ace.config?.setModuleUrl?.('ace/mode/json_worker', workerJsonModule.default);
|
||||
},
|
||||
} satisfies AceModuleLoadResult;
|
||||
};
|
||||
|
||||
const AccountDataEditor = () => {
|
||||
@@ -25,17 +42,20 @@ const AccountDataEditor = () => {
|
||||
const [phase, setPhase] = useState<'warning' | 'loading' | 'editor' | 'fallback'>('warning');
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const [AceEditor, setAceEditor] = useState<React.ComponentType<any> | null>(null);
|
||||
const [aceOnBeforeLoad, setAceOnBeforeLoad] = useState<AceModuleLoadResult['onBeforeLoad'] | undefined>(undefined);
|
||||
const [text, setText] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (phase !== 'loading') return;
|
||||
loadAce()
|
||||
.then((Editor) => {
|
||||
.then(({ Editor, onBeforeLoad }) => {
|
||||
setAceEditor(() => Editor);
|
||||
setAceOnBeforeLoad(() => onBeforeLoad);
|
||||
setText(buildEditableAccountJson(account));
|
||||
setPhase('editor');
|
||||
})
|
||||
.catch(() => {
|
||||
setAceOnBeforeLoad(undefined);
|
||||
setText(buildEditableAccountJson(account));
|
||||
setPhase('fallback');
|
||||
});
|
||||
@@ -94,7 +114,17 @@ const AccountDataEditor = () => {
|
||||
{phase === 'fallback' && <div className={styles.fallbackWarning}>{t('editor_fallback_warning')}</div>}
|
||||
<div className={styles.editorContainer}>
|
||||
{phase === 'editor' && AceEditor ? (
|
||||
<AceEditor mode='json' theme='monokai' width='100%' height='500px' fontSize={13} showPrintMargin={false} value={text} onChange={setText} />
|
||||
<AceEditor
|
||||
mode='json'
|
||||
theme='monokai'
|
||||
width='100%'
|
||||
height='500px'
|
||||
fontSize={13}
|
||||
showPrintMargin={false}
|
||||
value={text}
|
||||
onChange={setText}
|
||||
onBeforeLoad={aceOnBeforeLoad}
|
||||
/>
|
||||
) : (
|
||||
<textarea
|
||||
value={text}
|
||||
|
||||
Reference in New Issue
Block a user