diff --git a/package.json b/package.json index 22adae5c..ab08902d 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "license": "GPL-2.0-only", "private": true, "dependencies": { - "@bitsocialnet/bitsocial-react-hooks": "https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/d609b67dea7e518f7931d3a69fa75e4e86591d37", + "@bitsocialnet/bitsocial-react-hooks": "https://codeload.github.com/bitsocialnet/bitsocial-react-hooks/tar.gz/95b46a8350ed5a2f96721f0dc14f2aaf26d410bf", "@capacitor/app": "7.0.1", "@capacitor/status-bar": "7.0.1", "@capawesome/capacitor-android-edge-to-edge-support": "7.2.2", diff --git a/scripts/patch-bitsocial-react-hooks-esm.cjs b/scripts/patch-bitsocial-react-hooks-esm.cjs index 617b3a20..61f28f42 100644 --- a/scripts/patch-bitsocial-react-hooks-esm.cjs +++ b/scripts/patch-bitsocial-react-hooks-esm.cjs @@ -5,6 +5,7 @@ const path = require('path'); const packageDistPath = path.join(__dirname, '..', 'node_modules', '@bitsocialnet', 'bitsocial-react-hooks', 'dist'); const logPrefix = '[patch-bitsocial-react-hooks-esm]'; +const packageIndexPath = path.join(packageDistPath, 'index.js'); if (!fs.existsSync(packageDistPath)) { console.log(`${logPrefix} Skip: @bitsocialnet/bitsocial-react-hooks dist not found.`); @@ -14,6 +15,10 @@ if (!fs.existsSync(packageDistPath)) { const relativeImportPattern = /(from\s+|import\s+)(['"])(\.\.?\/[^'"]+)\2/g; let touchedFiles = 0; let rewrittenImports = 0; +let removedNodeDebugPatches = 0; + +const nodeDebugPatchPattern = + /\/\/ fix DEBUG_DEPTH bug https:\/\/github\.com\/debug-js\/debug\/issues\/746\s*try\s*\{\s*if \(process\.env\.DEBUG_DEPTH\) \{\s*require\("util"\)\.inspect\.defaultOptions\.depth = process\.env\.DEBUG_DEPTH;\s*\}\s*if \(process\.env\.DEBUG_ARRAY\) \{\s*require\("util"\)\.inspect\.defaultOptions\.maxArrayLength = process\.env\.DEBUG_ARRAY;\s*\}\s*\}\s*catch \(e\) \{ \}/m; const splitSpecifier = (specifier) => { const suffixStart = specifier.search(/[?#]/); @@ -52,7 +57,7 @@ const patchFile = (filePath) => { const source = fs.readFileSync(filePath, 'utf8'); let fileImportCount = 0; - const updated = source.replace(relativeImportPattern, (match, prefix, quote, specifier) => { + let updated = source.replace(relativeImportPattern, (match, prefix, quote, specifier) => { const resolvedSpecifier = resolveSpecifier(filePath, specifier); if (!resolvedSpecifier || resolvedSpecifier === specifier) { @@ -63,7 +68,19 @@ const patchFile = (filePath) => { return `${prefix}${quote}${resolvedSpecifier}${quote}`; }); - if (!fileImportCount) { + if (filePath === packageIndexPath) { + const nextUpdated = updated.replace( + nodeDebugPatchPattern, + '// Browser bundle: skip Node-only util DEBUG_DEPTH/DEBUG_ARRAY tuning.\n', + ); + + if (nextUpdated !== updated) { + updated = nextUpdated; + removedNodeDebugPatches += 1; + } + } + + if (!fileImportCount && updated === source) { return; } @@ -94,4 +111,6 @@ if (!touchedFiles) { process.exit(0); } -console.log(`${logPrefix} Patched ${rewrittenImports} imports across ${touchedFiles} files.`); +console.log( + `${logPrefix} Patched ${rewrittenImports} imports across ${touchedFiles} files${removedNodeDebugPatches ? ` and removed ${removedNodeDebugPatches} browser-incompatible debug util block(s)` : ''}.`, +); diff --git a/src/components/settings-modal/advanced-settings/__tests__/advanced-settings.test.tsx b/src/components/settings-modal/advanced-settings/__tests__/advanced-settings.test.tsx index 5a0ac8dd..eb5400ea 100644 --- a/src/components/settings-modal/advanced-settings/__tests__/advanced-settings.test.tsx +++ b/src/components/settings-modal/advanced-settings/__tests__/advanced-settings.test.tsx @@ -9,20 +9,20 @@ const act = (React as { act?: (cb: () => void | Promise) => 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, 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; @@ -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', }, }, diff --git a/src/components/settings-modal/advanced-settings/advanced-settings.tsx b/src/components/settings-modal/advanced-settings/advanced-settings.tsx index ae833ade..0cc81647 100644 --- a/src/components/settings-modal/advanced-settings/advanced-settings.tsx +++ b/src/components/settings-modal/advanced-settings/advanced-settings.tsx @@ -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; } +type AccountProtocolOptions = { + chainProviders?: Record; + 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 (
@@ -69,18 +104,18 @@ const PubsubProvidersSettings = ({ pubsubProvidersRef }: SettingsProps) => { autoCapitalize='off' autoComplete='off' spellCheck='false' - rows={pubsubHttpClientsOptions?.length || 1} + rows={pubsubKuboRpcClientsOptions?.length || 1} />
); }; 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 (
@@ -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 (
- +
{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 (
@@ -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(null); const mediaIpfsGatewayUrlRef = useRef(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 = {}; @@ -238,13 +272,13 @@ const AdvancedSettings = () => { await setAccount({ ...account, mediaIpfsGatewayUrl, - plebbitOptions: { - ...plebbitOptions, + pkcOptions: { + ...protocolOptions, ipfsGatewayUrls, - pubsubHttpClientsOptions, + pubsubKuboRpcClientsOptions: pubsubHttpClientsOptions, chainProviders, httpRoutersOptions, - plebbitRpcClientsOptions, + pkcRpcClientsOptions, dataPath, }, }); diff --git a/src/hooks/__tests__/use-publish-post.test.tsx b/src/hooks/__tests__/use-publish-post.test.tsx index 0dc5d220..520efe75 100644 --- a/src/hooks/__tests__/use-publish-post.test.tsx +++ b/src/hooks/__tests__/use-publish-post.test.tsx @@ -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'); diff --git a/src/hooks/__tests__/use-publish-reply.test.tsx b/src/hooks/__tests__/use-publish-reply.test.tsx index 47783e97..fea99018 100644 --- a/src/hooks/__tests__/use-publish-reply.test.tsx +++ b/src/hooks/__tests__/use-publish-reply.test.tsx @@ -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', }); }); diff --git a/src/hooks/use-publish-post.ts b/src/hooks/use-publish-post.ts index 63e9cd92..d69528e6 100644 --- a/src/hooks/use-publish-post.ts +++ b/src/hooks/use-publish-post.ts @@ -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, ); - const newOptions = { ...baseOptions, ...sanitizedOptions }; + const { + communityAddress: nextCommunityAddress, + subplebbitAddress: legacyCommunityAddress, + ...restOptions + } = sanitizedOptions as Partial & { subplebbitAddress?: string }; + const resolvedCommunityAddress = nextCommunityAddress ?? legacyCommunityAddress ?? baseOptions.communityAddress; + const newOptions = { + ...baseOptions, + ...restOptions, + ...(resolvedCommunityAddress ? { communityAddress: resolvedCommunityAddress } : {}), + }; setPublishPostStore(newOptions); }, [createBaseOptions, setPublishPostStore], diff --git a/src/hooks/use-publish-reply.ts b/src/hooks/use-publish-reply.ts index a1fef78b..f0b42bf5 100644 --- a/src/hooks/use-publish-reply.ts +++ b/src/hooks/use-publish-reply.ts @@ -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, ); - const newOptions = { ...baseOptions, ...sanitizedOptions }; + const { + communityAddress: nextCommunityAddress, + subplebbitAddress: legacyCommunityAddress, + ...restOptions + } = sanitizedOptions as Partial & { subplebbitAddress?: string }; + const resolvedCommunityAddress = nextCommunityAddress ?? legacyCommunityAddress ?? baseOptions.communityAddress; + const newOptions = { + ...baseOptions, + ...restOptions, + ...(resolvedCommunityAddress ? { communityAddress: resolvedCommunityAddress } : {}), + }; setPublishReplyStore(newOptions); }, [createBaseOptions, setPublishReplyStore], diff --git a/src/lib/utils/__tests__/account-editor-utils.test.ts b/src/lib/utils/__tests__/account-editor-utils.test.ts index 69605ef2..48c9f325 100644 --- a/src/lib/utils/__tests__/account-editor-utils.test.ts +++ b/src/lib/utils/__tests__/account-editor-utils.test.ts @@ -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(); diff --git a/src/lib/utils/__tests__/challenge-utils.test.ts b/src/lib/utils/__tests__/challenge-utils.test.ts index 1018b0bf..c18ce1a1 100644 --- a/src/lib/utils/__tests__/challenge-utils.test.ts +++ b/src/lib/utils/__tests__/challenge-utils.test.ts @@ -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( { diff --git a/src/lib/utils/account-editor-utils.ts b/src/lib/utils/account-editor-utils.ts index d6fbf4ac..2ad07ae1 100644 --- a/src/lib/utils/account-editor-utils.ts +++ b/src/lib/utils/account-editor-utils.ts @@ -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, diff --git a/src/lib/utils/challenge-utils.ts b/src/lib/utils/challenge-utils.ts index 3065ab1d..9a6e805a 100644 --- a/src/lib/utils/challenge-utils.ts +++ b/src/lib/utils/challenge-utils.ts @@ -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); } diff --git a/src/stores/__tests__/publish-stores.test.ts b/src/stores/__tests__/publish-stores.test.ts index 14149cd5..0a33cfaf 100644 --- a/src/stores/__tests__/publish-stores.test.ts +++ b/src/stores/__tests__/publish-stores.test.ts @@ -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'); diff --git a/src/stores/use-publish-post-store.ts b/src/stores/use-publish-post-store.ts index f226a1b9..fb23b10e 100644 --- a/src/stores/use-publish-post-store.ts +++ b/src/stores/use-publish-post-store.ts @@ -40,7 +40,6 @@ const usePublishPostStore = create((set) => ({ const publishCommentOptions: PublishCommentOptions = { communityAddress, - subplebbitAddress: communityAddress, title, content, link, diff --git a/src/stores/use-publish-reply-store.ts b/src/stores/use-publish-reply-store.ts index 03ae0f54..f72ddbd9 100644 --- a/src/stores/use-publish-reply-store.ts +++ b/src/stores/use-publish-reply-store.ts @@ -35,7 +35,6 @@ const usePublishReplyStore = create((set) => ({ const publishCommentOptions: PublishCommentOptions = { communityAddress, - subplebbitAddress: communityAddress, parentCid, postCid: comment?.postCid || parentCid, content, diff --git a/src/views/account-data-editor/__tests__/account-data-editor.test.tsx b/src/views/account-data-editor/__tests__/account-data-editor.test.tsx index bc910e28..78bb4857 100644 --- a/src/views/account-data-editor/__tests__/account-data-editor.test.tsx +++ b/src/views/account-data-editor/__tests__/account-data-editor.test.tsx @@ -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; diff --git a/src/views/account-data-editor/account-data-editor.tsx b/src/views/account-data-editor/account-data-editor.tsx index 96782b81..18c9fe0d 100644 --- a/src/views/account-data-editor/account-data-editor.tsx +++ b/src/views/account-data-editor/account-data-editor.tsx @@ -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; + 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 | null>(null); + const [aceOnBeforeLoad, setAceOnBeforeLoad] = useState(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' &&
{t('editor_fallback_warning')}
}
{phase === 'editor' && AceEditor ? ( - + ) : (