From 4508f589dd12c076142455f0d36cd09ab9582159 Mon Sep 17 00:00:00 2001 From: plebeius Date: Thu, 5 Mar 2026 17:14:23 +0800 Subject: [PATCH 01/19] chore(deps): migrate from pkc-react-hooks to bitsocial-react-hooks --- AGENTS.md | 4 +- package.json | 2 +- src/app.tsx | 4 +- .../board-buttons/board-buttons.tsx | 2 +- src/components/board-header/board-header.tsx | 6 +- .../boards-bar-edit-modal.tsx | 2 +- src/components/boards-bar/boards-bar.tsx | 4 +- src/components/catalog-row/catalog-row.tsx | 2 +- .../challenge-modal/challenge-modal.tsx | 2 +- .../comment-content/comment-content.tsx | 4 +- src/components/edit-menu/edit-menu.tsx | 2 +- src/components/footer/footer.tsx | 2 +- src/components/markdown/markdown.tsx | 4 +- src/components/post-desktop/post-desktop.tsx | 4 +- src/components/post-form/post-form.tsx | 6 +- .../post-menu-mobile/post-menu-mobile.tsx | 2 +- src/components/post-mobile/post-mobile.tsx | 2 +- src/components/reply-modal/reply-modal.tsx | 2 +- .../reply-quote-preview.tsx | 2 +- .../__tests__/account-settings.test.tsx | 2 +- .../account-settings/account-settings.tsx | 2 +- .../advanced-settings/advanced-settings.tsx | 2 +- .../crypto-address-setting.tsx | 2 +- .../crypto-wallets-setting.tsx | 2 +- .../subscriptions-setting.tsx | 2 +- .../use-account-subplebbits-with-metadata.ts | 2 +- src/hooks/use-author-privileges.ts | 2 +- src/hooks/use-catalog-feed-rows.ts | 2 +- src/hooks/use-count-links-in-replies.ts | 4 +- src/hooks/use-fetch-gif-first-frame.ts | 2 +- src/hooks/use-hide.ts | 2 +- src/hooks/use-is-subplebbit-offline.ts | 2 +- src/hooks/use-popular-posts.ts | 2 +- src/hooks/use-post-page-number.ts | 4 +- src/hooks/use-publish-post.ts | 2 +- src/hooks/use-publish-reply.ts | 2 +- src/hooks/use-quoted-by-map.ts | 2 +- src/hooks/use-stable-subplebbit.ts | 2 +- src/hooks/use-state-string.ts | 2 +- src/hooks/use-subplebbits-stats.ts | 2 +- src/hooks/use-theme.ts | 2 +- src/lib/utils/challenge-utils.ts | 2 +- src/lib/utils/media-utils.ts | 2 +- src/lib/utils/pattern-utils.ts | 4 +- src/lib/utils/post-menu-props.ts | 2 +- src/stores/use-catalog-filters-store.ts | 2 +- src/stores/use-challenges-store.ts | 2 +- src/stores/use-post-number-store.ts | 2 +- src/stores/use-publish-post-store.ts | 2 +- src/stores/use-publish-reply-store.ts | 2 +- src/stores/use-theme-store.ts | 2 +- .../__tests__/account-data-editor.test.tsx | 2 +- .../account-data-editor.tsx | 2 +- src/views/board/board.tsx | 2 +- src/views/catalog/catalog.tsx | 2 +- src/views/home/boards-list/boards-list.tsx | 2 +- src/views/home/home.tsx | 2 +- .../popular-threads-box.tsx | 2 +- src/views/mod-queue/mod-queue.tsx | 4 +- src/views/pending-post/pending-post.tsx | 2 +- src/views/post/post.tsx | 4 +- src/views/rules/rules.tsx | 2 +- vite.config.js | 4 +- yarn.lock | 553 +++++------------- 64 files changed, 219 insertions(+), 492 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 00144d95..0105abc6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,7 +42,7 @@ Only record items that are repo-specific, likely to recur, and have a concrete m - Zustand for shared state - React Router v6 - Vite -- pkc-react-hooks +- bitsocial-react-hooks - i18next - yarn - oxlint @@ -72,7 +72,7 @@ src/ ### React Architecture Rules - Do not use `useState` for shared/global state. Use Zustand stores in `src/stores/`. -- Do not use `useEffect` for data fetching. Use `pkc-react-hooks`. +- Do not use `useEffect` for data fetching. Use `bitsocial-react-hooks`. - Do not sync derived state with effects. Compute during render. - Avoid copy-paste logic across components. Extract custom hooks in `src/hooks/`. - Avoid boolean flag soup for complex flows; model state clearly in Zustand. diff --git a/package.json b/package.json index 89ae6986..f208db51 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "GPL-2.0-only", "private": true, "dependencies": { - "@bitsocialhq/pkc-react-hooks": "https://github.com/bitsocialhq/pkc-react-hooks.git#00743c41a0cbbb88d29dccf21f45b69c16b8850c", + "@bitsocialhq/bitsocial-react-hooks": "https://github.com/bitsocialhq/bitsocial-react-hooks.git#6dc27da29debfb9c0144b445132bae4cfd975c4f", "@capacitor/app": "7.0.1", "@capacitor/status-bar": "7.0.1", "@capawesome/capacitor-android-edge-to-edge-support": "7.2.2", diff --git a/src/app.tsx b/src/app.tsx index 32548a2e..36ad94b7 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,7 +1,7 @@ import { lazy, Suspense, useEffect } from 'react'; import { Navigate, Outlet, Route, Routes, useLocation, useParams } from 'react-router-dom'; -import { useAccount, useAccountComment, useSubplebbit } from '@bitsocialhq/pkc-react-hooks'; -import useAccountsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/accounts'; +import { useAccount, useAccountComment, useSubplebbit } from '@bitsocialhq/bitsocial-react-hooks'; +import useAccountsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/accounts'; import { initSnow, removeSnow } from './lib/snow'; import { isAllView, isCatalogView, isModView, isSubscriptionsView } from './lib/utils/view-utils'; import { preloadThemeAssets } from './lib/utils/preload-utils'; diff --git a/src/components/board-buttons/board-buttons.tsx b/src/components/board-buttons/board-buttons.tsx index 19787c35..637545aa 100644 --- a/src/components/board-buttons/board-buttons.tsx +++ b/src/components/board-buttons/board-buttons.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'; -import { useAccountComment, useComment, useSubscribe } from '@bitsocialhq/pkc-react-hooks'; +import { useAccountComment, useComment, useSubscribe } from '@bitsocialhq/bitsocial-react-hooks'; import { isAllView, isCatalogView, isModView, isModQueueView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils'; import { usePostPageNumber } from '../../hooks/use-post-page-number'; import { useDirectories, useDirectoryByAddress } from '../../hooks/use-directories'; diff --git a/src/components/board-header/board-header.tsx b/src/components/board-header/board-header.tsx index 6ac46f01..028253a8 100644 --- a/src/components/board-header/board-header.tsx +++ b/src/components/board-header/board-header.tsx @@ -1,9 +1,9 @@ import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useParams, useNavigate } from 'react-router-dom'; -import { useAccountComment } from '@bitsocialhq/pkc-react-hooks'; -import useAccountsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/accounts'; -import useSubplebbitsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits'; +import { useAccountComment } from '@bitsocialhq/bitsocial-react-hooks'; +import useAccountsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/accounts'; +import useSubplebbitsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/subplebbits'; import getShortAddress from '../../lib/get-short-address'; import { useStableSubplebbit } from '../../hooks/use-stable-subplebbit'; import { isAllView, isSubscriptionsView, isModView } from '../../lib/utils/view-utils'; diff --git a/src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx b/src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx index ca0c2e59..7eac7048 100644 --- a/src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx +++ b/src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx @@ -1,6 +1,6 @@ import { useState, useMemo } from 'react'; import { Link, useLocation } from 'react-router-dom'; -import { useAccount } from '@bitsocialhq/pkc-react-hooks'; +import { useAccount } from '@bitsocialhq/bitsocial-react-hooks'; import useBoardsBarEditModalStore from '../../stores/use-boards-bar-edit-modal-store'; import useBoardsBarVisibilityStore from '../../stores/use-boards-bar-visibility-store'; import { getAllBoardCodes } from '../../constants/board-codes'; diff --git a/src/components/boards-bar/boards-bar.tsx b/src/components/boards-bar/boards-bar.tsx index 7bc706db..c8ad13cd 100644 --- a/src/components/boards-bar/boards-bar.tsx +++ b/src/components/boards-bar/boards-bar.tsx @@ -2,8 +2,8 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import getShortAddress from '../../lib/get-short-address'; -import { useAccountComment } from '@bitsocialhq/pkc-react-hooks'; -import useAccountsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/accounts'; +import { useAccountComment } from '@bitsocialhq/bitsocial-react-hooks'; +import useAccountsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/accounts'; import { isAllView, isCatalogView, isModView, isSubscriptionsView } from '../../lib/utils/view-utils'; import { useDirectories, useDirectoriesMetadata, DirectoryCommunity } from '../../hooks/use-directories'; import { useBoardPath, useResolvedSubplebbitAddress } from '../../hooks/use-resolved-subplebbit-address'; diff --git a/src/components/catalog-row/catalog-row.tsx b/src/components/catalog-row/catalog-row.tsx index 4012d192..3492a6b7 100644 --- a/src/components/catalog-row/catalog-row.tsx +++ b/src/components/catalog-row/catalog-row.tsx @@ -3,7 +3,7 @@ import { createPortal } from 'react-dom'; import { useTranslation } from 'react-i18next'; import { Link, useLocation, useParams } from 'react-router-dom'; import { useFloating, offset, size, Placement } from '@floating-ui/react'; -import { Comment, useReplies } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, useReplies } from '@bitsocialhq/bitsocial-react-hooks'; import getShortAddress from '../../lib/get-short-address'; import { shouldShowSnow } from '../../lib/snow'; import { getHasThumbnail } from '../../lib/utils/media-utils'; diff --git a/src/components/challenge-modal/challenge-modal.tsx b/src/components/challenge-modal/challenge-modal.tsx index 3ba93b8c..1acd1d50 100644 --- a/src/components/challenge-modal/challenge-modal.tsx +++ b/src/components/challenge-modal/challenge-modal.tsx @@ -1,6 +1,6 @@ import { useRef, useState, useEffect, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { Challenge as ChallengeType, useAccount, useComment } from '@bitsocialhq/pkc-react-hooks'; +import { Challenge as ChallengeType, useAccount, useComment } from '@bitsocialhq/bitsocial-react-hooks'; import { getPublicationPreview, getPublicationType, getVotePreview } from '../../lib/utils/challenge-utils'; import useIsMobile from '../../hooks/use-is-mobile'; import useChallengesStore from '../../stores/use-challenges-store'; diff --git a/src/components/comment-content/comment-content.tsx b/src/components/comment-content/comment-content.tsx index 760d3245..d8c00dd5 100644 --- a/src/components/comment-content/comment-content.tsx +++ b/src/components/comment-content/comment-content.tsx @@ -1,8 +1,8 @@ import { Fragment, useMemo, useState } from 'react'; import { useLocation, useParams } from 'react-router-dom'; import { Trans, useTranslation } from 'react-i18next'; -import { Comment, useComment } from '@bitsocialhq/pkc-react-hooks'; -import useSubplebbitsPagesStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits-pages'; +import { Comment, useComment } from '@bitsocialhq/bitsocial-react-hooks'; +import useSubplebbitsPagesStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/subplebbits-pages'; import usePostNumberStore from '../../stores/use-post-number-store'; import getShortAddress from '../../lib/get-short-address'; import { getFormattedDate, getFormattedTimeAgo } from '../../lib/utils/time-utils'; diff --git a/src/components/edit-menu/edit-menu.tsx b/src/components/edit-menu/edit-menu.tsx index 27e9045e..77d99966 100644 --- a/src/components/edit-menu/edit-menu.tsx +++ b/src/components/edit-menu/edit-menu.tsx @@ -8,7 +8,7 @@ import { usePublishCommentEdit, usePublishCommentModeration, PublishCommentModerationOptions, -} from '@bitsocialhq/pkc-react-hooks'; +} from '@bitsocialhq/bitsocial-react-hooks'; import styles from './edit-menu.module.css'; import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils'; import useChallengesStore from '../../stores/use-challenges-store'; diff --git a/src/components/footer/footer.tsx b/src/components/footer/footer.tsx index 7d66c17f..466831b0 100644 --- a/src/components/footer/footer.tsx +++ b/src/components/footer/footer.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; import { useLocation, useParams } from 'react-router-dom'; -import { useComment } from '@bitsocialhq/pkc-react-hooks'; +import { useComment } from '@bitsocialhq/bitsocial-react-hooks'; import BoardsBar from '../boards-bar'; import SiteLegalMeta from '../site-legal-meta'; import StyleSelector from '../style-selector/style-selector'; diff --git a/src/components/markdown/markdown.tsx b/src/components/markdown/markdown.tsx index 809563d1..0beac50a 100644 --- a/src/components/markdown/markdown.tsx +++ b/src/components/markdown/markdown.tsx @@ -11,8 +11,8 @@ import { Link, useLocation, useParams } from 'react-router-dom'; import { canEmbed } from '../embed'; import { is5chanLink, transform5chanLinkToInternal, isValidCrossboardPattern } from '../../lib/utils/url-utils'; import usePostNumberStore from '../../stores/use-post-number-store'; -import useSubplebbitsPagesStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits-pages'; -import { useComment } from '@bitsocialhq/pkc-react-hooks'; +import useSubplebbitsPagesStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/subplebbits-pages'; +import { useComment } from '@bitsocialhq/bitsocial-react-hooks'; import ReplyQuotePreview from '../reply-quote-preview'; const safeParseUrl = (href: string): URL | null => { diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index 2169aafe..ca719ea7 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef, useState, useCallback } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { Link, useLocation, useNavigationType, useParams } from 'react-router-dom'; import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso'; -import { Comment, useEditedComment, useReplies, useAccount, useAccountComment } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, useEditedComment, useReplies, useAccount, useAccountComment } from '@bitsocialhq/bitsocial-react-hooks'; import getShortAddress from '../../lib/get-short-address'; import styles from '../../views/post/post.module.css'; import { CommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail, getMediaDimensions } from '../../lib/utils/media-utils'; @@ -42,7 +42,7 @@ import useChallengesStore from '../../stores/use-challenges-store'; import useFeedResetStore from '../../stores/use-feed-reset-store'; import usePostNumberStore from '../../stores/use-post-number-store'; import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils'; -import { usePublishCommentModeration } from '@bitsocialhq/pkc-react-hooks'; +import { usePublishCommentModeration } from '@bitsocialhq/bitsocial-react-hooks'; import useQuotedByMap from '../../hooks/use-quoted-by-map'; import useProgressiveRender from '../../hooks/use-progressive-render'; import { BOARD_REPLIES_PREVIEW_FETCH_SIZE, BOARD_REPLIES_PREVIEW_VISIBLE_COUNT, REPLIES_PER_PAGE } from '../../lib/constants'; diff --git a/src/components/post-form/post-form.tsx b/src/components/post-form/post-form.tsx index 4dea216f..e93d859f 100644 --- a/src/components/post-form/post-form.tsx +++ b/src/components/post-form/post-form.tsx @@ -1,10 +1,10 @@ import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate, useParams } from 'react-router-dom'; -import { Comment, setAccount, useAccount, useAccountComment, useAccountSubplebbits, useEditedComment } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, setAccount, useAccount, useAccountComment, useAccountSubplebbits, useEditedComment } from '@bitsocialhq/bitsocial-react-hooks'; import getShortAddress from '../../lib/get-short-address'; -import useSubplebbitsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits'; -import useSubplebbitsPagesStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits-pages'; +import useSubplebbitsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/subplebbits'; +import useSubplebbitsPagesStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/subplebbits-pages'; import { getLinkMediaInfo } from '../../lib/utils/media-utils'; import { isValidURL } from '../../lib/utils/url-utils'; import { isAllView, isCatalogView, isModQueueView, isModView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils'; diff --git a/src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx b/src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx index 84a92060..ee232b4e 100644 --- a/src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx +++ b/src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx @@ -1,7 +1,7 @@ import { memo, useState } from 'react'; import { createPortal } from 'react-dom'; import { useTranslation } from 'react-i18next'; -import { Comment } from '@bitsocialhq/pkc-react-hooks'; +import { Comment } from '@bitsocialhq/bitsocial-react-hooks'; import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react'; import styles from './post-menu-mobile.module.css'; import { getCommentMediaInfo } from '../../../lib/utils/media-utils'; diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index ca439c8d..8b56e23f 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef, useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { Link, useLocation, useNavigationType, useParams } from 'react-router-dom'; import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso'; -import { Comment, useEditedComment, useReplies, useAccount, usePublishCommentModeration, useAccountComment } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, useEditedComment, useReplies, useAccount, usePublishCommentModeration, useAccountComment } from '@bitsocialhq/bitsocial-react-hooks'; import getShortAddress from '../../lib/get-short-address'; import styles from '../../views/post/post.module.css'; import { shouldShowSnow } from '../../lib/snow'; diff --git a/src/components/reply-modal/reply-modal.tsx b/src/components/reply-modal/reply-modal.tsx index 3a0ca880..3c462698 100644 --- a/src/components/reply-modal/reply-modal.tsx +++ b/src/components/reply-modal/reply-modal.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef, useState } from 'react'; import { useLocation, useParams } from 'react-router-dom'; import { Trans, useTranslation } from 'react-i18next'; -import { setAccount, useAccount } from '@bitsocialhq/pkc-react-hooks'; +import { setAccount, useAccount } from '@bitsocialhq/bitsocial-react-hooks'; import { useSubplebbitField } from '../../hooks/use-stable-subplebbit'; import { getFormattedTimeAgo } from '../../lib/utils/time-utils'; import { isValidURL } from '../../lib/utils/url-utils'; diff --git a/src/components/reply-quote-preview/reply-quote-preview.tsx b/src/components/reply-quote-preview/reply-quote-preview.tsx index 7567b413..534d2a39 100644 --- a/src/components/reply-quote-preview/reply-quote-preview.tsx +++ b/src/components/reply-quote-preview/reply-quote-preview.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { Link, useLocation, useNavigate } from 'react-router-dom'; -import { Comment, useAccount } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, useAccount } from '@bitsocialhq/bitsocial-react-hooks'; import { useFloating, offset, shift, size, autoUpdate, Placement } from '@floating-ui/react'; import { useDirectories } from '../../hooks/use-directories'; import { getBoardPath } from '../../lib/utils/route-utils'; diff --git a/src/components/settings-modal/account-settings/__tests__/account-settings.test.tsx b/src/components/settings-modal/account-settings/__tests__/account-settings.test.tsx index 9c14a4f9..0ae8e3e7 100644 --- a/src/components/settings-modal/account-settings/__tests__/account-settings.test.tsx +++ b/src/components/settings-modal/account-settings/__tests__/account-settings.test.tsx @@ -15,7 +15,7 @@ vi.mock('react-i18next', () => ({ }), })); -vi.mock('@bitsocialhq/pkc-react-hooks', () => ({ +vi.mock('@bitsocialhq/bitsocial-react-hooks', () => ({ useAccount: () => ({ id: 'test-id', name: 'Account 1', author: { address: '0x123', shortAddress: '0x1...3' } }), useAccounts: () => ({ accounts: [{ id: 'test-id', name: 'Account 1', author: { shortAddress: '0x1...3' } }] }), deleteAccount: vi.fn(), diff --git a/src/components/settings-modal/account-settings/account-settings.tsx b/src/components/settings-modal/account-settings/account-settings.tsx index 558443b1..2e63b4db 100644 --- a/src/components/settings-modal/account-settings/account-settings.tsx +++ b/src/components/settings-modal/account-settings/account-settings.tsx @@ -1,6 +1,6 @@ import { memo } from 'react'; import { useTranslation } from 'react-i18next'; -import { deleteAccount, exportAccount, importAccount, setActiveAccount, useAccount, useAccounts } from '@bitsocialhq/pkc-react-hooks'; +import { deleteAccount, exportAccount, importAccount, setActiveAccount, useAccount, useAccounts } from '@bitsocialhq/bitsocial-react-hooks'; import styles from './account-settings.module.css'; import { Capacitor } from '@capacitor/core'; import { useLocation, useNavigate } from 'react-router-dom'; diff --git a/src/components/settings-modal/advanced-settings/advanced-settings.tsx b/src/components/settings-modal/advanced-settings/advanced-settings.tsx index c225b6f0..70cac761 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 '@bitsocialhq/pkc-react-hooks'; +import { setAccount, useAccount, usePlebbitRpcSettings } from '@bitsocialhq/bitsocial-react-hooks'; import { useTranslation } from 'react-i18next'; import styles from './advanced-settings.module.css'; diff --git a/src/components/settings-modal/crypto-address-setting/crypto-address-setting.tsx b/src/components/settings-modal/crypto-address-setting/crypto-address-setting.tsx index c32b1a41..f95d540b 100644 --- a/src/components/settings-modal/crypto-address-setting/crypto-address-setting.tsx +++ b/src/components/settings-modal/crypto-address-setting/crypto-address-setting.tsx @@ -1,6 +1,6 @@ import { memo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useAccount, setAccount, useResolvedAuthorAddress } from '@bitsocialhq/pkc-react-hooks'; +import { useAccount, setAccount, useResolvedAuthorAddress } from '@bitsocialhq/bitsocial-react-hooks'; import styles from './crypto-address-setting.module.css'; const withErrorHandling = async (fn: () => Promise, onError: (e: unknown) => void): Promise => { diff --git a/src/components/settings-modal/crypto-wallets-setting/crypto-wallets-setting.tsx b/src/components/settings-modal/crypto-wallets-setting/crypto-wallets-setting.tsx index 5c9fbc52..835e740c 100644 --- a/src/components/settings-modal/crypto-wallets-setting/crypto-wallets-setting.tsx +++ b/src/components/settings-modal/crypto-wallets-setting/crypto-wallets-setting.tsx @@ -1,5 +1,5 @@ import { memo, useState } from 'react'; -import { Account, setAccount, useAccount } from '@bitsocialhq/pkc-react-hooks'; +import { Account, setAccount, useAccount } from '@bitsocialhq/bitsocial-react-hooks'; import styles from './crypto-wallets-setting.module.css'; import { Trans, useTranslation } from 'react-i18next'; import capitalize from 'lodash/capitalize'; diff --git a/src/components/settings-modal/subscriptions-setting/subscriptions-setting.tsx b/src/components/settings-modal/subscriptions-setting/subscriptions-setting.tsx index 399d6d4a..99b1122b 100644 --- a/src/components/settings-modal/subscriptions-setting/subscriptions-setting.tsx +++ b/src/components/settings-modal/subscriptions-setting/subscriptions-setting.tsx @@ -1,4 +1,4 @@ -import { setAccount, useAccount, useSubscribe } from '@bitsocialhq/pkc-react-hooks'; +import { setAccount, useAccount, useSubscribe } from '@bitsocialhq/bitsocial-react-hooks'; import getShortAddress from '../../../lib/get-short-address'; import styles from './subscriptions-setting.module.css'; import { useTranslation } from 'react-i18next'; diff --git a/src/hooks/use-account-subplebbits-with-metadata.ts b/src/hooks/use-account-subplebbits-with-metadata.ts index 24418edb..db1745e1 100644 --- a/src/hooks/use-account-subplebbits-with-metadata.ts +++ b/src/hooks/use-account-subplebbits-with-metadata.ts @@ -1,4 +1,4 @@ -import useAccountsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/accounts'; +import useAccountsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/accounts'; import { DirectoryCommunity } from './use-directories'; export const useAccountSubplebbitsWithMetadata = (): DirectoryCommunity[] => { diff --git a/src/hooks/use-author-privileges.ts b/src/hooks/use-author-privileges.ts index 930132ff..da374d14 100644 --- a/src/hooks/use-author-privileges.ts +++ b/src/hooks/use-author-privileges.ts @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import { useAccount } from '@bitsocialhq/pkc-react-hooks'; +import { useAccount } from '@bitsocialhq/bitsocial-react-hooks'; import { useSubplebbitField } from './use-stable-subplebbit'; interface AuthorPrivilegesProps { diff --git a/src/hooks/use-catalog-feed-rows.ts b/src/hooks/use-catalog-feed-rows.ts index 168de93b..72e75638 100644 --- a/src/hooks/use-catalog-feed-rows.ts +++ b/src/hooks/use-catalog-feed-rows.ts @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import { useAccountComments, Subplebbit } from '@bitsocialhq/pkc-react-hooks'; +import { useAccountComments, Subplebbit } from '@bitsocialhq/bitsocial-react-hooks'; const useCatalogFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolean, subplebbit: Subplebbit) => { const { address } = subplebbit || {}; diff --git a/src/hooks/use-count-links-in-replies.ts b/src/hooks/use-count-links-in-replies.ts index c212e9ae..300a9893 100644 --- a/src/hooks/use-count-links-in-replies.ts +++ b/src/hooks/use-count-links-in-replies.ts @@ -1,6 +1,6 @@ import { useMemo } from 'react'; -import { Comment } from '@bitsocialhq/pkc-react-hooks'; -import { flattenCommentsPages } from '@bitsocialhq/pkc-react-hooks/dist/lib/utils'; +import { Comment } from '@bitsocialhq/bitsocial-react-hooks'; +import { flattenCommentsPages } from '@bitsocialhq/bitsocial-react-hooks/dist/lib/utils'; const useCountLinksInReplies = (comment: Comment, firstXReplies?: number) => { let linkCount = 0; diff --git a/src/hooks/use-fetch-gif-first-frame.ts b/src/hooks/use-fetch-gif-first-frame.ts index c0a1c416..4b3d0272 100644 --- a/src/hooks/use-fetch-gif-first-frame.ts +++ b/src/hooks/use-fetch-gif-first-frame.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import localForageLru from '@bitsocialhq/pkc-react-hooks/dist/lib/localforage-lru/index.js'; +import localForageLru from '@bitsocialhq/bitsocial-react-hooks/dist/lib/localforage-lru/index.js'; const gifFrameDb = localForageLru.createInstance({ name: '5chanGifFrames', size: 500 }); const failedUrls = new Set(); diff --git a/src/hooks/use-hide.ts b/src/hooks/use-hide.ts index 510f424b..c188a6e8 100644 --- a/src/hooks/use-hide.ts +++ b/src/hooks/use-hide.ts @@ -1,6 +1,6 @@ import { useCallback, useMemo } from 'react'; import { create } from 'zustand'; -import localForageLru from '@bitsocialhq/pkc-react-hooks/dist/lib/localforage-lru/index.js'; +import localForageLru from '@bitsocialhq/bitsocial-react-hooks/dist/lib/localforage-lru/index.js'; interface HideStoreState { hiddenCids: { [key: string]: boolean }; diff --git a/src/hooks/use-is-subplebbit-offline.ts b/src/hooks/use-is-subplebbit-offline.ts index 20500c47..6ad5e252 100644 --- a/src/hooks/use-is-subplebbit-offline.ts +++ b/src/hooks/use-is-subplebbit-offline.ts @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; import { useEffect } from 'react'; -import { Subplebbit } from '@bitsocialhq/pkc-react-hooks'; +import { Subplebbit } from '@bitsocialhq/bitsocial-react-hooks'; import { getFormattedTimeAgo } from '../lib/utils/time-utils'; import useSubplebbitOfflineStore from '../stores/use-subplebbit-offline-store'; import useSubplebbitsLoadingStartTimestamps from '../stores/use-subplebbits-loading-start-timestamps-store'; diff --git a/src/hooks/use-popular-posts.ts b/src/hooks/use-popular-posts.ts index b9eeede3..496bd5c0 100644 --- a/src/hooks/use-popular-posts.ts +++ b/src/hooks/use-popular-posts.ts @@ -1,5 +1,5 @@ import { useMemo, useRef } from 'react'; -import { Comment, Subplebbit } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, Subplebbit } from '@bitsocialhq/bitsocial-react-hooks'; import { getCommentMediaInfo, getHasThumbnail } from '../lib/utils/media-utils'; const MAX_POSTS = 8; diff --git a/src/hooks/use-post-page-number.ts b/src/hooks/use-post-page-number.ts index d75aedaf..4c00c634 100644 --- a/src/hooks/use-post-page-number.ts +++ b/src/hooks/use-post-page-number.ts @@ -1,6 +1,6 @@ import { useMemo } from 'react'; -import { useFeed } from '@bitsocialhq/pkc-react-hooks'; -import useFeedsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/feeds'; +import { useFeed } from '@bitsocialhq/bitsocial-react-hooks'; +import useFeedsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/feeds'; import { useDirectoryByAddress } from './use-directories'; import { useBoardFeedPageSize } from './use-board-feed-page-size'; import { findPostPageInFeed, findPostPageInLoadedBoardFeeds, type FeedsOptionsLike, type LoadedFeedsLike } from '../lib/utils/post-page-resolution'; diff --git a/src/hooks/use-publish-post.ts b/src/hooks/use-publish-post.ts index d8bf5334..44bd1033 100644 --- a/src/hooks/use-publish-post.ts +++ b/src/hooks/use-publish-post.ts @@ -1,5 +1,5 @@ import { useCallback } from 'react'; -import { Comment, usePublishComment } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, usePublishComment } from '@bitsocialhq/bitsocial-react-hooks'; import usePublishPostStore from '../stores/use-publish-post-store'; const usePublishPost = ({ subplebbitAddress }: { subplebbitAddress?: string }) => { diff --git a/src/hooks/use-publish-reply.ts b/src/hooks/use-publish-reply.ts index 67ad852c..1b06ab53 100644 --- a/src/hooks/use-publish-reply.ts +++ b/src/hooks/use-publish-reply.ts @@ -1,5 +1,5 @@ import { useCallback, useMemo } from 'react'; -import { Comment, usePublishComment } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, usePublishComment } from '@bitsocialhq/bitsocial-react-hooks'; import usePublishReplyStore from '../stores/use-publish-reply-store'; import usePostNumberStore from '../stores/use-post-number-store'; import { getQuotedCidsFromContent, mergeQuotedCids } from '../lib/utils/reply-quote-utils'; diff --git a/src/hooks/use-quoted-by-map.ts b/src/hooks/use-quoted-by-map.ts index 9f568e89..324a810e 100644 --- a/src/hooks/use-quoted-by-map.ts +++ b/src/hooks/use-quoted-by-map.ts @@ -1,5 +1,5 @@ import { useCallback, useMemo, useRef } from 'react'; -import { Comment } from '@bitsocialhq/pkc-react-hooks'; +import { Comment } from '@bitsocialhq/bitsocial-react-hooks'; import { QUOTE_NUMBER_REGEX } from '../lib/utils/url-utils'; import usePostNumberStore from '../stores/use-post-number-store'; diff --git a/src/hooks/use-stable-subplebbit.ts b/src/hooks/use-stable-subplebbit.ts index 564b7f54..d2b498ac 100644 --- a/src/hooks/use-stable-subplebbit.ts +++ b/src/hooks/use-stable-subplebbit.ts @@ -1,4 +1,4 @@ -import useSubplebbitsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits'; +import useSubplebbitsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/subplebbits'; /** * Shallow compare two objects by keys and values. diff --git a/src/hooks/use-state-string.ts b/src/hooks/use-state-string.ts index 96ea1681..b5900782 100644 --- a/src/hooks/use-state-string.ts +++ b/src/hooks/use-state-string.ts @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import { useClientsStates, useSubplebbit, useSubplebbitsStates } from '@bitsocialhq/pkc-react-hooks'; +import { useClientsStates, useSubplebbit, useSubplebbitsStates } from '@bitsocialhq/bitsocial-react-hooks'; import debounce from 'lodash/debounce'; interface CommentOrSubplebbit { diff --git a/src/hooks/use-subplebbits-stats.ts b/src/hooks/use-subplebbits-stats.ts index 7304c6f2..bee12ee5 100644 --- a/src/hooks/use-subplebbits-stats.ts +++ b/src/hooks/use-subplebbits-stats.ts @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { useSubplebbitStats } from '@bitsocialhq/pkc-react-hooks'; +import { useSubplebbitStats } from '@bitsocialhq/bitsocial-react-hooks'; import { create } from 'zustand'; export type SubplebbitsStatsState = { diff --git a/src/hooks/use-theme.ts b/src/hooks/use-theme.ts index db6971e8..3dc56534 100644 --- a/src/hooks/use-theme.ts +++ b/src/hooks/use-theme.ts @@ -4,7 +4,7 @@ import { isAllView, isSubscriptionsView, isModView } from '../lib/utils/view-uti import useThemeStore from '../stores/use-theme-store'; import { useDirectories } from './use-directories'; import { useResolvedSubplebbitAddress } from './use-resolved-subplebbit-address'; -import { useAccountComment } from '@bitsocialhq/pkc-react-hooks'; +import { useAccountComment } from '@bitsocialhq/bitsocial-react-hooks'; import useSpecialThemeStore from '../stores/use-special-theme-store'; import { isChristmas } from '../lib/utils/time-utils'; import { updateFavicon, isSfwBoard } from '../lib/update-favicon'; diff --git a/src/lib/utils/challenge-utils.ts b/src/lib/utils/challenge-utils.ts index 36b15846..55db91b8 100644 --- a/src/lib/utils/challenge-utils.ts +++ b/src/lib/utils/challenge-utils.ts @@ -1,4 +1,4 @@ -import { ChallengeVerification } from '@bitsocialhq/pkc-react-hooks'; +import { ChallengeVerification } from '@bitsocialhq/bitsocial-react-hooks'; import directoriesData from '../../data/5chan-directories.json'; import { getBoardPath } from './route-utils'; diff --git a/src/lib/utils/media-utils.ts b/src/lib/utils/media-utils.ts index da1d382f..fd08e2d9 100644 --- a/src/lib/utils/media-utils.ts +++ b/src/lib/utils/media-utils.ts @@ -1,4 +1,4 @@ -import localForageLru from '@bitsocialhq/pkc-react-hooks/dist/lib/localforage-lru/index.js'; +import localForageLru from '@bitsocialhq/bitsocial-react-hooks/dist/lib/localforage-lru/index.js'; import { canEmbed } from '../../components/embed'; import memoize from 'memoizee'; import { isValidURL } from './url-utils'; diff --git a/src/lib/utils/pattern-utils.ts b/src/lib/utils/pattern-utils.ts index bda84056..23d2e0f6 100644 --- a/src/lib/utils/pattern-utils.ts +++ b/src/lib/utils/pattern-utils.ts @@ -1,5 +1,5 @@ -import { Comment } from '@bitsocialhq/pkc-react-hooks'; -import useSubplebbitsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits'; +import { Comment } from '@bitsocialhq/bitsocial-react-hooks'; +import useSubplebbitsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/subplebbits'; /** * Checks if a text matches a pattern according to various pattern matching rules: diff --git a/src/lib/utils/post-menu-props.ts b/src/lib/utils/post-menu-props.ts index d555868a..99ecdc4f 100644 --- a/src/lib/utils/post-menu-props.ts +++ b/src/lib/utils/post-menu-props.ts @@ -1,4 +1,4 @@ -import { Comment } from '@bitsocialhq/pkc-react-hooks'; +import { Comment } from '@bitsocialhq/bitsocial-react-hooks'; export type PostMenuProps = { cid?: string; diff --git a/src/stores/use-catalog-filters-store.ts b/src/stores/use-catalog-filters-store.ts index 53aa6e1f..cbd6a6b6 100644 --- a/src/stores/use-catalog-filters-store.ts +++ b/src/stores/use-catalog-filters-store.ts @@ -1,6 +1,6 @@ import { create } from 'zustand'; import { persist } from 'zustand/middleware'; -import { Comment } from '@bitsocialhq/pkc-react-hooks'; +import { Comment } from '@bitsocialhq/bitsocial-react-hooks'; import { commentMatchesPattern } from '../lib/utils/pattern-utils'; interface FilterItem { diff --git a/src/stores/use-challenges-store.ts b/src/stores/use-challenges-store.ts index 4c508503..592d5f05 100644 --- a/src/stores/use-challenges-store.ts +++ b/src/stores/use-challenges-store.ts @@ -1,5 +1,5 @@ import { create } from 'zustand'; -import { Challenge } from '@bitsocialhq/pkc-react-hooks'; +import { Challenge } from '@bitsocialhq/bitsocial-react-hooks'; let nextChallengeId = 0; diff --git a/src/stores/use-post-number-store.ts b/src/stores/use-post-number-store.ts index 4e1c71de..c61d0788 100644 --- a/src/stores/use-post-number-store.ts +++ b/src/stores/use-post-number-store.ts @@ -1,5 +1,5 @@ import { create } from 'zustand'; -import type { Comment } from '@bitsocialhq/pkc-react-hooks'; +import type { Comment } from '@bitsocialhq/bitsocial-react-hooks'; interface PostNumberState { // Post numbers are only unique within a subplebbit, so scope by address diff --git a/src/stores/use-publish-post-store.ts b/src/stores/use-publish-post-store.ts index 4d08c6c5..9a9390a4 100644 --- a/src/stores/use-publish-post-store.ts +++ b/src/stores/use-publish-post-store.ts @@ -1,4 +1,4 @@ -import { ChallengeVerification, Comment, PublishCommentOptions } from '@bitsocialhq/pkc-react-hooks'; +import { ChallengeVerification, Comment, PublishCommentOptions } from '@bitsocialhq/bitsocial-react-hooks'; import { create } from 'zustand'; import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils'; import useChallengesStore from './use-challenges-store'; diff --git a/src/stores/use-publish-reply-store.ts b/src/stores/use-publish-reply-store.ts index 887e70c8..2a42a588 100644 --- a/src/stores/use-publish-reply-store.ts +++ b/src/stores/use-publish-reply-store.ts @@ -1,4 +1,4 @@ -import { ChallengeVerification, Comment, PublishCommentOptions } from '@bitsocialhq/pkc-react-hooks'; +import { ChallengeVerification, Comment, PublishCommentOptions } from '@bitsocialhq/bitsocial-react-hooks'; import { create } from 'zustand'; import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils'; import useChallengesStore from './use-challenges-store'; diff --git a/src/stores/use-theme-store.ts b/src/stores/use-theme-store.ts index de45d6fe..abf79ca8 100644 --- a/src/stores/use-theme-store.ts +++ b/src/stores/use-theme-store.ts @@ -1,5 +1,5 @@ import { create, StoreApi } from 'zustand'; -import localForageLru from '@bitsocialhq/pkc-react-hooks/dist/lib/localforage-lru/index.js'; +import localForageLru from '@bitsocialhq/bitsocial-react-hooks/dist/lib/localforage-lru/index.js'; interface ThemeState { themes: { 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 a1d29138..97258397 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 @@ -28,7 +28,7 @@ vi.mock('../../../lib/utils/account-editor-utils', () => ({ buildSavePayload: vi.fn((parsed: { account: Record }, id: string) => ({ ...parsed.account, id })), })); -vi.mock('@bitsocialhq/pkc-react-hooks', () => ({ +vi.mock('@bitsocialhq/bitsocial-react-hooks', () => ({ useAccount: () => ({ id: 'test-id', name: 'Account 1', author: { address: '0x123', shortAddress: '0x1...3' } }), setAccount: vi.fn(), })); diff --git a/src/views/account-data-editor/account-data-editor.tsx b/src/views/account-data-editor/account-data-editor.tsx index 2060b68d..1a3122e4 100644 --- a/src/views/account-data-editor/account-data-editor.tsx +++ b/src/views/account-data-editor/account-data-editor.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; -import { setAccount, useAccount } from '@bitsocialhq/pkc-react-hooks'; +import { setAccount, useAccount } from '@bitsocialhq/bitsocial-react-hooks'; import { buildEditableAccountJson, safeParseAccountJson, buildSavePayload } from '../../lib/utils/account-editor-utils'; import styles from './account-data-editor.module.css'; diff --git a/src/views/board/board.tsx b/src/views/board/board.tsx index 3d3c809c..eb6f7ec8 100644 --- a/src/views/board/board.tsx +++ b/src/views/board/board.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useMemo, useRef } from 'react'; import { Link, useLocation, useNavigate, useNavigationType, useParams } from 'react-router-dom'; -import { Comment, useAccount, useAccountComments, useAccountSubplebbits, useFeed, useSubplebbit } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, useAccount, useAccountComments, useAccountSubplebbits, useFeed, useSubplebbit } from '@bitsocialhq/bitsocial-react-hooks'; import { useSubplebbitField } from '../../hooks/use-stable-subplebbit'; import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso'; import { useTranslation } from 'react-i18next'; diff --git a/src/views/catalog/catalog.tsx b/src/views/catalog/catalog.tsx index 78941be1..ff897d59 100644 --- a/src/views/catalog/catalog.tsx +++ b/src/views/catalog/catalog.tsx @@ -1,7 +1,7 @@ import { useEffect, useMemo, useRef, useState, useCallback } from 'react'; import { useLocation, useNavigate, useNavigationType, useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { Comment, useAccount, useFeed, useSubplebbit, useAccountComments } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, useAccount, useFeed, useSubplebbit, useAccountComments } from '@bitsocialhq/bitsocial-react-hooks'; import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso'; import useCatalogFeedRows from '../../hooks/use-catalog-feed-rows'; import { useDirectories, useDirectoryByAddress } from '../../hooks/use-directories'; diff --git a/src/views/home/boards-list/boards-list.tsx b/src/views/home/boards-list/boards-list.tsx index 025387b7..6dc28c40 100644 --- a/src/views/home/boards-list/boards-list.tsx +++ b/src/views/home/boards-list/boards-list.tsx @@ -1,6 +1,6 @@ import { Link, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import useAccountsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/accounts'; +import useAccountsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/accounts'; import { useDirectoriesState, useDirectories, DirectoryCommunity } from '../../../hooks/use-directories'; import { getBoardPath } from '../../../lib/utils/route-utils'; import useDisclaimerModalStore from '../../../stores/use-disclaimer-modal-store'; diff --git a/src/views/home/home.tsx b/src/views/home/home.tsx index 271ecff4..e6454126 100644 --- a/src/views/home/home.tsx +++ b/src/views/home/home.tsx @@ -1,7 +1,7 @@ import { useEffect, useMemo, useRef, FormEvent } from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { Trans, useTranslation } from 'react-i18next'; -import { useSubplebbits } from '@bitsocialhq/pkc-react-hooks'; +import { useSubplebbits } from '@bitsocialhq/bitsocial-react-hooks'; import styles from './home.module.css'; import { useDirectories, useDirectoryAddresses } from '../../hooks/use-directories'; import { SubplebbitStatsCollector, useSubplebbitsStatsStore } from '../../hooks/use-subplebbits-stats'; diff --git a/src/views/home/popular-threads-box/popular-threads-box.tsx b/src/views/home/popular-threads-box/popular-threads-box.tsx index f2bbc575..0fc8b21a 100644 --- a/src/views/home/popular-threads-box/popular-threads-box.tsx +++ b/src/views/home/popular-threads-box/popular-threads-box.tsx @@ -1,7 +1,7 @@ import { memo, useMemo } from 'react'; import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import { Comment, Subplebbit } from '@bitsocialhq/pkc-react-hooks'; +import { Comment, Subplebbit } from '@bitsocialhq/bitsocial-react-hooks'; import styles from '../home.module.css'; import usePopularPosts from '../../../hooks/use-popular-posts'; import usePopularThreadsOptionsStore from '../../../stores/use-popular-threads-options-store'; diff --git a/src/views/mod-queue/mod-queue.tsx b/src/views/mod-queue/mod-queue.tsx index b57b143c..61858607 100644 --- a/src/views/mod-queue/mod-queue.tsx +++ b/src/views/mod-queue/mod-queue.tsx @@ -1,8 +1,8 @@ import React, { useMemo, useState, useEffect, useCallback, memo } from 'react'; import { useTranslation } from 'react-i18next'; import { useParams, Link } from 'react-router-dom'; -import { useFeed, Comment, usePublishCommentModeration, useEditedComment, useSubplebbit, useComment } from '@bitsocialhq/pkc-react-hooks'; -import useAccountsStore from '@bitsocialhq/pkc-react-hooks/dist/stores/accounts'; +import { useFeed, Comment, usePublishCommentModeration, useEditedComment, useSubplebbit, useComment } from '@bitsocialhq/bitsocial-react-hooks'; +import useAccountsStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/accounts'; import { Virtuoso } from 'react-virtuoso'; import styles from './mod-queue.module.css'; import useModQueueStore from '../../stores/use-mod-queue-store'; diff --git a/src/views/pending-post/pending-post.tsx b/src/views/pending-post/pending-post.tsx index f622abeb..0bc8bcc6 100644 --- a/src/views/pending-post/pending-post.tsx +++ b/src/views/pending-post/pending-post.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; -import { useAccountComment, useAccountComments } from '@bitsocialhq/pkc-react-hooks'; +import { useAccountComment, useAccountComments } from '@bitsocialhq/bitsocial-react-hooks'; import { useDirectories } from '../../hooks/use-directories'; import { getBoardPath } from '../../lib/utils/route-utils'; import { Post } from '../post'; diff --git a/src/views/post/post.tsx b/src/views/post/post.tsx index 4a7d8db1..d22bbe75 100644 --- a/src/views/post/post.tsx +++ b/src/views/post/post.tsx @@ -1,7 +1,7 @@ import { memo, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { Comment, Role, useComment, useEditedComment, useSubplebbit } from '@bitsocialhq/pkc-react-hooks'; -import useSubplebbitsPagesStore from '@bitsocialhq/pkc-react-hooks/dist/stores/subplebbits-pages'; +import { Comment, Role, useComment, useEditedComment, useSubplebbit } from '@bitsocialhq/bitsocial-react-hooks'; +import useSubplebbitsPagesStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/subplebbits-pages'; import { useSubplebbitField } from '../../hooks/use-stable-subplebbit'; import { useLocation, useNavigate, useParams } from 'react-router-dom'; import { isAllView } from '../../lib/utils/view-utils'; diff --git a/src/views/rules/rules.tsx b/src/views/rules/rules.tsx index 5e850657..ef991a74 100644 --- a/src/views/rules/rules.tsx +++ b/src/views/rules/rules.tsx @@ -1,6 +1,6 @@ import { useEffect, useState, FormEvent } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; -import { useSubplebbit } from '@bitsocialhq/pkc-react-hooks'; +import { useSubplebbit } from '@bitsocialhq/bitsocial-react-hooks'; import { Footer, HomeLogo } from '../home'; import { useDirectories, DirectoryCommunity } from '../../hooks/use-directories'; import { getSubplebbitAddress, getBoardPath } from '../../lib/utils/route-utils'; diff --git a/vite.config.js b/vite.config.js index c21249de..a5cce09e 100644 --- a/vite.config.js +++ b/vite.config.js @@ -172,8 +172,8 @@ export default defineConfig({ if (/[\\/]node_modules[\\/](@plebbit[\\/]plebbit-js)[\\/]/.test(id)) { return 'plebbit-js'; } - if (/[\\/]node_modules[\\/](@bitsocialhq[\\/]pkc-react-hooks)[\\/]/.test(id)) { - return 'pkc-react-hooks'; + if (/[\\/]node_modules[\\/](@bitsocialhq[\\/]bitsocial-react-hooks)[\\/]/.test(id)) { + return 'bitsocial-react-hooks'; } if (/[\\/]node_modules[\\/](@react-spring|@use-gesture)[\\/]/.test(id)) { return 'spring-gesture'; diff --git a/yarn.lock b/yarn.lock index 9c12f2e9..0e34fd08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1023,30 +1023,14 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.28.5" -"@bitsocialhq/pkc-react-hooks@https://github.com/bitsocialhq/pkc-react-hooks.git#00743c41a0cbbb88d29dccf21f45b69c16b8850c": +"@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#6dc27da29debfb9c0144b445132bae4cfd975c4f": version "0.1.0" - resolved "https://github.com/bitsocialhq/pkc-react-hooks.git#00743c41a0cbbb88d29dccf21f45b69c16b8850c" + resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#6dc27da29debfb9c0144b445132bae4cfd975c4f" dependencies: - "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#ca9288c42f4b9a3d7ab6928ba03da6931c24e519" + "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#10ed04e3866dd986a7f802bc9efd027f0e7d465b" "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git" assert "2.0.0" - ethers "5.6.9" - localforage "1.10.0" - lodash.isequal "4.5.0" - memoizee "0.4.15" - quick-lru "5.1.1" - uint8arrays "3.1.1" - uuid "11.1.0" - zustand "4.0.0" - -"@bitsocialhq/pkc-react-hooks@https://github.com/bitsocialhq/pkc-react-hooks.git#8d93bb78eb570f0769904cb6ce5cb83ab8b277d4": - version "0.1.0" - resolved "https://github.com/bitsocialhq/pkc-react-hooks.git#8d93bb78eb570f0769904cb6ce5cb83ab8b277d4" - dependencies: - "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#ca9288c42f4b9a3d7ab6928ba03da6931c24e519" - "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git" - assert "2.0.0" - ethers "5.6.9" + ethers "5.8.0" localforage "1.10.0" lodash.isequal "4.5.0" memoizee "0.4.15" @@ -1823,22 +1807,7 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.11.tgz#5ecda6f3fe138b7e456f4e429edde33c823f392f" integrity sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA== -"@ethersproject/abi@5.6.4": - version "5.6.4" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.4.tgz#f6e01b6ed391a505932698ecc0d9e7a99ee60362" - integrity sha512-TTeZUlCeIHG6527/2goZA6gW5F8Emoc7MrZDC7hhP84aRGvW3TEdTnZR08Ls88YXM1m2SuK42Osw/jSi3uO8gg== - dependencies: - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/hash" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.1" - -"@ethersproject/abi@^5.6.3": +"@ethersproject/abi@5.8.0", "@ethersproject/abi@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.8.0.tgz#e79bb51940ac35fe6f3262d7fe2cdb25ad5f07d9" integrity sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q== @@ -1853,20 +1822,7 @@ "@ethersproject/properties" "^5.8.0" "@ethersproject/strings" "^5.8.0" -"@ethersproject/abstract-provider@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.1.tgz#02ddce150785caf0c77fe036a0ebfcee61878c59" - integrity sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ== - dependencies: - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/networks" "^5.6.3" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/transactions" "^5.6.2" - "@ethersproject/web" "^5.6.1" - -"@ethersproject/abstract-provider@^5.6.1", "@ethersproject/abstract-provider@^5.8.0": +"@ethersproject/abstract-provider@5.8.0", "@ethersproject/abstract-provider@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz#7581f9be601afa1d02b95d26b9d9840926a35b0c" integrity sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg== @@ -1879,18 +1835,7 @@ "@ethersproject/transactions" "^5.8.0" "@ethersproject/web" "^5.8.0" -"@ethersproject/abstract-signer@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.2.tgz#491f07fc2cbd5da258f46ec539664713950b0b33" - integrity sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ== - dependencies: - "@ethersproject/abstract-provider" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - -"@ethersproject/abstract-signer@^5.6.2", "@ethersproject/abstract-signer@^5.8.0": +"@ethersproject/abstract-signer@5.8.0", "@ethersproject/abstract-signer@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz#8d7417e95e4094c1797a9762e6789c7356db0754" integrity sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA== @@ -1901,18 +1846,7 @@ "@ethersproject/logger" "^5.8.0" "@ethersproject/properties" "^5.8.0" -"@ethersproject/address@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.1.tgz#ab57818d9aefee919c5721d28cd31fd95eff413d" - integrity sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q== - dependencies: - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/rlp" "^5.6.1" - -"@ethersproject/address@^5.6.1", "@ethersproject/address@^5.8.0": +"@ethersproject/address@5.8.0", "@ethersproject/address@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.8.0.tgz#3007a2c352eee566ad745dca1dbbebdb50a6a983" integrity sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA== @@ -1923,29 +1857,14 @@ "@ethersproject/logger" "^5.8.0" "@ethersproject/rlp" "^5.8.0" -"@ethersproject/base64@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.1.tgz#2c40d8a0310c9d1606c2c37ae3092634b41d87cb" - integrity sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw== - dependencies: - "@ethersproject/bytes" "^5.6.1" - -"@ethersproject/base64@^5.6.1", "@ethersproject/base64@^5.8.0": +"@ethersproject/base64@5.8.0", "@ethersproject/base64@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.8.0.tgz#61c669c648f6e6aad002c228465d52ac93ee83eb" integrity sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ== dependencies: "@ethersproject/bytes" "^5.8.0" -"@ethersproject/basex@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.6.1.tgz#badbb2f1d4a6f52ce41c9064f01eab19cc4c5305" - integrity sha512-a52MkVz4vuBXR06nvflPMotld1FJWSj2QT0985v7P/emPZO00PucFAkbcmq2vpVU7Ts7umKiSI6SppiLykVWsA== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/properties" "^5.6.0" - -"@ethersproject/basex@^5.6.1", "@ethersproject/basex@^5.8.0": +"@ethersproject/basex@5.8.0", "@ethersproject/basex@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.8.0.tgz#1d279a90c4be84d1c1139114a1f844869e57d03a" integrity sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q== @@ -1953,16 +1872,7 @@ "@ethersproject/bytes" "^5.8.0" "@ethersproject/properties" "^5.8.0" -"@ethersproject/bignumber@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.2.tgz#72a0717d6163fab44c47bcc82e0c550ac0315d66" - integrity sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - bn.js "^5.2.1" - -"@ethersproject/bignumber@^5.6.2", "@ethersproject/bignumber@^5.8.0": +"@ethersproject/bignumber@5.8.0", "@ethersproject/bignumber@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.8.0.tgz#c381d178f9eeb370923d389284efa19f69efa5d7" integrity sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA== @@ -1971,65 +1881,37 @@ "@ethersproject/logger" "^5.8.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" - integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== - dependencies: - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/bytes@^5.6.1", "@ethersproject/bytes@^5.8.0": +"@ethersproject/bytes@5.8.0", "@ethersproject/bytes@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.8.0.tgz#9074820e1cac7507a34372cadeb035461463be34" integrity sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A== dependencies: "@ethersproject/logger" "^5.8.0" -"@ethersproject/constants@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.1.tgz#e2e974cac160dd101cf79fdf879d7d18e8cb1370" - integrity sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg== - dependencies: - "@ethersproject/bignumber" "^5.6.2" - -"@ethersproject/constants@^5.6.1", "@ethersproject/constants@^5.8.0": +"@ethersproject/constants@5.8.0", "@ethersproject/constants@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.8.0.tgz#12f31c2f4317b113a4c19de94e50933648c90704" integrity sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg== dependencies: "@ethersproject/bignumber" "^5.8.0" -"@ethersproject/contracts@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.6.2.tgz#20b52e69ebc1b74274ff8e3d4e508de971c287bc" - integrity sha512-hguUA57BIKi6WY0kHvZp6PwPlWF87MCeB4B7Z7AbUpTxfFXFdn/3b0GmjZPagIHS+3yhcBJDnuEfU4Xz+Ks/8g== +"@ethersproject/contracts@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.8.0.tgz#243a38a2e4aa3e757215ea64e276f8a8c9d8ed73" + integrity sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ== dependencies: - "@ethersproject/abi" "^5.6.3" - "@ethersproject/abstract-provider" "^5.6.1" - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/transactions" "^5.6.2" + "@ethersproject/abi" "^5.8.0" + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" -"@ethersproject/hash@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.1.tgz#224572ea4de257f05b4abf8ae58b03a67e99b0f4" - integrity sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA== - dependencies: - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.1" - -"@ethersproject/hash@^5.6.1", "@ethersproject/hash@^5.8.0": +"@ethersproject/hash@5.8.0", "@ethersproject/hash@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.8.0.tgz#b8893d4629b7f8462a90102572f8cd65a0192b4c" integrity sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA== @@ -2044,25 +1926,7 @@ "@ethersproject/properties" "^5.8.0" "@ethersproject/strings" "^5.8.0" -"@ethersproject/hdnode@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.6.2.tgz#26f3c83a3e8f1b7985c15d1db50dc2903418b2d2" - integrity sha512-tERxW8Ccf9CxW2db3WsN01Qao3wFeRsfYY9TCuhmG0xNpl2IO8wgXU3HtWIZ49gUWPggRy4Yg5axU0ACaEKf1Q== - dependencies: - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/basex" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/pbkdf2" "^5.6.1" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/sha2" "^5.6.1" - "@ethersproject/signing-key" "^5.6.2" - "@ethersproject/strings" "^5.6.1" - "@ethersproject/transactions" "^5.6.2" - "@ethersproject/wordlists" "^5.6.1" - -"@ethersproject/hdnode@^5.6.2", "@ethersproject/hdnode@^5.8.0": +"@ethersproject/hdnode@5.8.0", "@ethersproject/hdnode@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.8.0.tgz#a51ae2a50bcd48ef6fd108c64cbae5e6ff34a761" integrity sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA== @@ -2080,26 +1944,7 @@ "@ethersproject/transactions" "^5.8.0" "@ethersproject/wordlists" "^5.8.0" -"@ethersproject/json-wallets@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.6.1.tgz#3f06ba555c9c0d7da46756a12ac53483fe18dd91" - integrity sha512-KfyJ6Zwz3kGeX25nLihPwZYlDqamO6pfGKNnVMWWfEVVp42lTfCZVXXy5Ie8IZTN0HKwAngpIPi7gk4IJzgmqQ== - dependencies: - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/hdnode" "^5.6.2" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/pbkdf2" "^5.6.1" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/random" "^5.6.1" - "@ethersproject/strings" "^5.6.1" - "@ethersproject/transactions" "^5.6.2" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/json-wallets@^5.6.1": +"@ethersproject/json-wallets@5.8.0", "@ethersproject/json-wallets@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz#d18de0a4cf0f185f232eb3c17d5e0744d97eb8c9" integrity sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w== @@ -2118,15 +1963,7 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.1.tgz#b867167c9b50ba1b1a92bccdd4f2d6bd168a91cc" - integrity sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA== - dependencies: - "@ethersproject/bytes" "^5.6.1" - js-sha3 "0.8.0" - -"@ethersproject/keccak256@^5.6.1", "@ethersproject/keccak256@^5.8.0": +"@ethersproject/keccak256@5.8.0", "@ethersproject/keccak256@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.8.0.tgz#d2123a379567faf2d75d2aaea074ffd4df349e6a" integrity sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng== @@ -2134,39 +1971,19 @@ "@ethersproject/bytes" "^5.8.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" - integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== - -"@ethersproject/logger@^5.6.0", "@ethersproject/logger@^5.8.0": +"@ethersproject/logger@5.8.0", "@ethersproject/logger@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.8.0.tgz#f0232968a4f87d29623a0481690a2732662713d6" integrity sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA== -"@ethersproject/networks@5.6.4": - version "5.6.4" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.4.tgz#51296d8fec59e9627554f5a8a9c7791248c8dc07" - integrity sha512-KShHeHPahHI2UlWdtDMn2lJETcbtaJge4k7XSjDR9h79QTd6yQJmv6Cp2ZA4JdqWnhszAOLSuJEd9C0PRw7hSQ== - dependencies: - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/networks@^5.6.3", "@ethersproject/networks@^5.8.0": +"@ethersproject/networks@5.8.0", "@ethersproject/networks@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.8.0.tgz#8b4517a3139380cba9fb00b63ffad0a979671fde" integrity sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg== dependencies: "@ethersproject/logger" "^5.8.0" -"@ethersproject/pbkdf2@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.6.1.tgz#f462fe320b22c0d6b1d72a9920a3963b09eb82d1" - integrity sha512-k4gRQ+D93zDRPNUfmduNKq065uadC2YjMP/CqwwX5qG6R05f47boq6pLZtV/RnC4NZAYOPH1Cyo54q0c9sshRQ== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/sha2" "^5.6.1" - -"@ethersproject/pbkdf2@^5.6.1", "@ethersproject/pbkdf2@^5.8.0": +"@ethersproject/pbkdf2@5.8.0", "@ethersproject/pbkdf2@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz#cd2621130e5dd51f6a0172e63a6e4a0c0a0ec37e" integrity sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg== @@ -2174,55 +1991,40 @@ "@ethersproject/bytes" "^5.8.0" "@ethersproject/sha2" "^5.8.0" -"@ethersproject/properties@5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04" - integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg== - dependencies: - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/properties@^5.6.0", "@ethersproject/properties@^5.8.0": +"@ethersproject/properties@5.8.0", "@ethersproject/properties@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.8.0.tgz#405a8affb6311a49a91dabd96aeeae24f477020e" integrity sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw== dependencies: "@ethersproject/logger" "^5.8.0" -"@ethersproject/providers@5.6.8": - version "5.6.8" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.6.8.tgz#22e6c57be215ba5545d3a46cf759d265bb4e879d" - integrity sha512-Wf+CseT/iOJjrGtAOf3ck9zS7AgPmr2fZ3N97r4+YXN3mBePTG2/bJ8DApl9mVwYL+RpYbNxMEkEp4mPGdwG/w== +"@ethersproject/providers@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.8.0.tgz#6c2ae354f7f96ee150439f7de06236928bc04cb4" + integrity sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw== dependencies: - "@ethersproject/abstract-provider" "^5.6.1" - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/base64" "^5.6.1" - "@ethersproject/basex" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/hash" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/networks" "^5.6.3" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/random" "^5.6.1" - "@ethersproject/rlp" "^5.6.1" - "@ethersproject/sha2" "^5.6.1" - "@ethersproject/strings" "^5.6.1" - "@ethersproject/transactions" "^5.6.2" - "@ethersproject/web" "^5.6.1" + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/base64" "^5.8.0" + "@ethersproject/basex" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/networks" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/random" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + "@ethersproject/sha2" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/web" "^5.8.0" bech32 "1.1.4" - ws "7.4.6" + ws "8.18.0" -"@ethersproject/random@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.6.1.tgz#66915943981bcd3e11bbd43733f5c3ba5a790255" - integrity sha512-/wtPNHwbmng+5yi3fkipA8YBT59DdkGRoC2vWk09Dci/q5DlgnMkhIycjHlavrvrjJBkFjO/ueLyT+aUDfc4lA== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/random@^5.6.1", "@ethersproject/random@^5.8.0": +"@ethersproject/random@5.8.0", "@ethersproject/random@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.8.0.tgz#1bced04d49449f37c6437c701735a1a022f0057a" integrity sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A== @@ -2230,15 +2032,7 @@ "@ethersproject/bytes" "^5.8.0" "@ethersproject/logger" "^5.8.0" -"@ethersproject/rlp@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.1.tgz#df8311e6f9f24dcb03d59a2bac457a28a4fe2bd8" - integrity sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/rlp@^5.6.1", "@ethersproject/rlp@^5.8.0": +"@ethersproject/rlp@5.8.0", "@ethersproject/rlp@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.8.0.tgz#5a0d49f61bc53e051532a5179472779141451de5" integrity sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q== @@ -2246,16 +2040,7 @@ "@ethersproject/bytes" "^5.8.0" "@ethersproject/logger" "^5.8.0" -"@ethersproject/sha2@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.6.1.tgz#211f14d3f5da5301c8972a8827770b6fd3e51656" - integrity sha512-5K2GyqcW7G4Yo3uenHegbXRPDgARpWUiXc6RiF7b6i/HXUoWlb7uCARh7BAHg7/qT/Q5ydofNwiZcim9qpjB6g== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - hash.js "1.1.7" - -"@ethersproject/sha2@^5.6.1", "@ethersproject/sha2@^5.8.0": +"@ethersproject/sha2@5.8.0", "@ethersproject/sha2@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.8.0.tgz#8954a613bb78dac9b46829c0a95de561ef74e5e1" integrity sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A== @@ -2264,19 +2049,7 @@ "@ethersproject/logger" "^5.8.0" hash.js "1.1.7" -"@ethersproject/signing-key@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.2.tgz#8a51b111e4d62e5a62aee1da1e088d12de0614a3" - integrity sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/signing-key@^5.6.2", "@ethersproject/signing-key@^5.8.0": +"@ethersproject/signing-key@5.8.0", "@ethersproject/signing-key@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.8.0.tgz#9797e02c717b68239c6349394ea85febf8893119" integrity sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w== @@ -2288,28 +2061,19 @@ elliptic "6.6.1" hash.js "1.1.7" -"@ethersproject/solidity@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.6.1.tgz#5845e71182c66d32e6ec5eefd041fca091a473e2" - integrity sha512-KWqVLkUUoLBfL1iwdzUVlkNqAUIFMpbbeH0rgCfKmJp0vFtY4AsaN91gHKo9ZZLkC4UOm3cI3BmMV4N53BOq4g== +"@ethersproject/solidity@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.8.0.tgz#429bb9fcf5521307a9448d7358c26b93695379b9" + integrity sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA== dependencies: - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/sha2" "^5.6.1" - "@ethersproject/strings" "^5.6.1" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/sha2" "^5.8.0" + "@ethersproject/strings" "^5.8.0" -"@ethersproject/strings@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.1.tgz#dbc1b7f901db822b5cafd4ebf01ca93c373f8952" - integrity sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - -"@ethersproject/strings@^5.6.1", "@ethersproject/strings@^5.8.0": +"@ethersproject/strings@5.8.0", "@ethersproject/strings@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.8.0.tgz#ad79fafbf0bd272d9765603215ac74fd7953908f" integrity sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg== @@ -2318,22 +2082,7 @@ "@ethersproject/constants" "^5.8.0" "@ethersproject/logger" "^5.8.0" -"@ethersproject/transactions@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.2.tgz#793a774c01ced9fe7073985bb95a4b4e57a6370b" - integrity sha512-BuV63IRPHmJvthNkkt9G70Ullx6AcM+SDc+a8Aw/8Yew6YwT51TcBKEp1P4oOQ/bP25I18JJr7rcFRgFtU9B2Q== - dependencies: - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/rlp" "^5.6.1" - "@ethersproject/signing-key" "^5.6.2" - -"@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.8.0": +"@ethersproject/transactions@5.8.0", "@ethersproject/transactions@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.8.0.tgz#1e518822403abc99def5a043d1c6f6fe0007e46b" integrity sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg== @@ -2348,48 +2097,37 @@ "@ethersproject/rlp" "^5.8.0" "@ethersproject/signing-key" "^5.8.0" -"@ethersproject/units@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.6.1.tgz#ecc590d16d37c8f9ef4e89e2005bda7ddc6a4e6f" - integrity sha512-rEfSEvMQ7obcx3KWD5EWWx77gqv54K6BKiZzKxkQJqtpriVsICrktIQmKl8ReNToPeIYPnFHpXvKpi068YFZXw== +"@ethersproject/units@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.8.0.tgz#c12f34ba7c3a2de0e9fa0ed0ee32f3e46c5c2c6a" + integrity sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ== dependencies: - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/constants" "^5.6.1" - "@ethersproject/logger" "^5.6.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/logger" "^5.8.0" -"@ethersproject/wallet@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.6.2.tgz#cd61429d1e934681e413f4bc847a5f2f87e3a03c" - integrity sha512-lrgh0FDQPuOnHcF80Q3gHYsSUODp6aJLAdDmDV0xKCN/T7D99ta1jGVhulg3PY8wiXEngD0DfM0I2XKXlrqJfg== +"@ethersproject/wallet@5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.8.0.tgz#49c300d10872e6986d953e8310dc33d440da8127" + integrity sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA== dependencies: - "@ethersproject/abstract-provider" "^5.6.1" - "@ethersproject/abstract-signer" "^5.6.2" - "@ethersproject/address" "^5.6.1" - "@ethersproject/bignumber" "^5.6.2" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/hash" "^5.6.1" - "@ethersproject/hdnode" "^5.6.2" - "@ethersproject/json-wallets" "^5.6.1" - "@ethersproject/keccak256" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/random" "^5.6.1" - "@ethersproject/signing-key" "^5.6.2" - "@ethersproject/transactions" "^5.6.2" - "@ethersproject/wordlists" "^5.6.1" + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/hdnode" "^5.8.0" + "@ethersproject/json-wallets" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/random" "^5.8.0" + "@ethersproject/signing-key" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/wordlists" "^5.8.0" -"@ethersproject/web@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.1.tgz#6e2bd3ebadd033e6fe57d072db2b69ad2c9bdf5d" - integrity sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA== - dependencies: - "@ethersproject/base64" "^5.6.1" - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.1" - -"@ethersproject/web@^5.6.1", "@ethersproject/web@^5.8.0": +"@ethersproject/web@5.8.0", "@ethersproject/web@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.8.0.tgz#3e54badc0013b7a801463a7008a87988efce8a37" integrity sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw== @@ -2400,18 +2138,7 @@ "@ethersproject/properties" "^5.8.0" "@ethersproject/strings" "^5.8.0" -"@ethersproject/wordlists@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.6.1.tgz#1e78e2740a8a21e9e99947e47979d72e130aeda1" - integrity sha512-wiPRgBpNbNwCQFoCr8bcWO8o5I810cqO6mkdtKfLKFlLxeCWcnzDi4Alu8iyNzlhYuS9npCwivMbRWF19dyblw== - dependencies: - "@ethersproject/bytes" "^5.6.1" - "@ethersproject/hash" "^5.6.1" - "@ethersproject/logger" "^5.6.0" - "@ethersproject/properties" "^5.6.0" - "@ethersproject/strings" "^5.6.1" - -"@ethersproject/wordlists@^5.6.1", "@ethersproject/wordlists@^5.8.0": +"@ethersproject/wordlists@5.8.0", "@ethersproject/wordlists@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.8.0.tgz#7a5654ee8d1bb1f4dbe43f91d217356d650ad821" integrity sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg== @@ -4272,9 +3999,9 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#ca9288c42f4b9a3d7ab6928ba03da6931c24e519": +"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#10ed04e3866dd986a7f802bc9efd027f0e7d465b": version "0.0.11" - resolved "https://github.com/plebbit/plebbit-js.git#ca9288c42f4b9a3d7ab6928ba03da6931c24e519" + resolved "https://github.com/plebbit/plebbit-js.git#10ed04e3866dd986a7f802bc9efd027f0e7d465b" dependencies: "@bonfida/spl-name-service" "3.0.16" "@enhances/with-resolvers" "0.0.5" @@ -7569,7 +7296,7 @@ elementtree@^0.1.7: dependencies: sax "1.1.4" -elliptic@6.5.4, elliptic@6.6.1, elliptic@^6.5.3, elliptic@^6.6.1: +elliptic@6.6.1, elliptic@^6.5.3, elliptic@^6.6.1: version "6.6.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== @@ -7916,41 +7643,41 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -ethers@5.6.9: - version "5.6.9" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.6.9.tgz#4e12f8dfcb67b88ae7a78a9519b384c23c576a4d" - integrity sha512-lMGC2zv9HC5EC+8r429WaWu3uWJUCgUCt8xxKCFqkrFuBDZXDYIdzDUECxzjf2BMF8IVBByY1EBoGSL3RTm8RA== +ethers@5.8.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.8.0.tgz#97858dc4d4c74afce83ea7562fe9493cedb4d377" + integrity sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg== dependencies: - "@ethersproject/abi" "5.6.4" - "@ethersproject/abstract-provider" "5.6.1" - "@ethersproject/abstract-signer" "5.6.2" - "@ethersproject/address" "5.6.1" - "@ethersproject/base64" "5.6.1" - "@ethersproject/basex" "5.6.1" - "@ethersproject/bignumber" "5.6.2" - "@ethersproject/bytes" "5.6.1" - "@ethersproject/constants" "5.6.1" - "@ethersproject/contracts" "5.6.2" - "@ethersproject/hash" "5.6.1" - "@ethersproject/hdnode" "5.6.2" - "@ethersproject/json-wallets" "5.6.1" - "@ethersproject/keccak256" "5.6.1" - "@ethersproject/logger" "5.6.0" - "@ethersproject/networks" "5.6.4" - "@ethersproject/pbkdf2" "5.6.1" - "@ethersproject/properties" "5.6.0" - "@ethersproject/providers" "5.6.8" - "@ethersproject/random" "5.6.1" - "@ethersproject/rlp" "5.6.1" - "@ethersproject/sha2" "5.6.1" - "@ethersproject/signing-key" "5.6.2" - "@ethersproject/solidity" "5.6.1" - "@ethersproject/strings" "5.6.1" - "@ethersproject/transactions" "5.6.2" - "@ethersproject/units" "5.6.1" - "@ethersproject/wallet" "5.6.2" - "@ethersproject/web" "5.6.1" - "@ethersproject/wordlists" "5.6.1" + "@ethersproject/abi" "5.8.0" + "@ethersproject/abstract-provider" "5.8.0" + "@ethersproject/abstract-signer" "5.8.0" + "@ethersproject/address" "5.8.0" + "@ethersproject/base64" "5.8.0" + "@ethersproject/basex" "5.8.0" + "@ethersproject/bignumber" "5.8.0" + "@ethersproject/bytes" "5.8.0" + "@ethersproject/constants" "5.8.0" + "@ethersproject/contracts" "5.8.0" + "@ethersproject/hash" "5.8.0" + "@ethersproject/hdnode" "5.8.0" + "@ethersproject/json-wallets" "5.8.0" + "@ethersproject/keccak256" "5.8.0" + "@ethersproject/logger" "5.8.0" + "@ethersproject/networks" "5.8.0" + "@ethersproject/pbkdf2" "5.8.0" + "@ethersproject/properties" "5.8.0" + "@ethersproject/providers" "5.8.0" + "@ethersproject/random" "5.8.0" + "@ethersproject/rlp" "5.8.0" + "@ethersproject/sha2" "5.8.0" + "@ethersproject/signing-key" "5.8.0" + "@ethersproject/solidity" "5.8.0" + "@ethersproject/strings" "5.8.0" + "@ethersproject/transactions" "5.8.0" + "@ethersproject/units" "5.8.0" + "@ethersproject/wallet" "5.8.0" + "@ethersproject/web" "5.8.0" + "@ethersproject/wordlists" "5.8.0" ethers@6.16.0: version "6.16.0" @@ -15530,7 +15257,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@7.4.6, ws@8.17.1, ws@8.18.3, ws@^7.5.10, ws@^8.18.3, ws@^8.5.0: +ws@8.17.1, ws@8.18.0, ws@8.18.3, ws@^7.5.10, ws@^8.18.3, ws@^8.5.0: version "8.18.3" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== From 3fa758ef8c801b127ec0b752d447379fdc5657a2 Mon Sep 17 00:00:00 2001 From: plebeius Date: Thu, 5 Mar 2026 19:07:42 +0800 Subject: [PATCH 02/19] chore(deps): upgrade bitsocial-react-hooks --- package.json | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f208db51..d380e3f9 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "GPL-2.0-only", "private": true, "dependencies": { - "@bitsocialhq/bitsocial-react-hooks": "https://github.com/bitsocialhq/bitsocial-react-hooks.git#6dc27da29debfb9c0144b445132bae4cfd975c4f", + "@bitsocialhq/bitsocial-react-hooks": "https://github.com/bitsocialhq/bitsocial-react-hooks.git#c9e56de2307f5bd5db0c2b7958a3ecad6ea0a724", "@capacitor/app": "7.0.1", "@capacitor/status-bar": "7.0.1", "@capawesome/capacitor-android-edge-to-edge-support": "7.2.2", diff --git a/yarn.lock b/yarn.lock index 0e34fd08..41663fd4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1023,9 +1023,9 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.28.5" -"@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#6dc27da29debfb9c0144b445132bae4cfd975c4f": +"@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#c9e56de2307f5bd5db0c2b7958a3ecad6ea0a724": version "0.1.0" - resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#6dc27da29debfb9c0144b445132bae4cfd975c4f" + resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#c9e56de2307f5bd5db0c2b7958a3ecad6ea0a724" dependencies: "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#10ed04e3866dd986a7f802bc9efd027f0e7d465b" "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git" From 980b5ca57276322b7838dad19d40208f37403c50 Mon Sep 17 00:00:00 2001 From: plebeius Date: Thu, 5 Mar 2026 19:09:23 +0800 Subject: [PATCH 03/19] fix(post): hide stuck Loading and Downloading board for pending comments --- src/components/post-desktop/post-desktop.tsx | 10 ++++++++-- src/components/post-mobile/post-mobile.tsx | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index ca719ea7..7c057e2b 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -1009,7 +1009,7 @@ const PostDesktop = ({ )} {/* Virtuoso infinite scroll for post page view when there's more content to paginate */} - {!isHidden && showAllReplies && !isInPendingPostView && showReplies && hasMore && ( + {!isHidden && showAllReplies && !isInPendingPostView && showReplies && hasMore && !!post?.replyCount && ( )} - {!isInPendingPostView && stateString && !hasFailedState && state !== 'succeeded' && isInPostPageView && !(!showReplies && !showAllReplies) ? ( + {!isInPendingPostView && + stateString && + !hasFailedState && + state !== 'succeeded' && + !(post?.timestamp && !post?.updatedAt) && + isInPostPageView && + !(!showReplies && !showAllReplies) ? (

diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index 8b56e23f..3d1aff04 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -732,7 +732,7 @@ const PostMobile = ({ )}
{/* Virtuoso infinite scroll for post page view when there's more content to paginate */} - {showAllReplies && !isInPendingPostView && showReplies && hasMore && ( + {showAllReplies && !isInPendingPostView && showReplies && hasMore && !!post?.replyCount && ( ))} - {!isInPendingPostView && stateString && !hasFailedState && state !== 'succeeded' && isInPostPageView && !(!showReplies && !showAllReplies) ? ( + {!isInPendingPostView && + stateString && + !hasFailedState && + state !== 'succeeded' && + !(post?.timestamp && !post?.updatedAt) && + isInPostPageView && + !(!showReplies && !showAllReplies) ? (
From 59851a4b01ba9ef356d4f081163f490c26443694 Mon Sep 17 00:00:00 2001 From: plebeius Date: Thu, 5 Mar 2026 19:30:50 +0800 Subject: [PATCH 04/19] fix(publishing): abandon challenge close and clean failed local posts --- .../challenge-modal/challenge-modal.tsx | 38 +++++++++---------- src/components/post-desktop/post-desktop.tsx | 30 ++++++++++++++- src/components/post-mobile/post-mobile.tsx | 30 ++++++++++++++- src/hooks/use-publish-post.ts | 20 +++++++++- src/hooks/use-publish-reply.ts | 21 ++++++++-- src/stores/use-challenges-store.ts | 21 +++++++--- src/stores/use-publish-post-store.ts | 4 -- src/stores/use-publish-reply-store.ts | 4 -- src/views/post/post.module.css | 28 +++++++++++++- 9 files changed, 156 insertions(+), 40 deletions(-) diff --git a/src/components/challenge-modal/challenge-modal.tsx b/src/components/challenge-modal/challenge-modal.tsx index 1acd1d50..a513fc3c 100644 --- a/src/components/challenge-modal/challenge-modal.tsx +++ b/src/components/challenge-modal/challenge-modal.tsx @@ -18,6 +18,7 @@ const useParentAddress = (parentCid?: string) => { interface ChallengeProps { challenge: ChallengeType; closeModal: () => void; + abandonModal: () => void; } const TextChallenge = ({ challenge }: { challenge: string }) =>
{challenge}
; @@ -29,12 +30,12 @@ interface IframeChallengeProps { shortSubplebbitAddress?: string; subplebbitAddress?: string; readableUrl: string; - closeModal: () => void; + onCancel: () => void; onDone: () => void; publicationDetails: React.ReactNode; } -const IframeChallenge = ({ challenge, shortSubplebbitAddress, subplebbitAddress, readableUrl, closeModal, onDone, publicationDetails }: IframeChallengeProps) => { +const IframeChallenge = ({ challenge, shortSubplebbitAddress, subplebbitAddress, readableUrl, onCancel, onDone, publicationDetails }: IframeChallengeProps) => { const account = useAccount(); const [theme] = useTheme(); const [showIframeConfirmation, setShowIframeConfirmation] = useState(true); @@ -71,9 +72,9 @@ const IframeChallenge = ({ challenge, shortSubplebbitAddress, subplebbitAddress, } catch (error) { console.error('Invalid iframe challenge URL', { error }); alert('Error: Invalid URL for authentication challenge'); - closeModal(); + onCancel(); } - }, [account, challenge, closeModal, theme]); + }, [account, challenge, onCancel, theme]); const sendThemeToIframe = useCallback(() => { if (!iframeRef.current || !iframeOrigin) return; @@ -106,7 +107,7 @@ const IframeChallenge = ({ challenge, shortSubplebbitAddress, subplebbitAddress,
- +
@@ -134,7 +135,7 @@ const IframeChallenge = ({ challenge, shortSubplebbitAddress, subplebbitAddress, ); }; -const Challenge = ({ challenge, closeModal }: ChallengeProps) => { +const Challenge = ({ challenge, closeModal, abandonModal }: ChallengeProps) => { const { t } = useTranslation(); const challenges = challenge?.[0]?.challenges; @@ -207,7 +208,7 @@ const Challenge = ({ challenge, closeModal }: ChallengeProps) => { closeModal(); }; - const onIframeClose = useCallback(() => { + const onIframeDone = useCallback(() => { if (!publication) return; publication.publishChallengeAnswers(['']); closeModal(); @@ -226,16 +227,12 @@ const Challenge = ({ challenge, closeModal }: ChallengeProps) => { useEffect(() => { const onEscapeKey = (e: KeyboardEvent) => { if (e.key === 'Escape') { - if (isIframeChallenge) { - onIframeClose(); - } else { - closeModal(); - } + abandonModal(); } }; document.addEventListener('keydown', onEscapeKey); return () => document.removeEventListener('keydown', onEscapeKey); - }, [closeModal, isIframeChallenge, onIframeClose]); + }, [abandonModal]); const getChallengeUrl = useCallback(() => { try { @@ -314,7 +311,7 @@ const Challenge = ({ challenge, closeModal }: ChallengeProps) => { >
Challenge for {publicationType} -
{isIframeChallenge ? ( @@ -324,8 +321,8 @@ const Challenge = ({ challenge, closeModal }: ChallengeProps) => { shortSubplebbitAddress={shortSubplebbitAddress} subplebbitAddress={subplebbitAddress} readableUrl={readableUrl} - closeModal={closeModal} - onDone={onIframeClose} + onCancel={abandonModal} + onDone={onIframeDone} publicationDetails={publicationDetails} /> ) : ( @@ -357,7 +354,7 @@ const Challenge = ({ challenge, closeModal }: ChallengeProps) => { {t('submit')} )} - + {challenges?.length > 1 && ( {' '} + ] + + )} {!(removed || deleted) && !isModQueue && } {cid && parentCid && } diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index 3d1aff04..5032efd8 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef, useState, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { Link, useLocation, useNavigationType, useParams } from 'react-router-dom'; import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso'; -import { Comment, useEditedComment, useReplies, useAccount, usePublishCommentModeration, useAccountComment } from '@bitsocialhq/bitsocial-react-hooks'; +import { Comment, deleteComment, useEditedComment, useReplies, useAccount, usePublishCommentModeration, useAccountComment } from '@bitsocialhq/bitsocial-react-hooks'; import getShortAddress from '../../lib/get-short-address'; import styles from '../../views/post/post.module.css'; import { shouldShowSnow } from '../../lib/snow'; @@ -188,6 +188,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos const isOverThreshold = isAwaitingApproval && timeWaiting > alertThresholdSeconds; const hasFailedState = state === 'failed'; + const canDeleteFailedPost = hasFailedState && typeof post?.index === 'number'; const postMenuProps = selectPostMenuProps(post); const pseudonymityMode = useSubplebbitField(subplebbitAddress, (sub) => sub?.features?.pseudonymityMode); @@ -223,6 +224,24 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos : openReplyModal && openReplyModal(cid, post?.number, postCid, threadNumber, subplebbitAddress); }; + const [isDeletingFailedPost, setIsDeletingFailedPost] = useState(false); + const onDeleteFailedPost = () => { + if (isDeletingFailedPost || !canDeleteFailedPost) { + return; + } + + setIsDeletingFailedPost(true); + deleteComment(post?.cid || post.index) + .then(() => { + setIsDeletingFailedPost(false); + }) + .catch((error) => { + console.error('Failed to delete failed post:', error); + alert(`Failed to delete post: ${error instanceof Error ? error.message : 'Unknown error'}`); + setIsDeletingFailedPost(false); + }); + }; + return ( <>
@@ -393,6 +412,15 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos
)} + {canDeleteFailedPost && ( + + this post failed to publish, it's not visible to other users [{' '} + {' '} + ] + + )}
{(hasThumbnail || link) && !(deleted || removed) && } diff --git a/src/hooks/use-publish-post.ts b/src/hooks/use-publish-post.ts index 44bd1033..fd586d16 100644 --- a/src/hooks/use-publish-post.ts +++ b/src/hooks/use-publish-post.ts @@ -1,6 +1,7 @@ -import { useCallback } from 'react'; +import { useCallback, useMemo, useRef } from 'react'; import { Comment, usePublishComment } from '@bitsocialhq/bitsocial-react-hooks'; import usePublishPostStore from '../stores/use-publish-post-store'; +import useChallengesStore from '../stores/use-challenges-store'; const usePublishPost = ({ subplebbitAddress }: { subplebbitAddress?: string }) => { const { author, title, content, link, spoiler, publishCommentOptions } = usePublishPostStore((state) => ({ @@ -14,6 +15,8 @@ const usePublishPost = ({ subplebbitAddress }: { subplebbitAddress?: string }) = const setPublishPostStore = usePublishPostStore((state) => state.setPublishPostStore); const resetPublishPostStore = usePublishPostStore((state) => state.resetPublishPostStore); + const addChallenge = useChallengesStore((state) => state.addChallenge); + const abandonPublishRef = useRef<(() => Promise) | undefined>(); const createBaseOptions = useCallback(() => { const baseOptions: Comment = { @@ -51,7 +54,20 @@ const usePublishPost = ({ subplebbitAddress }: { subplebbitAddress?: string }) = const resetPublishPostOptions = useCallback(() => resetPublishPostStore(), [resetPublishPostStore]); - const { index, publishComment } = usePublishComment(publishCommentOptions); + const publishOptionsWithAbandon = useMemo( + () => ({ + ...publishCommentOptions, + onChallenge: async (...args: any[]) => { + addChallenge(args, async () => { + await abandonPublishRef.current?.(); + }); + }, + }), + [addChallenge, publishCommentOptions], + ); + + const { index, publishComment, abandonPublish } = usePublishComment(publishOptionsWithAbandon); + abandonPublishRef.current = abandonPublish; return { setPublishPostOptions, diff --git a/src/hooks/use-publish-reply.ts b/src/hooks/use-publish-reply.ts index 1b06ab53..f231dce4 100644 --- a/src/hooks/use-publish-reply.ts +++ b/src/hooks/use-publish-reply.ts @@ -1,8 +1,9 @@ -import { useCallback, useMemo } from 'react'; +import { useCallback, useMemo, useRef } from 'react'; import { Comment, usePublishComment } from '@bitsocialhq/bitsocial-react-hooks'; import usePublishReplyStore from '../stores/use-publish-reply-store'; import usePostNumberStore from '../stores/use-post-number-store'; import { getQuotedCidsFromContent, mergeQuotedCids } from '../lib/utils/reply-quote-utils'; +import useChallengesStore from '../stores/use-challenges-store'; const usePublishReply = ({ cid, subplebbitAddress, postCid }: { cid: string; subplebbitAddress: string; postCid?: string }) => { const parentCid = cid; @@ -17,6 +18,8 @@ const usePublishReply = ({ cid, subplebbitAddress, postCid }: { cid: string; sub const setPublishReplyStore = usePublishReplyStore((state) => state.setPublishReplyStore); const resetPublishReplyStore = usePublishReplyStore((state) => state.resetPublishReplyStore); + const addChallenge = useChallengesStore((state) => state.addChallenge); + const abandonPublishRef = useRef<(() => Promise) | undefined>(); const createBaseOptions = useCallback(() => { const baseOptions: Comment = { @@ -58,9 +61,21 @@ const usePublishReply = ({ cid, subplebbitAddress, postCid }: { cid: string; sub const scopedNumberToCid = usePostNumberStore((state) => (subplebbitAddress ? state.numberToCid[subplebbitAddress] : undefined)); const quotedCids = useMemo(() => getQuotedCidsFromContent(content, scopedNumberToCid), [content, scopedNumberToCid]); - const publishOptions = useMemo(() => mergeQuotedCids(publishCommentOptions, quotedCids), [publishCommentOptions, quotedCids]); + const mergedPublishOptions = useMemo(() => mergeQuotedCids(publishCommentOptions, quotedCids), [publishCommentOptions, quotedCids]); + const publishOptionsWithAbandon = useMemo( + () => ({ + ...mergedPublishOptions, + onChallenge: async (...args: any[]) => { + addChallenge(args, async () => { + await abandonPublishRef.current?.(); + }); + }, + }), + [addChallenge, mergedPublishOptions], + ); - const { index, publishComment } = usePublishComment(publishOptions); + const { index, publishComment, abandonPublish } = usePublishComment(publishOptionsWithAbandon); + abandonPublishRef.current = abandonPublish; return { setPublishReplyOptions, diff --git a/src/stores/use-challenges-store.ts b/src/stores/use-challenges-store.ts index 592d5f05..c0bf8c7c 100644 --- a/src/stores/use-challenges-store.ts +++ b/src/stores/use-challenges-store.ts @@ -4,16 +4,17 @@ import { Challenge } from '@bitsocialhq/bitsocial-react-hooks'; let nextChallengeId = 0; interface State { - challenges: Array<{ challenge: Challenge; id: number }>; - addChallenge: (challenge: Challenge) => void; + challenges: Array<{ challenge: Challenge; id: number; onAbandon?: () => Promise | void }>; + addChallenge: (challenge: Challenge, onAbandon?: () => Promise | void) => void; removeChallenge: () => void; + abandonCurrentChallenge: () => Promise; } -const useChallengesStore = create((set) => ({ +const useChallengesStore = create((set, get) => ({ challenges: [], - addChallenge: (challenge: Challenge) => { + addChallenge: (challenge: Challenge, onAbandon?: () => Promise | void) => { set((state) => ({ - challenges: [...state.challenges, { challenge, id: nextChallengeId++ }], + challenges: [...state.challenges, { challenge, id: nextChallengeId++, onAbandon }], })); }, removeChallenge: () => { @@ -23,6 +24,16 @@ const useChallengesStore = create((set) => ({ return { challenges }; }); }, + abandonCurrentChallenge: async () => { + const currentChallenge = get().challenges[0]; + try { + await currentChallenge?.onAbandon?.(); + } catch (error) { + console.error('Failed to abandon challenge publication:', error); + } finally { + get().removeChallenge(); + } + }, })); export default useChallengesStore; diff --git a/src/stores/use-publish-post-store.ts b/src/stores/use-publish-post-store.ts index 9a9390a4..678d11d6 100644 --- a/src/stores/use-publish-post-store.ts +++ b/src/stores/use-publish-post-store.ts @@ -1,7 +1,6 @@ import { ChallengeVerification, Comment, PublishCommentOptions } from '@bitsocialhq/bitsocial-react-hooks'; import { create } from 'zustand'; import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils'; -import useChallengesStore from './use-challenges-store'; type SubmitState = { author?: any | undefined; @@ -16,8 +15,6 @@ type SubmitState = { resetPublishPostStore: () => void; }; -const { addChallenge } = useChallengesStore.getState(); - const usePublishPostStore = create((set) => ({ author: undefined, displayName: undefined, @@ -44,7 +41,6 @@ const usePublishPostStore = create((set) => ({ content, link, spoiler, - onChallenge: (...args: any) => addChallenge(args), onChallengeVerification: (challengeVerification: ChallengeVerification, comment: Comment) => { alertChallengeVerificationFailed(challengeVerification, comment); }, diff --git a/src/stores/use-publish-reply-store.ts b/src/stores/use-publish-reply-store.ts index 2a42a588..dcadc3be 100644 --- a/src/stores/use-publish-reply-store.ts +++ b/src/stores/use-publish-reply-store.ts @@ -1,7 +1,6 @@ import { ChallengeVerification, Comment, PublishCommentOptions } from '@bitsocialhq/bitsocial-react-hooks'; import { create } from 'zustand'; import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils'; -import useChallengesStore from './use-challenges-store'; type ReplyState = { author: { [parentCid: string]: any | undefined }; @@ -14,8 +13,6 @@ type ReplyState = { resetPublishReplyStore: (parentCid: string) => void; }; -const { addChallenge } = useChallengesStore.getState(); - const usePublishReplyStore = create((set) => ({ author: {}, displayName: {}, @@ -42,7 +39,6 @@ const usePublishReplyStore = create((set) => ({ content, link, spoiler, - onChallenge: (...args: any) => addChallenge(args), onChallengeVerification: (challengeVerification: ChallengeVerification, comment: Comment) => { alertChallengeVerificationFailed(challengeVerification, comment); }, diff --git a/src/views/post/post.module.css b/src/views/post/post.module.css index 36eae9ef..1a9b8bc0 100644 --- a/src/views/post/post.module.css +++ b/src/views/post/post.module.css @@ -582,6 +582,32 @@ font-weight: 700; } +.failedPublishNotice { + display: block; + margin-top: 4px; + color: red; + font-weight: 700; +} + +.failedDeletePostButton { + all: unset; + color: red; + cursor: pointer; + font-weight: 700; + text-decoration: underline; + text-transform: uppercase; +} + +.failedDeletePostButton:hover:not(:disabled) { + color: #b30000; +} + +.failedDeletePostButton:disabled { + cursor: wait; + opacity: 0.7; + text-decoration: none; +} + .grayEditMessage { color: var(--post-mobile-abbr-text-color); } @@ -709,4 +735,4 @@ 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } -} \ No newline at end of file +} From 9cc68768872940bfca272fb29a28d0fae9611a30 Mon Sep 17 00:00:00 2001 From: plebeius Date: Thu, 5 Mar 2026 20:47:49 +0800 Subject: [PATCH 05/19] fix(challenge flow): abandon publish immediately on modal close --- src/hooks/use-publish-post.ts | 9 +++++---- src/hooks/use-publish-reply.ts | 9 +++++---- src/stores/use-challenges-store.ts | 3 +-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/hooks/use-publish-post.ts b/src/hooks/use-publish-post.ts index fd586d16..90e2d59e 100644 --- a/src/hooks/use-publish-post.ts +++ b/src/hooks/use-publish-post.ts @@ -17,6 +17,9 @@ const usePublishPost = ({ subplebbitAddress }: { subplebbitAddress?: string }) = const resetPublishPostStore = usePublishPostStore((state) => state.resetPublishPostStore); const addChallenge = useChallengesStore((state) => state.addChallenge); const abandonPublishRef = useRef<(() => Promise) | undefined>(); + const abandonCurrentPublish = useCallback(async () => { + await abandonPublishRef.current?.(); + }, []); const createBaseOptions = useCallback(() => { const baseOptions: Comment = { @@ -58,12 +61,10 @@ const usePublishPost = ({ subplebbitAddress }: { subplebbitAddress?: string }) = () => ({ ...publishCommentOptions, onChallenge: async (...args: any[]) => { - addChallenge(args, async () => { - await abandonPublishRef.current?.(); - }); + addChallenge(args, abandonCurrentPublish); }, }), - [addChallenge, publishCommentOptions], + [abandonCurrentPublish, addChallenge, publishCommentOptions], ); const { index, publishComment, abandonPublish } = usePublishComment(publishOptionsWithAbandon); diff --git a/src/hooks/use-publish-reply.ts b/src/hooks/use-publish-reply.ts index f231dce4..a73802e5 100644 --- a/src/hooks/use-publish-reply.ts +++ b/src/hooks/use-publish-reply.ts @@ -20,6 +20,9 @@ const usePublishReply = ({ cid, subplebbitAddress, postCid }: { cid: string; sub const resetPublishReplyStore = usePublishReplyStore((state) => state.resetPublishReplyStore); const addChallenge = useChallengesStore((state) => state.addChallenge); const abandonPublishRef = useRef<(() => Promise) | undefined>(); + const abandonCurrentPublish = useCallback(async () => { + await abandonPublishRef.current?.(); + }, []); const createBaseOptions = useCallback(() => { const baseOptions: Comment = { @@ -66,12 +69,10 @@ const usePublishReply = ({ cid, subplebbitAddress, postCid }: { cid: string; sub () => ({ ...mergedPublishOptions, onChallenge: async (...args: any[]) => { - addChallenge(args, async () => { - await abandonPublishRef.current?.(); - }); + addChallenge(args, abandonCurrentPublish); }, }), - [addChallenge, mergedPublishOptions], + [abandonCurrentPublish, addChallenge, mergedPublishOptions], ); const { index, publishComment, abandonPublish } = usePublishComment(publishOptionsWithAbandon); diff --git a/src/stores/use-challenges-store.ts b/src/stores/use-challenges-store.ts index c0bf8c7c..d73e5a6e 100644 --- a/src/stores/use-challenges-store.ts +++ b/src/stores/use-challenges-store.ts @@ -26,12 +26,11 @@ const useChallengesStore = create((set, get) => ({ }, abandonCurrentChallenge: async () => { const currentChallenge = get().challenges[0]; + get().removeChallenge(); try { await currentChallenge?.onAbandon?.(); } catch (error) { console.error('Failed to abandon challenge publication:', error); - } finally { - get().removeChallenge(); } }, })); From 65731ceb3a6cb03445cc3898f1a688994161497a Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 14:55:40 +0800 Subject: [PATCH 06/19] fix(markdown): handle unavailable reply quote links --- .../comment-content/comment-content.tsx | 5 +- src/components/markdown/markdown.tsx | 7 +- .../reply-quote-preview.tsx | 124 +++++++++++++----- .../utils/__tests__/quote-link-utils.test.ts | 45 +++++++ src/lib/utils/quote-link-utils.ts | 17 +++ src/views/post/post.module.css | 7 + 6 files changed, 172 insertions(+), 33 deletions(-) create mode 100644 src/lib/utils/__tests__/quote-link-utils.test.ts create mode 100644 src/lib/utils/quote-link-utils.ts diff --git a/src/components/comment-content/comment-content.tsx b/src/components/comment-content/comment-content.tsx index d8c00dd5..ac412b59 100644 --- a/src/components/comment-content/comment-content.tsx +++ b/src/components/comment-content/comment-content.tsx @@ -17,12 +17,15 @@ import styles from '../../views/post/post.module.css'; import capitalize from 'lodash/capitalize'; const QuotedCidLink = ({ cid, postCid }: { cid: string; postCid: string }) => { + const quotedNumber = usePostNumberStore((state) => state.cidToNumber[cid]); const commentFromStore = useSubplebbitsPagesStore((state) => state.comments[cid]); const commentFromHook = useComment({ commentCid: cid, onlyIfCached: true }); // Prefer hook version to ensure 'number' property is populated for deeper nested replies in Virtuoso const quotedComment = commentFromHook?.number !== undefined ? commentFromHook : commentFromStore; const isOP = cid === postCid; - return ; + const isUnavailable = !quotedComment || quotedComment.deleted || quotedComment.removed; + + return ; }; const useScopedCidToNumber = (cids: string[]) => { diff --git a/src/components/markdown/markdown.tsx b/src/components/markdown/markdown.tsx index 0beac50a..20f551f4 100644 --- a/src/components/markdown/markdown.tsx +++ b/src/components/markdown/markdown.tsx @@ -10,6 +10,7 @@ import styles from './markdown.module.css'; import { Link, useLocation, useParams } from 'react-router-dom'; import { canEmbed } from '../embed'; import { is5chanLink, transform5chanLinkToInternal, isValidCrossboardPattern } from '../../lib/utils/url-utils'; +import { isUnavailableQuoteTarget } from '../../lib/utils/quote-link-utils'; import usePostNumberStore from '../../stores/use-post-number-store'; import useSubplebbitsPagesStore from '@bitsocialhq/bitsocial-react-hooks/dist/stores/subplebbits-pages'; import { useComment } from '@bitsocialhq/bitsocial-react-hooks'; @@ -276,8 +277,10 @@ const NumberQuoteLink = ({ number, threadPostCid, subplebbitAddress }: { number: const comment = commentFromHook?.number !== undefined ? commentFromHook : commentFromStore; const isOP = Boolean(threadPostCid && cid === threadPostCid); - if (!comment) { - return {`>>${number}`}; + if (!comment || isUnavailableQuoteTarget(comment)) { + return ( + + ); } return ; diff --git a/src/components/reply-quote-preview/reply-quote-preview.tsx b/src/components/reply-quote-preview/reply-quote-preview.tsx index 534d2a39..5d7c4f96 100644 --- a/src/components/reply-quote-preview/reply-quote-preview.tsx +++ b/src/components/reply-quote-preview/reply-quote-preview.tsx @@ -5,6 +5,7 @@ import { Comment, useAccount } from '@bitsocialhq/bitsocial-react-hooks'; import { useFloating, offset, shift, size, autoUpdate, Placement } from '@floating-ui/react'; import { useDirectories } from '../../hooks/use-directories'; import { getBoardPath } from '../../lib/utils/route-utils'; +import { formatQuoteNumber, isUnavailableQuoteTarget, shouldShowFloatingQuotePreview } from '../../lib/utils/quote-link-utils'; import useIsMobile from '../../hooks/use-is-mobile'; import styles from '../../views/post/post.module.css'; import { Post } from '../../views/post'; @@ -14,6 +15,8 @@ interface ReplyQuotePreviewProps { backlinkReply?: Comment; isQuotelinkReply?: boolean; quotelinkReply?: Comment; + quotelinkNumber?: number; + isQuotelinkUnavailable?: boolean; isOP?: boolean; showTrailingBreak?: boolean; } @@ -80,7 +83,16 @@ const scrollToReplyOnPage = (cid: string) => { return true; }; -const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, isQuotelinkReply, isOP, showTrailingBreak = true }: ReplyQuotePreviewProps) => { +const DesktopQuotePreview = ({ + backlinkReply, + quotelinkReply, + quotelinkNumber, + isBacklinkReply, + isQuotelinkReply, + isQuotelinkUnavailable, + isOP, + showTrailingBreak = true, +}: ReplyQuotePreviewProps) => { const [hoveredCid, setHoveredCid] = useState(null); const [outOfViewCid, setOutOfViewCid] = useState(null); const [placement, setPlacement] = useState('right'); @@ -194,26 +206,45 @@ const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, i const account = useAccount(); + const resolvedQuotelinkNumber = quotelinkReply?.number ?? quotelinkNumber; + const resolvedQuotelinkCid = quotelinkReply?.cid; + const resolvedQuotelinkSubplebbitAddress = quotelinkReply?.subplebbitAddress; + const quotelinkUnavailable = Boolean(isQuotelinkUnavailable || isUnavailableQuoteTarget(quotelinkReply)); + const quotelinkClassName = quotelinkUnavailable ? `${styles.quoteLink} ${styles.quoteLinkUnavailable}` : styles.quoteLink; const quotelinkBoardPath = quotelinkReply?.subplebbitAddress ? getBoardPath(quotelinkReply.subplebbitAddress, directories) : undefined; const quotelinkRoute = quotelinkReply?.cid ? (quotelinkBoardPath ? `/${quotelinkBoardPath}/thread/${quotelinkReply.cid}` : `/thread/${quotelinkReply.cid}`) : '#'; + const shouldShowQuotelinkPreview = shouldShowFloatingQuotePreview({ + hoveredCid, + outOfViewCid, + quoteCid: resolvedQuotelinkCid, + isUnavailable: quotelinkUnavailable, + }); + const quotelinkLabel = ( + <> + {formatQuoteNumber(resolvedQuotelinkNumber)} + {isOP && ' (OP)'} + {quotelinkReply?.author?.address === account?.author?.address && ' (You)'} + + ); const replyQuotelink = ( <> - handleMouseOver(quotelinkReply?.cid)} - onMouseLeave={() => handleMouseLeave(quotelinkReply?.cid)} - onClick={(e) => handleClick(e, quotelinkReply?.cid, quotelinkReply?.subplebbitAddress, !!isOP)} - > - {`>>${quotelinkReply?.number ?? '?'}`} - {isOP && ' (OP)'} - {quotelinkReply?.author?.address === account?.author?.address && ' (You)'} - + {quotelinkUnavailable ? ( + {quotelinkLabel} + ) : ( + handleMouseOver(resolvedQuotelinkCid)} + onMouseLeave={() => handleMouseLeave(resolvedQuotelinkCid)} + onClick={(e) => handleClick(e, resolvedQuotelinkCid, resolvedQuotelinkSubplebbitAddress, !!isOP)} + > + {quotelinkLabel} + + )} {showTrailingBreak &&
} - {hoveredCid === quotelinkReply?.cid && - outOfViewCid === quotelinkReply?.cid && + {shouldShowQuotelinkPreview && createPortal(
@@ -226,7 +257,16 @@ const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, i return isBacklinkReply ? replyBacklink : isQuotelinkReply && replyQuotelink; }; -const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, isQuotelinkReply, isOP, showTrailingBreak = true }: ReplyQuotePreviewProps) => { +const MobileQuotePreview = ({ + backlinkReply, + quotelinkReply, + quotelinkNumber, + isBacklinkReply, + isQuotelinkReply, + isQuotelinkUnavailable, + isOP, + showTrailingBreak = true, +}: ReplyQuotePreviewProps) => { const [hoveredCid, setHoveredCid] = useState(null); const [outOfViewCid, setOutOfViewCid] = useState(null); const directories = useDirectories(); @@ -320,37 +360,48 @@ const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, is ); const account = useAccount(); + const resolvedQuotelinkNumber = quotelinkReply?.number ?? quotelinkNumber; + const resolvedQuotelinkCid = quotelinkReply?.cid; + const resolvedQuotelinkSubplebbitAddress = quotelinkReply?.subplebbitAddress; + const quotelinkUnavailable = Boolean(isQuotelinkUnavailable || isUnavailableQuoteTarget(quotelinkReply)); + const quotelinkClassName = quotelinkUnavailable ? `${styles.quoteLink} ${styles.quoteLinkUnavailable}` : styles.quoteLink; + const shouldShowQuotelinkPreview = shouldShowFloatingQuotePreview({ + hoveredCid, + outOfViewCid, + quoteCid: resolvedQuotelinkCid, + isUnavailable: quotelinkUnavailable, + }); const replyQuotelink = ( <> handleMouseOver(quotelinkReply?.cid)} - onMouseLeave={() => handleMouseLeave(quotelinkReply?.cid)} + ref={quotelinkUnavailable ? undefined : refs.setReference} + className={quotelinkClassName} + onMouseOver={quotelinkUnavailable ? undefined : () => handleMouseOver(resolvedQuotelinkCid)} + onMouseLeave={quotelinkUnavailable ? undefined : () => handleMouseLeave(resolvedQuotelinkCid)} > - {`>>${quotelinkReply?.number ?? '?'}`} + {formatQuoteNumber(resolvedQuotelinkNumber)} {isOP && ' (OP)'} {quotelinkReply?.author?.address === account?.author?.address && ' (You)'} - {quotelinkReply?.number && + {!quotelinkUnavailable && + resolvedQuotelinkNumber && (() => { - const quotelinkBoardPath = quotelinkReply?.subplebbitAddress ? getBoardPath(quotelinkReply.subplebbitAddress, directories) : undefined; - const quotelinkRoute = quotelinkReply?.cid + const quotelinkBoardPath = resolvedQuotelinkSubplebbitAddress ? getBoardPath(resolvedQuotelinkSubplebbitAddress, directories) : undefined; + const quotelinkRoute = resolvedQuotelinkCid ? quotelinkBoardPath - ? `/${quotelinkBoardPath}/thread/${quotelinkReply.cid}` - : `/thread/${quotelinkReply.cid}` + ? `/${quotelinkBoardPath}/thread/${resolvedQuotelinkCid}` + : `/thread/${resolvedQuotelinkCid}` : '#'; return ( - handleClick(e, quotelinkReply?.cid, quotelinkReply?.subplebbitAddress, !!isOP)}> + handleClick(e, resolvedQuotelinkCid, resolvedQuotelinkSubplebbitAddress, !!isOP)}> {' '} # ); })()} {showTrailingBreak &&
} - {hoveredCid === quotelinkReply?.cid && - outOfViewCid === quotelinkReply?.cid && + {shouldShowQuotelinkPreview && createPortal(
@@ -363,15 +414,26 @@ const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, is return isBacklinkReply ? replyBacklink : isQuotelinkReply && replyQuotelink; }; -const ReplyQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, isQuotelinkReply, isOP, showTrailingBreak }: ReplyQuotePreviewProps) => { +const ReplyQuotePreview = ({ + backlinkReply, + quotelinkReply, + quotelinkNumber, + isBacklinkReply, + isQuotelinkReply, + isQuotelinkUnavailable, + isOP, + showTrailingBreak, +}: ReplyQuotePreviewProps) => { const isMobile = useIsMobile(); return isMobile ? ( @@ -379,8 +441,10 @@ const ReplyQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, isQ diff --git a/src/lib/utils/__tests__/quote-link-utils.test.ts b/src/lib/utils/__tests__/quote-link-utils.test.ts new file mode 100644 index 00000000..1642f81f --- /dev/null +++ b/src/lib/utils/__tests__/quote-link-utils.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from 'vitest'; +import { formatQuoteNumber, isUnavailableQuoteTarget, shouldShowFloatingQuotePreview } from '../quote-link-utils'; + +describe('quote-link-utils', () => { + it('formats quote numbers with the expected prefix', () => { + expect(formatQuoteNumber(123)).toBe('>>123'); + expect(formatQuoteNumber()).toBe('>>?'); + }); + + it('marks deleted and removed comments as unavailable quote targets', () => { + expect(isUnavailableQuoteTarget(undefined)).toBe(false); + expect(isUnavailableQuoteTarget({ deleted: true, removed: false })).toBe(true); + expect(isUnavailableQuoteTarget({ deleted: false, removed: true })).toBe(true); + expect(isUnavailableQuoteTarget({ deleted: false, removed: false })).toBe(false); + }); + + it('only shows floating previews for available targets that are hovered out of view', () => { + expect( + shouldShowFloatingQuotePreview({ + hoveredCid: 'cid-1', + outOfViewCid: 'cid-1', + quoteCid: 'cid-1', + isUnavailable: false, + }), + ).toBe(true); + + expect( + shouldShowFloatingQuotePreview({ + hoveredCid: 'cid-1', + outOfViewCid: 'cid-1', + quoteCid: 'cid-1', + isUnavailable: true, + }), + ).toBe(false); + + expect( + shouldShowFloatingQuotePreview({ + hoveredCid: 'cid-1', + outOfViewCid: 'cid-2', + quoteCid: 'cid-1', + isUnavailable: false, + }), + ).toBe(false); + }); +}); diff --git a/src/lib/utils/quote-link-utils.ts b/src/lib/utils/quote-link-utils.ts new file mode 100644 index 00000000..83a4593c --- /dev/null +++ b/src/lib/utils/quote-link-utils.ts @@ -0,0 +1,17 @@ +import type { Comment } from '@bitsocialhq/bitsocial-react-hooks'; + +export const formatQuoteNumber = (number?: number) => `>>${number ?? '?'}`; + +export const isUnavailableQuoteTarget = (comment?: Partial> | null) => Boolean(comment?.deleted || comment?.removed); + +export const shouldShowFloatingQuotePreview = ({ + hoveredCid, + outOfViewCid, + quoteCid, + isUnavailable, +}: { + hoveredCid: string | null; + outOfViewCid: string | null; + quoteCid?: string; + isUnavailable?: boolean; +}) => Boolean(quoteCid && !isUnavailable && hoveredCid === quoteCid && outOfViewCid === quoteCid); diff --git a/src/views/post/post.module.css b/src/views/post/post.module.css index 1a9b8bc0..0298b931 100644 --- a/src/views/post/post.module.css +++ b/src/views/post/post.module.css @@ -490,6 +490,13 @@ cursor: pointer; } +.quoteLinkUnavailable, +.quoteLinkUnavailable:hover { + color: var(--post-quotelink-text-color); + text-decoration: line-through; + cursor: default; +} + .replyMobile { padding-top: 7px; content-visibility: auto; From 14262fe887a4b548a27e78ef75d3a935fff465c7 Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 19:19:05 +0800 Subject: [PATCH 07/19] chore: improve wording, translations --- public/translations/ar/default.json | 2 +- public/translations/bn/default.json | 2 +- public/translations/cs/default.json | 2 +- public/translations/da/default.json | 2 +- public/translations/de/default.json | 2 +- public/translations/el/default.json | 2 +- public/translations/en/default.json | 2 +- public/translations/es/default.json | 2 +- public/translations/fa/default.json | 2 +- public/translations/fi/default.json | 2 +- public/translations/fil/default.json | 2 +- public/translations/fr/default.json | 2 +- public/translations/he/default.json | 2 +- public/translations/hi/default.json | 2 +- public/translations/hu/default.json | 2 +- public/translations/id/default.json | 2 +- public/translations/it/default.json | 2 +- public/translations/ja/default.json | 2 +- public/translations/ko/default.json | 2 +- public/translations/mr/default.json | 2 +- public/translations/nl/default.json | 2 +- public/translations/no/default.json | 2 +- public/translations/pl/default.json | 2 +- public/translations/pt/default.json | 2 +- public/translations/ro/default.json | 2 +- public/translations/ru/default.json | 2 +- public/translations/sq/default.json | 2 +- public/translations/sv/default.json | 2 +- public/translations/te/default.json | 2 +- public/translations/th/default.json | 2 +- public/translations/tr/default.json | 2 +- public/translations/uk/default.json | 2 +- public/translations/ur/default.json | 2 +- public/translations/vi/default.json | 2 +- public/translations/zh/default.json | 2 +- src/components/site-legal-meta/site-legal-meta.tsx | 2 +- src/views/faq/faq.tsx | 4 ++-- 37 files changed, 38 insertions(+), 38 deletions(-) diff --git a/public/translations/ar/default.json b/public/translations/ar/default.json index 89866618..f4709908 100644 --- a/public/translations/ar/default.json +++ b/public/translations/ar/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "ما هو 5chan؟", "go": "اذهب", "5chan_description": "5chan لوحة صور لامركزية بالكامل ومفتوحة المصدر، حيث يمكن لأي شخص إنشاء وامتلاك عدد غير محدود من اللوحات بشكل تشفيري. يضيف مالكو اللوحات ويشرفون على لوحتهم ويحددون <1>Rules. جميع البيانات نصية فقط وتُشارك من نظير إلى نظير، بما في ذلك روابط تضمين الصور. راجع <2>FAQs لمعرفة المزيد. لا تتردد في النقر على لوحة أدناه تهمك والبدء فوراً!", - "no_global_rules_info": "5chan تطبيق بدون خادم، هذا الموقع مجرد طريقة واحدة لفتحه. لتجنب الاعتماد على توفر الموقع، <1>حمّل إصداراً.", + "no_global_rules_info": "5chan تطبيق بدون خوادم، هذا الموقع مجرد طريقة واحدة لفتحه. لتجنب الاعتماد على توفر الموقع، <1>حمّل التطبيق.", "boards": "منتديات", "popular_threads": "المواضيع الشائعة", "options": "الخيارات", diff --git a/public/translations/bn/default.json b/public/translations/bn/default.json index ff3dd91a..d80e12d2 100644 --- a/public/translations/bn/default.json +++ b/public/translations/bn/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan কি?", "go": "যাও", "5chan_description": "5chan একটি সম্পূর্ণ বিকেন্দ্রীভূত এবং ওপেন-সোর্স ইমেজবোর্ড, যেখানে যে কেউ সীমাহীন বোর্ড তৈরি করতে এবং ক্রিপ্টোগ্রাফিকভাবে মালিকানা নিতে পারে। বোর্ড মালিকরা তাদের বোর্ড হোস্ট এবং মডারেট করেন এবং এর <1>Rules সেট করেন। সমস্ত ডেটা শুধুমাত্র টেক্সট এবং পিয়ার-টু-পিয়ার শেয়ার করা হয়, এম্বেড ইমেজের লিঙ্ক সহ। আরও জানতে <2>FAQs দেখুন। নীচের যে বোর্ডে আপনার আগ্রহ আছে সেটিতে ক্লিক করতে এবং সরাসরি যোগ দিতে নির্দ্বিধায়!", - "no_global_rules_info": "5chan একটি সার্ভারলেস অ্যাপ, এই ওয়েবসাইট এটি খোলার একটি উপায় মাত্র। ওয়েবসাইটের আপটাইমের উপর নির্ভরতা এড়াতে <1>একটি রিলিজ ডাউনলোড করুন।", + "no_global_rules_info": "5chan একটি সার্ভারলেস অ্যাপ, এই ওয়েবসাইট এটি খোলার একটি উপায় মাত্র। ওয়েবসাইটের আপটাইমের উপর নির্ভরতা এড়াতে <1>অ্যাপ ডাউনলোড করুন।", "boards": "বোর্ডসমূহ", "popular_threads": "জনপ্রিয় থ্রেডগুলি", "options": "বিকল্পসমূহ", diff --git a/public/translations/cs/default.json b/public/translations/cs/default.json index b6aa9318..a553dbac 100644 --- a/public/translations/cs/default.json +++ b/public/translations/cs/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Co je 5chan?", "go": "jít", "5chan_description": "5chan je plně decentralizované a open-source imageboard, kde kdokoli může vytvářet a kryptograficky vlastnit neomezený počet desek. Majitelé desek hostují a moderují svou desku a nastavují její <1>Rules. Všechna data jsou pouze textová a sdílená peer-to-peer, včetně odkazů na vložené obrázky. Pro více informací se podívejte na <2>FAQs. Klikněte na libovolnou desku níže a můžete začít!", - "no_global_rules_info": "5chan je bezserverová aplikace, tento web je jen jedním způsobem, jak ji otevřít. Abyste se nebyli závislí na dostupnosti webu, <1>stáhněte si vydání.", + "no_global_rules_info": "5chan je bezserverová aplikace, tento web je jen jeden způsob, jak ji otevřít. Abyste se nebyli závislí na dostupnosti webu, <1>stáhněte si aplikaci.", "boards": "nástěnky", "popular_threads": "Oblíbená vlákna", "options": "Možnosti", diff --git a/public/translations/da/default.json b/public/translations/da/default.json index 2eae9b12..f17e1c51 100644 --- a/public/translations/da/default.json +++ b/public/translations/da/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Hvad er 5chan?", "go": "gå", "5chan_description": "5chan er et fuldt decentraliseret og open-source imageboard, hvor alle kan oprette og kryptografisk eje ubegrænsede boards. Board-ejere hoster og modererer deres board og sætter dets <1>Rules. Alle data er kun tekst og deles peer-to-peer, inklusiv links til indlejrede billeder. Tjek <2>FAQs for at lære mere. Klik gerne på et board nedenfor der interesserer dig og kom i gang!", - "no_global_rules_info": "5chan er en serverløs app, denne hjemmeside er blot én måde at åbne den på. For at undgå at stole på hjemmesidens oppetid, <1>hent en udgivelse.", + "no_global_rules_info": "5chan er en serverløs app, denne hjemmeside er blot én måde at åbne den på. For at undgå at stole på hjemmesidens oppetid, <1>hent appen.", "boards": "opslagstavler", "popular_threads": "Populære tråde", "options": "Indstillinger", diff --git a/public/translations/de/default.json b/public/translations/de/default.json index 3f2138b6..b5a6aab3 100644 --- a/public/translations/de/default.json +++ b/public/translations/de/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Was ist 5chan?", "go": "gehen", "5chan_description": "5chan ist ein vollständig dezentrales und quelloffenes Imageboard, auf dem jeder unbegrenzt Boards erstellen und kryptografisch besitzen kann. Board-Inhaber hosten und moderieren ihr Board und legen dessen <1>Rules fest. Alle Daten sind rein textbasiert und werden peer-to-peer geteilt, inklusive Links zu eingebetteten Bildern. Schau dir die <2>FAQs an, um mehr zu erfahren. Klicke einfach auf ein Board unten, das dich interessiert, und leg los!", - "no_global_rules_info": "5chan ist eine serverlose App, diese Website ist nur eine Möglichkeit, sie zu öffnen. Um nicht von der Verfügbarkeit der Website abhängig zu sein, <1>lade eine Version herunter.", + "no_global_rules_info": "5chan ist eine serverlose App, diese Website ist nur eine Möglichkeit, sie zu öffnen. Um nicht von der Verfügbarkeit der Website abhängig zu sein, <1>lade die App herunter.", "boards": "Foren", "popular_threads": "Beliebte Threads", "options": "Optionen", diff --git a/public/translations/el/default.json b/public/translations/el/default.json index e62e50c3..190721b2 100644 --- a/public/translations/el/default.json +++ b/public/translations/el/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Τι είναι το 5chan;", "go": "πήγαινε", "5chan_description": "Το 5chan είναι ένα πλήρως αποκεντρωμένο και ανοιχτού κώδικα imageboard, όπου οποιοσδήποτε μπορεί να δημιουργήσει και να κατέχει κρυπτογραφικά απεριόριστες σανίδες. Οι ιδιοκτήτες σανίδων φιλοξενούν και ελέγχουν τη σανίδα τους και ορίζουν τους <1>Rules. Όλα τα δεδομένα είναι μόνο κείμενο και κοινοποιούνται peer-to-peer, συμπεριλαμβανομένων συνδέσμων για ενσωματωμένες εικόνες. Δείτε τα <2>FAQs για να μάθετε περισσότερα. Μη διστάσετε να κάνετε κλικ σε μια σανίδα παρακάτω που σας ενδιαφέρει και ξεκινήστε!", - "no_global_rules_info": "Το 5chan είναι μια εφαρμογή χωρίς διακομιστή, αυτός ο ιστότοπος είναι απλώς ένας τρόπος να την ανοίξετε. Για να μην εξαρτάστε από τη διαθεσιμότητα του ιστότοπου, <1>κατεβάστε μια έκδοση.", + "no_global_rules_info": "Το 5chan είναι μια εφαρμογή χωρίς διακομιστές, αυτός ο ιστότοπος είναι απλώς ένας τρόπος να την ανοίξετε. Για να αποφύγετε την εξάρτηση από τη διαθεσιμότητα του ιστότοπου, <1>κατεβάστε την εφαρμογή.", "boards": "διαδικτυακές πινακίδες", "popular_threads": "Δημοφιλή νήματα", "options": "Επιλογές", diff --git a/public/translations/en/default.json b/public/translations/en/default.json index f6ecd47a..b8f959f2 100644 --- a/public/translations/en/default.json +++ b/public/translations/en/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "What is 5chan?", "go": "go", "5chan_description": "5chan is a fully decentralized and open-source imageboard, where anyone can create and cryptographically own unlimited boards. Board owners host and moderate their board, and set its <1>Rules. All data is text-only and it's shared peer-to-peer, including links to embed images. Check out the <2>FAQs to learn more. Feel free to click on a board below that interests you and jump right in!", - "no_global_rules_info": "5chan is a serverless app, this website is just one way to open it. To avoid relying on the website's uptime, <1>download a release.", + "no_global_rules_info": "5chan is a serverless app, this website is just one way to open it. To avoid relying on the website's uptime, <1>download the app.", "boards": "boards", "popular_threads": "Popular threads", "options": "Options", diff --git a/public/translations/es/default.json b/public/translations/es/default.json index 95fc3a59..f6358d5e 100644 --- a/public/translations/es/default.json +++ b/public/translations/es/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "¿Qué es 5chan?", "go": "ir", "5chan_description": "5chan es un imageboard totalmente descentralizado y de código abierto, donde cualquiera puede crear y poseer criptográficamente tableros ilimitados. Los propietarios de tableros alojan y moderan su tablero y establecen sus <1>Rules. Todos los datos son solo texto y se comparten peer-to-peer, incluyendo enlaces para incrustar imágenes. Consulta las <2>FAQs para saber más. ¡Haz clic en cualquier tablero de abajo que te interese y empieza!", - "no_global_rules_info": "5chan es una app sin servidor, este sitio web es solo una forma de abrirlo. Para no depender del tiempo de actividad del sitio, <1>descarga una versión.", + "no_global_rules_info": "5chan es una aplicación sin servidor, este sitio web es solo una forma de abrirla. Para no depender del tiempo de actividad del sitio, <1>descarga la aplicación.", "boards": "foros", "popular_threads": "Hilos populares", "options": "Opciones", diff --git a/public/translations/fa/default.json b/public/translations/fa/default.json index 092ae9ae..5dc0d85c 100644 --- a/public/translations/fa/default.json +++ b/public/translations/fa/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan چیست؟", "go": "برو", "5chan_description": "5chan یک imageboard کاملاً غیرمتمرکز و متن‌باز است که هر کسی می‌تواند تخته‌های نامحدود ایجاد کند و به صورت رمزنگاری مالک آن‌ها شود. مالکان تخته، تخته خود را میزبانی و نظارت می‌کنند و <1>Rules آن را تعیین می‌کنند. تمام داده‌ها فقط متنی هستند و به صورت peer-to-peer به اشتراک گذاشته می‌شوند، از جمله لینک‌های تصاویر جاسازی شده. برای اطلاعات بیشتر <2>FAQs را ببینید. روی هر تخته‌ای که به آن علاقه دارید کلیک کنید و شروع کنید!", - "no_global_rules_info": "5chan یک اپلیکیشن بدون سرور است، این وب‌سایت تنها یکی از راه‌های باز کردن آن است. برای جلوگیری از وابستگی به در دسترس بودن وب‌سایت، <1>یک نسخه دانلود کنید.", + "no_global_rules_info": "5chan یک اپلیکیشن بدون سرور است، این وب‌سایت تنها یکی از راه‌های باز کردن آن است. برای جلوگیری از وابستگی به در دسترس بودن وب‌سایت، <1>اپلیکیشن را دانلود کنید.", "boards": "تالارهای پیام", "popular_threads": "نخستین موضوعات", "options": "گزینه‌ها", diff --git a/public/translations/fi/default.json b/public/translations/fi/default.json index 188a09eb..6e5af732 100644 --- a/public/translations/fi/default.json +++ b/public/translations/fi/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Mikä on 5chan?", "go": "mennä", "5chan_description": "5chan on täysin hajautettu ja avoimen lähdekoodin imageboard, jossa kuka tahansa voi luoda ja kryptografisesti omistaa rajattomasti lautia. Lautan omistajat isännöivät ja moderointavat lautaa ja asettavat sen <1>Rules. Kaikki data on vain tekstiä ja jaetaan peer-to-peer -verkossa, mukaan lukien linkit upotettaviin kuviin. Lue lisää <2>FAQs-osiosta. Voit vapaasti klikata alla olevaa lautaa, joka kiinnostaa sinua, ja aloittaa!", - "no_global_rules_info": "5chan on palvelimeton sovellus, tämä sivusto on vain yksi tapa avata se. Jotta et joutuisi luottamaan sivuston käytettävyyteen, <1>lataa julkaisu.", + "no_global_rules_info": "5chan on palvelimeton sovellus, tämä verkkosivusto on vain yksi tapa avata se. Jotta et joutuisi luottamaan verkkosivuston saatavuuteen, <1>lataa sovellus.", "boards": "foorumit", "popular_threads": "Suositut langat", "options": "Vaihtoehdot", diff --git a/public/translations/fil/default.json b/public/translations/fil/default.json index d51f1c72..35f6181c 100644 --- a/public/translations/fil/default.json +++ b/public/translations/fil/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Ano ang 5chan?", "go": "pumunta", "5chan_description": "Ang 5chan ay isang ganap na desentralisado at open-source na imageboard, kung saan sinuman ay maaaring lumikha at kriptograpikong magmay-ari ng walang limitasyong mga board. Ang mga may-ari ng board ay nagho-host at nagmo-moderate ng kanilang board, at nagtatakda ng <1>Rules nito. Lahat ng data ay text-only at ibinabahagi peer-to-peer, kasama ang mga link para sa embed na mga larawan. Tingnan ang <2>FAQs para matuto pa. Huwag mag-atubiling i-click ang anumang board sa ibaba na interesado ka at sumali na!", - "no_global_rules_info": "Ang 5chan ay isang serverless na app, ang website na ito ay isang paraan lamang para buksan ito. Para hindi umasa sa uptime ng website, <1>mag-download ng release.", + "no_global_rules_info": "Ang 5chan ay isang serverless na app, ang website na ito ay isang paraan lamang para buksan ito. Upang hindi umasa sa uptime ng website, <1>i-download ang app.", "boards": "mga board", "popular_threads": "Mga popular na thread", "options": "Mga Opsyon", diff --git a/public/translations/fr/default.json b/public/translations/fr/default.json index fda406a3..feaabafe 100644 --- a/public/translations/fr/default.json +++ b/public/translations/fr/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Qu'est-ce que 5chan?", "go": "aller", "5chan_description": "5chan est un imageboard entièrement décentralisé et open-source, où chacun peut créer et posséder cryptographiquement des boards illimités. Les propriétaires de boards hébergent et modèrent leur board et définissent ses <1>Rules. Toutes les données sont en texte uniquement et partagées en peer-to-peer, y compris les liens pour intégrer des images. Consultez les <2>FAQs pour en savoir plus. N'hésitez pas à cliquer sur un board ci-dessous qui vous intéresse et à vous lancer !", - "no_global_rules_info": "5chan est une application sans serveur, ce site web n'est qu'une façon de l'ouvrir. Pour ne pas dépendre de la disponibilité du site, <1>téléchargez une version.", + "no_global_rules_info": "5chan est une application sans serveur, ce site web n'est qu'une façon de l'ouvrir. Pour ne pas dépendre de la disponibilité du site, <1>téléchargez l'application.", "boards": "forums", "popular_threads": "Fils populaires", "options": "Options", diff --git a/public/translations/he/default.json b/public/translations/he/default.json index 3a45ebd6..53a4a99e 100644 --- a/public/translations/he/default.json +++ b/public/translations/he/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "מה זה 5chan?", "go": "לך", "5chan_description": "5chan הוא imageboard מבוזר לחלוטין וקוד פתוח, שבו כל אחד יכול ליצור ולבעלות קריפטוגרפית על לוחות בלתי מוגבלים. בעלי לוחות מארחים ומנהלים את הלוח שלהם ומגדירים את <1>Rules שלו. כל הנתונים הם טקסט בלבד ומשותפים peer-to-peer, כולל קישורים להטמעת תמונות. בדוק את <2>FAQs כדי ללמוד עוד. אל תהסס ללחוץ על לוח למטה שמעניין אותך ולהצטרף!", - "no_global_rules_info": "5chan הוא אפליקציה ללא שרת, האתר הזה הוא רק דרך אחת לפתוח אותה. כדי לא להסתמך על זמינות האתר, <1>הורד גרסה.", + "no_global_rules_info": "5chan הוא אפליקציה ללא שרת, האתר הזה הוא רק דרך אחת לפתוח אותה. כדי לא להסתמך על זמינות האתר, <1>הורד את האפליקציה.", "boards": "פורומים", "popular_threads": "אשכולות פופולריים", "options": "אפשרויות", diff --git a/public/translations/hi/default.json b/public/translations/hi/default.json index 0781292d..31b5368d 100644 --- a/public/translations/hi/default.json +++ b/public/translations/hi/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan क्या है?", "go": "जाओ", "5chan_description": "5chan एक पूरी तरह से विकेंद्रीकृत और ओपन-सोर्स इमेजबोर्ड है, जहाँ कोई भी असीमित बोर्ड बना सकता है और क्रिप्टोग्राफिक रूप से उनका मालिक हो सकता है। बोर्ड मालिक अपने बोर्ड को होस्ट और मॉडरेट करते हैं और इसके <1>Rules सेट करते हैं। सभी डेटा केवल टेक्स्ट है और इसे पीयर-टू-पीयर साझा किया जाता है, जिसमें एम्बेड इमेज के लिंक शामिल हैं। अधिक जानने के लिए <2>FAQs देखें। नीचे दिए गए किसी भी बोर्ड पर क्लिक करने में संकोच न करें जो आपको रुचिकर लगे और शुरू करें!", - "no_global_rules_info": "5chan एक सर्वरलेस ऐप है, यह वेबसाइट इसे खोलने का सिर्फ एक तरीका है। वेबसाइट की अपटाइम पर निर्भरता से बचने के लिए <1>एक रिलीज़ डाउनलोड करें।", + "no_global_rules_info": "5chan एक सर्वरलेस ऐप है, यह वेबसाइट इसे खोलने का सिर्फ एक तरीका है। वेबसाइट की अपटाइम पर निर्भर होने से बचने के लिए <1>ऐप डाउनलोड करें।", "boards": "मंच", "popular_threads": "लोकप्रिय थ्रेड्स", "options": "विकल्प", diff --git a/public/translations/hu/default.json b/public/translations/hu/default.json index 76cef903..9f3d3ce8 100644 --- a/public/translations/hu/default.json +++ b/public/translations/hu/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Mi az a 5chan?", "go": "menni", "5chan_description": "A 5chan egy teljesen decentralizált és nyílt forráskódú imageboard, ahol bárki létrehozhat és kriptográfiailag birtokolhat korlátlan számú fórumot. A fórum tulajdonosok hostolják és moderálják fórumukat, és beállítják annak <1>Rules. Minden adat csak szöveges és peer-to-peer módon osztozik meg, beleértve a beágyazott képek linkjeit is. Nézd meg a <2>FAQs oldalt, hogy többet tudj meg. Nyugodtan kattints egy alábbi fórumra, ami érdekel, és kezdd el!", - "no_global_rules_info": "A 5chan egy szerver nélküli alkalmazás, ez a weboldal csak egy módja annak megnyitásának. Hogy ne a weboldal elérhetőségétől függj, <1>tölts le egy kiadást.", + "no_global_rules_info": "A 5chan egy szerver nélküli alkalmazás, ez a weboldal csak egy módja annak, hogy megnyisd. Hogy ne a weboldal elérhetőségétől függj, <1>töltsd le az alkalmazást.", "boards": "fórumok", "popular_threads": "Népszerű szálak", "options": "Beállítások", diff --git a/public/translations/id/default.json b/public/translations/id/default.json index 5f88b887..44e812cd 100644 --- a/public/translations/id/default.json +++ b/public/translations/id/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Apa itu 5chan?", "go": "pergi", "5chan_description": "5chan adalah imageboard yang sepenuhnya terdesentralisasi dan open-source, di mana siapa pun dapat membuat dan secara kriptografis memiliki board tanpa batas. Pemilik board menghosting dan memoderasi board mereka serta menetapkan <1>Rules-nya. Semua data hanya berupa teks dan dibagikan peer-to-peer, termasuk tautan untuk menyematkan gambar. Lihat <2>FAQs untuk mempelajari lebih lanjut. Silakan klik board di bawah yang menarik minat Anda dan mulai!", - "no_global_rules_info": "5chan adalah aplikasi tanpa server, situs web ini hanyalah salah satu cara untuk membukanya. Agar tidak bergantung pada ketersediaan situs, <1>unduh rilis.", + "no_global_rules_info": "5chan adalah aplikasi tanpa server, situs web ini hanyalah salah satu cara untuk membukanya. Untuk menghindari ketergantungan pada ketersediaan situs, <1>unduh aplikasinya.", "boards": "papan pesan", "popular_threads": "Benang populer", "options": "Opsi", diff --git a/public/translations/it/default.json b/public/translations/it/default.json index 43d3701c..104cdbcf 100644 --- a/public/translations/it/default.json +++ b/public/translations/it/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Cos'è 5chan?", "go": "vai", "5chan_description": "5chan è un imageboard completamente decentralizzato e open-source, dove chiunque può creare e possedere criptograficamente board illimitati. I proprietari dei board ospitano e moderano il proprio board e ne impostano le <1>Rules. Tutti i dati sono solo testuali e condivisi peer-to-peer, inclusi i link per incorporare immagini. Consulta le <2>FAQs per saperne di più. Clicca pure su un board qui sotto che ti interessa e inizia!", - "no_global_rules_info": "5chan è un'app serverless, questo sito è solo un modo per aprirla. Per non dipendere dalla disponibilità del sito, <1>scarica una versione.", + "no_global_rules_info": "5chan è un'app serverless, questo sito web è solo un modo per aprirla. Per non dipendere dalla disponibilità del sito, <1>scarica l'app.", "boards": "board", "popular_threads": "Thread popolari", "options": "Opzioni", diff --git a/public/translations/ja/default.json b/public/translations/ja/default.json index 0017201e..e574f2e4 100644 --- a/public/translations/ja/default.json +++ b/public/translations/ja/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chanとは何ですか?", "go": "行く", "5chan_description": "5chanは完全に分散化されたオープンソースの画像掲示板で、誰でも無制限の板を作成し、暗号学的に所有できます。板のオーナーは板をホスト・モデレートし、<1>Rulesを設定します。すべてのデータはテキストのみで、画像埋め込み用のリンクを含め、ピアツーピアで共有されます。詳しくは<2>FAQsをご覧ください。興味のある板をクリックして、すぐに参加してください!", - "no_global_rules_info": "5chanはサーバーレスアプリで、このウェブサイトはそれを開く一つの方法に過ぎません。ウェブサイトの稼働に依存しないように、<1>リリースをダウンロードしてください。", + "no_global_rules_info": "5chanはサーバーレスアプリで、このウェブサイトは開く方法の一つに過ぎません。ウェブサイトの稼働状況に依存しないためには、<1>アプリをダウンロードしてください。", "boards": "掲示板", "popular_threads": "人気のあるスレッド", "options": "オプション", diff --git a/public/translations/ko/default.json b/public/translations/ko/default.json index 300a5cfc..38db9b2c 100644 --- a/public/translations/ko/default.json +++ b/public/translations/ko/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan이란 무엇인가요?", "go": "가기", "5chan_description": "5chan은 완전히 분산화된 오픈소스 이미지보드로, 누구나 무제한 보드를 생성하고 암호화적으로 소유할 수 있습니다. 보드 소유자는 보드를 호스팅하고 관리하며 <1>Rules를 설정합니다. 모든 데이터는 텍스트만 포함하며 이미지 임베드 링크를 포함해 피어 투 피어로 공유됩니다. 자세한 내용은 <2>FAQs를 확인하세요. 관심 있는 보드를 클릭하고 바로 참여하세요!", - "no_global_rules_info": "5chan은 서버리스 앱이며, 이 웹사이트는 열 수 있는 방법 중 하나일 뿐입니다. 웹사이트 가동 시간에 의존하지 않으려면 <1>릴리스를 다운로드하세요.", + "no_global_rules_info": "5chan은 서버리스 앱이며, 이 웹사이트는 열 수 있는 방법 중 하나일 뿐입니다. 웹사이트 가동 시간에 의존하지 않으려면 <1>앱을 다운로드하세요.", "boards": "게시판", "popular_threads": "인기 있는 스레드", "options": "옵션", diff --git a/public/translations/mr/default.json b/public/translations/mr/default.json index 8fa75510..bcf2dbc1 100644 --- a/public/translations/mr/default.json +++ b/public/translations/mr/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan काय आहे?", "go": "जा", "5chan_description": "5chan एक पूर्णपणे विकेंद्रीकृत आणि ओपन-सोर्स इमेजबोर्ड आहे, जिथे कोणीही अमर्यादित बोर्ड तयार करू शकतो आणि क्रिप्टोग्राफिकदृष्ट्या त्यांचा मालक होऊ शकतो. बोर्ड मालक त्यांच्या बोर्डचे होस्टिंग आणि मॉडरेशन करतात आणि त्याचे <1>Rules सेट करतात. सर्व डेटा फक्त मजकूर आहे आणि तो पीअर-टू-पीअर शेअर केला जातो, एम्बेड इमेजेसच्या लिंक्ससह. अधिक जाणून घेण्यासाठी <2>FAQs पहा. खाली असलेल्या कोणत्याही बोर्डवर क्लिक करण्यास संकोच करू नका आणि सुरू करा!", - "no_global_rules_info": "5chan हे सर्वरलेस अॅप आहे, ही वेबसाइट ते उघडण्याचा फक्त एक मार्ग आहे. वेबसाइटच्या अपटाइमवर अवलंबून राहणे टाळण्यासाठी <1>रिलीझ डाउनलोड करा.", + "no_global_rules_info": "5chan हे सर्व्हरलेस अॅप आहे, ही वेबसाइट ते उघडण्याचा फक्त एक मार्ग आहे. वेबसाइटच्या अपटाइमवर अवलंबून राहण्यापासून बचण्यासाठी <1>अॅप डाउनलोड करा.", "boards": "संदेश फलक", "popular_threads": "लोकप्रिय थ्रेड्स", "options": "पर्याय", diff --git a/public/translations/nl/default.json b/public/translations/nl/default.json index a5d428c8..4a0cbdcc 100644 --- a/public/translations/nl/default.json +++ b/public/translations/nl/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Wat is 5chan?", "go": "gaan", "5chan_description": "5chan is een volledig gedecentraliseerd en open-source imageboard, waar iedereen onbeperkt boards kan aanmaken en cryptografisch bezitten. Board-eigenaren hosten en modereren hun board en stellen de <1>Rules in. Alle data is alleen tekst en wordt peer-to-peer gedeeld, inclusief links voor ingesloten afbeeldingen. Bekijk de <2>FAQs voor meer informatie. Klik gerust op een board hieronder dat je interesseert en begin!", - "no_global_rules_info": "5chan is een serverloze app, deze website is slechts één manier om het te openen. Om niet af te hangen van de beschikbaarheid van de website, <1>download een release.", + "no_global_rules_info": "5chan is een serverloze app, deze website is slechts één manier om deze te openen. Om niet af te hangen van de beschikbaarheid van de website, <1>download de app.", "boards": "forums", "popular_threads": "Populaire threads", "options": "Opties", diff --git a/public/translations/no/default.json b/public/translations/no/default.json index 5e1f87ee..de8d48ee 100644 --- a/public/translations/no/default.json +++ b/public/translations/no/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Hva er 5chan?", "go": "gå", "5chan_description": "5chan er et fullstendig desentralisert og åpen kildekode-imageboard, hvor hvem som helst kan opprette og kryptografisk eie ubegrensede boards. Board-eiere hoster og modererer sitt board og setter dets <1>Rules. Alle data er kun tekst og deles peer-to-peer, inkludert lenker for å bygge inn bilder. Sjekk <2>FAQs for å lære mer. Klikk gjerne på et board nedenfor som interesserer deg og kom i gang!", - "no_global_rules_info": "5chan er en serverløs app, denne nettsiden er bare én måte å åpne den på. For å unngå å stole på nettsidens oppetid, <1>last ned en utgivelse.", + "no_global_rules_info": "5chan er en serverløs app, denne nettsiden er bare én måte å åpne den på. For å unngå å stole på nettsidens oppetid, <1>last ned appen.", "boards": "fora", "popular_threads": "Populære tråder", "options": "Alternativer", diff --git a/public/translations/pl/default.json b/public/translations/pl/default.json index 6017fb3e..593fd2e9 100644 --- a/public/translations/pl/default.json +++ b/public/translations/pl/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Co to jest 5chan?", "go": "iść", "5chan_description": "5chan to w pełni zdecentralizowany i open-source imageboard, gdzie każdy może tworzyć i kryptograficznie posiadać nieograniczoną liczbę tablic. Właściciele tablic hostują i moderują swoje tablice oraz ustawiają ich <1>Rules. Wszystkie dane są wyłącznie tekstowe i udostępniane peer-to-peer, w tym linki do osadzania obrazów. Sprawdź <2>FAQs, aby dowiedzieć się więcej. Kliknij dowolną tablicę poniżej, która Cię interesuje, i dołącz!", - "no_global_rules_info": "5chan to aplikacja bezserwerowa, ta strona to tylko jeden ze sposobów jej otwarcia. Aby nie polegać na dostępności strony, <1>pobierz wydanie.", + "no_global_rules_info": "5chan to aplikacja bezserwerowa, ta strona to tylko jeden ze sposobów jej otwarcia. Aby nie polegać na dostępności strony, <1>pobierz aplikację.", "boards": "fora", "popular_threads": "Popularne wątki", "options": "Opcje", diff --git a/public/translations/pt/default.json b/public/translations/pt/default.json index 054cf3a9..89e601ab 100644 --- a/public/translations/pt/default.json +++ b/public/translations/pt/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "O que é 5chan?", "go": "vai", "5chan_description": "5chan é um imageboard totalmente descentralizado e de código aberto, onde qualquer pessoa pode criar e possuir criptograficamente boards ilimitados. Os proprietários de boards hospedam e moderam seu board e definem suas <1>Rules. Todos os dados são apenas texto e compartilhados peer-to-peer, incluindo links para incorporar imagens. Confira as <2>FAQs para saber mais. Sinta-se à vontade para clicar em um board abaixo que te interessa e comece!", - "no_global_rules_info": "5chan é um app sem servidor, este site é apenas uma forma de abri-lo. Para não depender da disponibilidade do site, <1>baixe uma versão.", + "no_global_rules_info": "5chan é um aplicativo sem servidor, este site é apenas uma forma de abri-lo. Para não depender da disponibilidade do site, <1>baixe o aplicativo.", "boards": "fóruns", "popular_threads": "Tópicos populares", "options": "Opções", diff --git a/public/translations/ro/default.json b/public/translations/ro/default.json index e4cd1ea4..9a2858c6 100644 --- a/public/translations/ro/default.json +++ b/public/translations/ro/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Ce este 5chan?", "go": "du-te", "5chan_description": "5chan este un imageboard complet descentralizat și open-source, unde oricine poate crea și deține criptografic panouri nelimitate. Proprietarii de panouri găzduiesc și moderază panoul lor și îi stabilesc <1>Rules. Toate datele sunt doar text și sunt partajate peer-to-peer, inclusiv linkuri pentru imagini încorporate. Consultați <2>FAQs pentru a afla mai multe. Nu ezitați să dați clic pe un panou de mai jos care vă interesează și să începeți!", - "no_global_rules_info": "5chan este o aplicație serverless, acest site este doar o modalitate de a-l deschide. Pentru a nu depinde de disponibilitatea site-ului, <1>descarcă o versiune.", + "no_global_rules_info": "5chan este o aplicație fără server, acest site web este doar o modalitate de a-l deschide. Pentru a nu depinde de disponibilitatea site-ului, <1>descarcă aplicația.", "boards": "forumuri", "popular_threads": "Threaduri populare", "options": "Opțiuni", diff --git a/public/translations/ru/default.json b/public/translations/ru/default.json index be09f4dc..95c81fc1 100644 --- a/public/translations/ru/default.json +++ b/public/translations/ru/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Что такое 5chan?", "go": "идти", "5chan_description": "5chan — это полностью децентрализованный и открытый imageboard, где любой может создавать и криптографически владеть неограниченным количеством досок. Владельцы досок размещают и модерируют свою доску и устанавливают её <1>Rules. Все данные только текстовые и распространяются peer-to-peer, включая ссылки для встраивания изображений. Ознакомьтесь с <2>FAQs, чтобы узнать больше. Нажмите на любую доску ниже, которая вас интересует, и присоединяйтесь!", - "no_global_rules_info": "5chan — это безсерверное приложение, этот сайт — лишь один способ его открыть. Чтобы не зависеть от доступности сайта, <1>скачайте релиз.", + "no_global_rules_info": "5chan — это бессерверное приложение, этот сайт — лишь один из способов его открыть. Чтобы не зависеть от доступности сайта, <1>скачайте приложение.", "boards": "форумы", "popular_threads": "Популярные темы", "options": "Опции", diff --git a/public/translations/sq/default.json b/public/translations/sq/default.json index d8c5aa20..2c4b78ce 100644 --- a/public/translations/sq/default.json +++ b/public/translations/sq/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Çfarë është 5chan?", "go": "shko", "5chan_description": "5chan është një imageboard plotësisht i decentralizuar dhe me burim të hapur, ku kushdo mund të krijojë dhe të zotërojë kriptografikisht borda të pakufizuara. Pronarët e bordave hostojnë dhe moderojnë bordin e tyre dhe vendosin <1>Rules e tij. Të gjitha të dhënat janë vetëm teksti dhe ndahen peer-to-peer, duke përfshirë lidhjet për imazhe të ngulitura. Shikoni <2>FAQs për të mësuar më shumë. Mos ngurroni të klikoni në një bord më poshtë që ju intereson dhe filloni!", - "no_global_rules_info": "5chan është një aplikacion pa server, ky faqe është vetëm një mënyrë për ta hapur. Për të shmangur varësinë nga disponueshmëria e faqes, <1>shkarkoni një version.", + "no_global_rules_info": "5chan është një aplikacion pa server, ky faqe është vetëm një mënyrë për ta hapur. Për të shmangur varësinë nga disponueshmëria e faqes, <1>shkarkoni aplikacionin.", "boards": "forume", "popular_threads": "Threadet e njohur", "options": "Mundësitë", diff --git a/public/translations/sv/default.json b/public/translations/sv/default.json index 5fd96444..fa89c8bc 100644 --- a/public/translations/sv/default.json +++ b/public/translations/sv/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Vad är 5chan?", "go": "gå", "5chan_description": "5chan är en helt decentraliserad och öppen källkod imageboard, där vem som helst kan skapa och kryptografiskt äga obegränsade tavlor. Tavlägare hostar och modererar sin tavla och sätter dess <1>Rules. All data är endast text och delas peer-to-peer, inklusive länkar för inbäddade bilder. Kolla in <2>FAQs för att lära dig mer. Klicka gärna på en tavla nedan som intresserar dig och börja!", - "no_global_rules_info": "5chan är en serverlös app, denna webbplats är bara ett sätt att öppna den. För att inte vara beroende av webbplatsens drifttid, <1>ladda ner en version.", + "no_global_rules_info": "5chan är en serverlös app, denna webbplats är bara ett sätt att öppna den. För att inte vara beroende av webbplatsens drifttid, <1>ladda ner appen.", "boards": "forum", "popular_threads": "Populära trådar", "options": "Alternativ", diff --git a/public/translations/te/default.json b/public/translations/te/default.json index 8d30a1e3..fe0c9722 100644 --- a/public/translations/te/default.json +++ b/public/translations/te/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan ఏమిటి?", "go": "వెళ్లు", "5chan_description": "5chan పూర్తిగా వికేంద్రీకృతమైన మరియు ఓపెన్-సోర్స్ ఇమేజ్ బోర్డ్, ఇక్కడ ఎవరైనా అపరిమిత బోర్డ్లను సృష్టించవచ్చు మరియు క్రిప్టోగ్రాఫికల్గా స్వంతం చేసుకోవచ్చు. బోర్డ్ యజమానులు తమ బోర్డ్ను హోస్ట్ చేసి మోడరేట్ చేస్తారు మరియు దాని <1>Rules సెట్ చేస్తారు. అన్ని డేటా టెక్స్ట్ మాత్రమే మరియు ఎంబెడ్ చిత్రాల లింక్లతో సహా పీయర్-టు-పీయర్ షేర్ చేయబడుతుంది. మరింత తెలుసుకోవడానికి <2>FAQs చూడండి. మీకు ఆసక్తి ఉన్న క్రింది బోర్డ్పై క్లిక్ చేయడానికి సంకోచించకండి మరియు ప్రారంభించండి!", - "no_global_rules_info": "5chan ఒక సర్వర్‌లెస్ యాప్, ఈ వెబ్‌సైట్ దాన్ని తెరవడానికి ఒక మార్గం మాత్రమే. వెబ్‌సైట్ అప్‌టైమ్‌పై ఆధారపడకుండా ఉండడానికి <1>రిలీజ్ డౌన్‌లోడ్ చేయండి.", + "no_global_rules_info": "5chan ఒక సర్వర్‌లెస్ యాప్, ఈ వెబ్‌సైట్ దాన్ని తెరవడానికి ఒక మార్గం మాత్రమే. వెబ్‌సైట్ అప్‌టైమ్‌పై ఆధారపడకుండా ఉండాలంటే <1>యాప్ డౌన్‌లోడ్ చేయండి.", "boards": "సందేశ బోర్డులు", "popular_threads": "జనప్రియమైన థ్రెడ్‌లు", "options": "ఎంపికలు", diff --git a/public/translations/th/default.json b/public/translations/th/default.json index ee5e34f2..1ab00f2e 100644 --- a/public/translations/th/default.json +++ b/public/translations/th/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan คืออะไร?", "go": "ไป", "5chan_description": "5chan เป็น imageboard ที่กระจายอำนาจอย่างสมบูรณ์และโอเพนซอร์ส ที่ใครก็ตามสามารถสร้างและเป็นเจ้าของบอร์ดได้ไม่จำกัดด้วยการเข้ารหัส เจ้าของบอร์ดโฮสต์และดูแลบอร์ดของตน และตั้งค่า <1>Rules ข้อมูลทั้งหมดเป็นข้อความเท่านั้นและแชร์แบบ peer-to-peer รวมถึงลิงก์สำหรับฝังรูปภาพ ดู <2>FAQs เพื่อเรียนรู้เพิ่มเติม คลิกบอร์ดด้านล่างที่คุณสนใจและเริ่มต้นได้เลย!", - "no_global_rules_info": "5chan เป็นแอปแบบ serverless เว็บไซต์นี้เป็นเพียงวิธีหนึ่งในการเปิดใช้งาน เพื่อไม่ให้พึ่งพาเวลาทำงานของเว็บไซต์ <1>ดาวน์โหลดเวอร์ชัน", + "no_global_rules_info": "5chan เป็นแอปแบบไม่มีเซิร์ฟเวอร์ เว็บไซต์นี้เป็นเพียงวิธีหนึ่งในการเปิดใช้งาน เพื่อหลีกเลี่ยงการพึ่งพาเวลาทำงานของเว็บไซต์ <1>ดาวน์โหลดแอป", "boards": "กระดานข่าว", "popular_threads": "กระทู้ยอดนิยม", "options": "ตัวเลือก", diff --git a/public/translations/tr/default.json b/public/translations/tr/default.json index d7e3f91d..5b97218d 100644 --- a/public/translations/tr/default.json +++ b/public/translations/tr/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan nedir?", "go": "git", "5chan_description": "5chan, herkesin sınırsız board oluşturabileceği ve kriptografik olarak sahip olabileceği tamamen merkeziyetsiz ve açık kaynaklı bir imageboard'dur. Board sahipleri boardlarını barındırır ve moderatörlük yapar, <1>Rules ayarlar. Tüm veriler yalnızca metindir ve gömülü resimlerin bağlantıları dahil peer-to-peer paylaşılır. Daha fazla bilgi için <2>FAQs bölümüne bakın. İlginizi çeken bir boarda tıklayıp hemen başlayın!", - "no_global_rules_info": "5chan sunucusuz bir uygulamadır, bu web sitesi onu açmanın sadece bir yoludur. Web sitesinin çalışma süresine güvenmemek için <1>bir sürüm indirin.", + "no_global_rules_info": "5chan sunucusuz bir uygulamadır, bu web sitesi onu açmanın sadece bir yoludur. Web sitesinin çalışma süresine güvenmemek için <1>uygulamayı indirin.", "boards": "forumlar", "popular_threads": "Popüler konular", "options": "Seçenekler", diff --git a/public/translations/uk/default.json b/public/translations/uk/default.json index 37c6ce3d..07ad6144 100644 --- a/public/translations/uk/default.json +++ b/public/translations/uk/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Що таке 5chan?", "go": "йди", "5chan_description": "5chan — це повністю децентралізований та відкритий imageboard, де будь-хто може створювати та криптографічно володіти необмеженою кількістю дошок. Власники дошок хостують та модерують свою дошку і встановлюють її <1>Rules. Усі дані лише текстові і поширюються peer-to-peer, включно з посиланнями для вбудовування зображень. Перегляньте <2>FAQs, щоб дізнатися більше. Натисніть на будь-яку дошку нижче, що вас цікавить, і приєднуйтесь!", - "no_global_rules_info": "5chan — це безсерверний додаток, цей сайт — лише один із способів його відкрити. Щоб не залежати від доступності сайту, <1>завантажте реліз.", + "no_global_rules_info": "5chan — це безсерверний додаток, цей сайт — лише один із способів його відкрити. Щоб не залежати від доступності сайту, <1>завантажте додаток.", "boards": "форуми", "popular_threads": "Популярні теми", "options": "Опції", diff --git a/public/translations/ur/default.json b/public/translations/ur/default.json index 73ef545a..470e7d03 100644 --- a/public/translations/ur/default.json +++ b/public/translations/ur/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan کیا ہے؟", "go": "جا", "5chan_description": "5chan ایک مکمل طور پر غیر مرکزیت اور اوپن سورس imageboard ہے، جہاں کوئی بھی لامحدود بورڈز بنا سکتا ہے اور cryptographically ان کا مالک ہو سکتا ہے۔ بورڈ مالکان اپنے بورڈ کو ہوسٹ اور moderate کرتے ہیں اور اس کے <1>Rules سیٹ کرتے ہیں۔ تمام ڈیٹا صرف ٹیکسٹ ہے اور peer-to-peer شیئر کیا جاتا ہے، بشمول embed images کے لنکس۔ مزید جاننے کے لیے <2>FAQs دیکھیں۔ نیچے کسی بھی بورڈ پر کلک کریں جو آپ کو دلچسپ لگے اور شروع کریں!", - "no_global_rules_info": "5chan ایک سرور لیس ایپ ہے، یہ ویب سائٹ اسے کھولنے کا صرف ایک طریقہ ہے۔ ویب سائٹ کی اپ ٹائم پر انحصار سے بچنے کے لیے <1>ایک ریلیز ڈاؤن لوڈ کریں۔", + "no_global_rules_info": "5chan ایک سرور لیس ایپ ہے، یہ ویب سائٹ اسے کھولنے کا صرف ایک طریقہ ہے۔ ویب سائٹ کی اپ ٹائم پر انحصار سے بچنے کے لیے <1>ایپ ڈاؤن لوڈ کریں۔", "boards": "پیغام بورڈز", "popular_threads": "مقبول تھریڈز", "options": "اختیارات", diff --git a/public/translations/vi/default.json b/public/translations/vi/default.json index 4e81d225..0a345bfa 100644 --- a/public/translations/vi/default.json +++ b/public/translations/vi/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan là gì?", "go": "đi", "5chan_description": "5chan là một imageboard hoàn toàn phi tập trung và mã nguồn mở, nơi bất kỳ ai cũng có thể tạo và sở hữu mật mã vô hạn các bảng. Chủ sở hữu bảng lưu trữ và kiểm duyệt bảng của họ và cài đặt <1>Rules. Tất cả dữ liệu chỉ là văn bản và được chia sẻ peer-to-peer, bao gồm cả liên kết nhúng hình ảnh. Xem <2>FAQs để tìm hiểu thêm. Hãy nhấp vào bất kỳ bảng nào bên dưới mà bạn quan tâm và bắt đầu!", - "no_global_rules_info": "5chan là ứng dụng không cần máy chủ, trang web này chỉ là một cách để mở nó. Để không phụ thuộc vào thời gian hoạt động của trang web, <1>tải xuống phiên bản.", + "no_global_rules_info": "5chan là ứng dụng không cần máy chủ, trang web này chỉ là một cách để mở nó. Để không phụ thuộc vào thời gian hoạt động của trang web, <1>tải ứng dụng.", "boards": "diễn đàn", "popular_threads": "Chủ đề phổ biến", "options": "Tùy chọn", diff --git a/public/translations/zh/default.json b/public/translations/zh/default.json index b8f8c2ca..9c91aa60 100644 --- a/public/translations/zh/default.json +++ b/public/translations/zh/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "5chan是什么?", "go": "去", "5chan_description": "5chan 是一个完全去中心化和开源的图像板,任何人都可以创建并以加密方式拥有无限数量的板块。板块所有者托管和审核其板块,并设置其 <1>Rules。所有数据均为纯文本,且以点对点方式共享,包括嵌入图片的链接。查看 <2>FAQs 了解更多。欢迎点击下方任意感兴趣的板块,立即开始!", - "no_global_rules_info": "5chan 是无服务器应用,本网站只是打开它的方式之一。为避免依赖网站可用性,请<1>下载发行版。", + "no_global_rules_info": "5chan 是一个无服务器应用,本网站只是打开它的方式之一。为避免依赖网站的可用性,请<1>下载应用。", "boards": "论坛", "popular_threads": "热门主题", "options": "选项", diff --git a/src/components/site-legal-meta/site-legal-meta.tsx b/src/components/site-legal-meta/site-legal-meta.tsx index f839b915..ae4c31b8 100644 --- a/src/components/site-legal-meta/site-legal-meta.tsx +++ b/src/components/site-legal-meta/site-legal-meta.tsx @@ -7,7 +7,7 @@ export type SiteLegalMetaProps = { order?: SiteLegalMetaOrder; }; -const LicenseText = () => 5chan is free and open source software under GPLv2 license.; +const LicenseText = () => 5chan is free and open-source software under GPLv2 license.; const VersionFeedbackContact = () => ( <> diff --git a/src/views/faq/faq.tsx b/src/views/faq/faq.tsx index 4660cc83..dcb7caab 100644 --- a/src/views/faq/faq.tsx +++ b/src/views/faq/faq.tsx @@ -100,8 +100,8 @@ const FAQ = () => {
No. 5chan is a client app for the Bitsocial protocol. This website is just one place to open it — the domain could change, disappear, or be blocked without affecting the Bitsocial network or any boards. We recommend installing the app when your browser offers it, so you keep a local copy that works - independently. You can also download a desktop or Android release from GitHub. If you - know a board's address, you can connect from any host or installed copy. + independently. You can also download the app from GitHub. If you know a board's + address, you can connect from any host or installed copy.
How do I access the boards?
From b243ec55b88061fad728964a3d09b78ae1c5053c Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 19:24:43 +0800 Subject: [PATCH 08/19] chore(deps): upgrade bitsocial-react-hooks --- package.json | 2 +- yarn.lock | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d380e3f9..ee79da0e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "GPL-2.0-only", "private": true, "dependencies": { - "@bitsocialhq/bitsocial-react-hooks": "https://github.com/bitsocialhq/bitsocial-react-hooks.git#c9e56de2307f5bd5db0c2b7958a3ecad6ea0a724", + "@bitsocialhq/bitsocial-react-hooks": "https://github.com/bitsocialhq/bitsocial-react-hooks.git#b341bd331a6e4cf9611e4303248549d0bcc459d9", "@capacitor/app": "7.0.1", "@capacitor/status-bar": "7.0.1", "@capawesome/capacitor-android-edge-to-edge-support": "7.2.2", diff --git a/yarn.lock b/yarn.lock index 41663fd4..812897ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1023,6 +1023,22 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.28.5" +"@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#b341bd331a6e4cf9611e4303248549d0bcc459d9": + version "0.1.0" + resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#b341bd331a6e4cf9611e4303248549d0bcc459d9" + dependencies: + "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#10ed04e3866dd986a7f802bc9efd027f0e7d465b" + "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git" + assert "2.0.0" + ethers "5.8.0" + localforage "1.10.0" + lodash.isequal "4.5.0" + memoizee "0.4.15" + quick-lru "5.1.1" + uint8arrays "3.1.1" + uuid "11.1.0" + zustand "4.0.0" + "@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#c9e56de2307f5bd5db0c2b7958a3ecad6ea0a724": version "0.1.0" resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#c9e56de2307f5bd5db0c2b7958a3ecad6ea0a724" From ec404569e78622d4f1b8500dd1ffcc94eb398a85 Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 19:24:49 +0800 Subject: [PATCH 09/19] fix(quotes): avoid striking unresolved quote links --- .../comment-content/comment-content.tsx | 5 +++-- src/components/markdown/markdown.tsx | 4 ++-- .../reply-quote-preview.tsx | 21 ++++++++++++------- .../utils/__tests__/quote-link-utils.test.ts | 9 +++++++- src/lib/utils/quote-link-utils.ts | 12 ++++++++++- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/components/comment-content/comment-content.tsx b/src/components/comment-content/comment-content.tsx index ac412b59..38145f0e 100644 --- a/src/components/comment-content/comment-content.tsx +++ b/src/components/comment-content/comment-content.tsx @@ -6,6 +6,7 @@ import useSubplebbitsPagesStore from '@bitsocialhq/bitsocial-react-hooks/dist/st import usePostNumberStore from '../../stores/use-post-number-store'; import getShortAddress from '../../lib/get-short-address'; import { getFormattedDate, getFormattedTimeAgo } from '../../lib/utils/time-utils'; +import { isUnavailableQuoteTarget } from '../../lib/utils/quote-link-utils'; import { isPostPageView } from '../../lib/utils/view-utils'; import useIsMobile from '../../hooks/use-is-mobile'; import useStateString from '../../hooks/use-state-string'; @@ -23,7 +24,7 @@ const QuotedCidLink = ({ cid, postCid }: { cid: string; postCid: string }) => { // Prefer hook version to ensure 'number' property is populated for deeper nested replies in Virtuoso const quotedComment = commentFromHook?.number !== undefined ? commentFromHook : commentFromStore; const isOP = cid === postCid; - const isUnavailable = !quotedComment || quotedComment.deleted || quotedComment.removed; + const isUnavailable = isUnavailableQuoteTarget(quotedComment); return ; }; @@ -129,7 +130,7 @@ const CommentContent = ({ comment: post }: { comment: Comment }) => { !(deleted || removed) && (filteredQuotedCids.length > 0 ? filteredQuotedCids.map((cid: string) => ) - : shouldShowReplyingToReply && )} + : shouldShowReplyingToReply && )} {removed ? ( reason ? ( <> diff --git a/src/components/markdown/markdown.tsx b/src/components/markdown/markdown.tsx index 20f551f4..b5bece0f 100644 --- a/src/components/markdown/markdown.tsx +++ b/src/components/markdown/markdown.tsx @@ -277,13 +277,13 @@ const NumberQuoteLink = ({ number, threadPostCid, subplebbitAddress }: { number: const comment = commentFromHook?.number !== undefined ? commentFromHook : commentFromStore; const isOP = Boolean(threadPostCid && cid === threadPostCid); - if (!comment || isUnavailableQuoteTarget(comment)) { + if (isUnavailableQuoteTarget(comment)) { return ( ); } - return ; + return ; }; const renderAnchorLink = (children: React.ReactNode, href: string, threadPostCid?: string, subplebbitAddress?: string) => { diff --git a/src/components/reply-quote-preview/reply-quote-preview.tsx b/src/components/reply-quote-preview/reply-quote-preview.tsx index 5d7c4f96..7de273f2 100644 --- a/src/components/reply-quote-preview/reply-quote-preview.tsx +++ b/src/components/reply-quote-preview/reply-quote-preview.tsx @@ -5,7 +5,7 @@ import { Comment, useAccount } from '@bitsocialhq/bitsocial-react-hooks'; import { useFloating, offset, shift, size, autoUpdate, Placement } from '@floating-ui/react'; import { useDirectories } from '../../hooks/use-directories'; import { getBoardPath } from '../../lib/utils/route-utils'; -import { formatQuoteNumber, isUnavailableQuoteTarget, shouldShowFloatingQuotePreview } from '../../lib/utils/quote-link-utils'; +import { formatQuoteNumber, getQuoteTargetAvailability, shouldShowFloatingQuotePreview } from '../../lib/utils/quote-link-utils'; import useIsMobile from '../../hooks/use-is-mobile'; import styles from '../../views/post/post.module.css'; import { Post } from '../../views/post'; @@ -209,7 +209,9 @@ const DesktopQuotePreview = ({ const resolvedQuotelinkNumber = quotelinkReply?.number ?? quotelinkNumber; const resolvedQuotelinkCid = quotelinkReply?.cid; const resolvedQuotelinkSubplebbitAddress = quotelinkReply?.subplebbitAddress; - const quotelinkUnavailable = Boolean(isQuotelinkUnavailable || isUnavailableQuoteTarget(quotelinkReply)); + const quoteTargetAvailability = getQuoteTargetAvailability(quotelinkReply); + const quotelinkUnavailable = Boolean(isQuotelinkUnavailable || quoteTargetAvailability === 'unavailable'); + const quotelinkPendingResolution = !quotelinkUnavailable && quoteTargetAvailability === 'unresolved'; const quotelinkClassName = quotelinkUnavailable ? `${styles.quoteLink} ${styles.quoteLinkUnavailable}` : styles.quoteLink; const quotelinkBoardPath = quotelinkReply?.subplebbitAddress ? getBoardPath(quotelinkReply.subplebbitAddress, directories) : undefined; const quotelinkRoute = quotelinkReply?.cid ? (quotelinkBoardPath ? `/${quotelinkBoardPath}/thread/${quotelinkReply.cid}` : `/thread/${quotelinkReply.cid}`) : '#'; @@ -231,6 +233,8 @@ const DesktopQuotePreview = ({ <> {quotelinkUnavailable ? ( {quotelinkLabel} + ) : quotelinkPendingResolution ? ( + {quotelinkLabel} ) : ( handleMouseOver(resolvedQuotelinkCid)} - onMouseLeave={quotelinkUnavailable ? undefined : () => handleMouseLeave(resolvedQuotelinkCid)} + ref={quotelinkUnavailable || quotelinkPendingResolution ? undefined : refs.setReference} + className={quotelinkPendingResolution ? styles.quoteLink : quotelinkClassName} + onMouseOver={quotelinkUnavailable || quotelinkPendingResolution ? undefined : () => handleMouseOver(resolvedQuotelinkCid)} + onMouseLeave={quotelinkUnavailable || quotelinkPendingResolution ? undefined : () => handleMouseLeave(resolvedQuotelinkCid)} > {formatQuoteNumber(resolvedQuotelinkNumber)} {isOP && ' (OP)'} {quotelinkReply?.author?.address === account?.author?.address && ' (You)'} {!quotelinkUnavailable && + !quotelinkPendingResolution && resolvedQuotelinkNumber && (() => { const quotelinkBoardPath = resolvedQuotelinkSubplebbitAddress ? getBoardPath(resolvedQuotelinkSubplebbitAddress, directories) : undefined; diff --git a/src/lib/utils/__tests__/quote-link-utils.test.ts b/src/lib/utils/__tests__/quote-link-utils.test.ts index 1642f81f..c406d9b1 100644 --- a/src/lib/utils/__tests__/quote-link-utils.test.ts +++ b/src/lib/utils/__tests__/quote-link-utils.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import { formatQuoteNumber, isUnavailableQuoteTarget, shouldShowFloatingQuotePreview } from '../quote-link-utils'; +import { formatQuoteNumber, getQuoteTargetAvailability, isUnavailableQuoteTarget, shouldShowFloatingQuotePreview } from '../quote-link-utils'; describe('quote-link-utils', () => { it('formats quote numbers with the expected prefix', () => { @@ -7,6 +7,13 @@ describe('quote-link-utils', () => { expect(formatQuoteNumber()).toBe('>>?'); }); + it('distinguishes unresolved and unavailable quote targets', () => { + expect(getQuoteTargetAvailability(undefined)).toBe('unresolved'); + expect(getQuoteTargetAvailability({ deleted: true, removed: false })).toBe('unavailable'); + expect(getQuoteTargetAvailability({ deleted: false, removed: true })).toBe('unavailable'); + expect(getQuoteTargetAvailability({ deleted: false, removed: false })).toBe('available'); + }); + it('marks deleted and removed comments as unavailable quote targets', () => { expect(isUnavailableQuoteTarget(undefined)).toBe(false); expect(isUnavailableQuoteTarget({ deleted: true, removed: false })).toBe(true); diff --git a/src/lib/utils/quote-link-utils.ts b/src/lib/utils/quote-link-utils.ts index 83a4593c..f2ec0148 100644 --- a/src/lib/utils/quote-link-utils.ts +++ b/src/lib/utils/quote-link-utils.ts @@ -1,8 +1,18 @@ import type { Comment } from '@bitsocialhq/bitsocial-react-hooks'; +type QuoteTargetAvailability = 'available' | 'unresolved' | 'unavailable'; + export const formatQuoteNumber = (number?: number) => `>>${number ?? '?'}`; -export const isUnavailableQuoteTarget = (comment?: Partial> | null) => Boolean(comment?.deleted || comment?.removed); +export const getQuoteTargetAvailability = (comment?: Partial> | null): QuoteTargetAvailability => { + if (!comment) { + return 'unresolved'; + } + + return comment.deleted || comment.removed ? 'unavailable' : 'available'; +}; + +export const isUnavailableQuoteTarget = (comment?: Partial> | null) => getQuoteTargetAvailability(comment) === 'unavailable'; export const shouldShowFloatingQuotePreview = ({ hoveredCid, From 0247a392c29a0bd301e228eb18267352710cd3ad Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 19:36:19 +0800 Subject: [PATCH 10/19] Update yarn.lock --- yarn.lock | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/yarn.lock b/yarn.lock index 812897ef..87eeb80a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1039,22 +1039,6 @@ uuid "11.1.0" zustand "4.0.0" -"@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#c9e56de2307f5bd5db0c2b7958a3ecad6ea0a724": - version "0.1.0" - resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#c9e56de2307f5bd5db0c2b7958a3ecad6ea0a724" - dependencies: - "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#10ed04e3866dd986a7f802bc9efd027f0e7d465b" - "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git" - assert "2.0.0" - ethers "5.8.0" - localforage "1.10.0" - lodash.isequal "4.5.0" - memoizee "0.4.15" - quick-lru "5.1.1" - uint8arrays "3.1.1" - uuid "11.1.0" - zustand "4.0.0" - "@bonfida/sns-records@0.0.1": version "0.0.1" resolved "https://registry.yarnpkg.com/@bonfida/sns-records/-/sns-records-0.0.1.tgz#e178dece0aeeb1670c57703568ae3e1218e7e5fe" From 91615dbf4768e319cf50eb347b3138724445254d Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 20:54:11 +0800 Subject: [PATCH 11/19] feat(markdown): use BBCode-style [spoiler][/spoiler] tags --- src/components/markdown/markdown.tsx | 2 +- src/lib/utils/post-utils.ts | 2 +- src/views/faq/faq.tsx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/markdown/markdown.tsx b/src/components/markdown/markdown.tsx index b5bece0f..c9a4c63f 100644 --- a/src/components/markdown/markdown.tsx +++ b/src/components/markdown/markdown.tsx @@ -145,7 +145,7 @@ type Token = | { type: 'crossBoardLink'; display: string; route: string } | { type: 'spoiler'; tokens: Token[] }; -const SPOILER_REGEX = /([\s\S]*?)<\/spoiler>/; +const SPOILER_REGEX = /\[spoiler\]([\s\S]*?)\[\/spoiler\]/; const CROSSBOARD_REGEX = />>>\/((?:[a-zA-Z0-9]{1,10}\/(?:[a-zA-Z0-9]{46})?|[a-zA-Z0-9\-.]+(?:\/[a-zA-Z0-9]{46})?))[.,:;!?]*/; const QUOTE_LINK_REGEX = /(?/\w])>>(\d+)(?![\d/])/; const URL_REGEX = /https?:\/\/[^\s<\[\]]*[^\s<\[\].,;:!?\"'\)\]>]/; diff --git a/src/lib/utils/post-utils.ts b/src/lib/utils/post-utils.ts index c075d06f..773d3c48 100644 --- a/src/lib/utils/post-utils.ts +++ b/src/lib/utils/post-utils.ts @@ -23,7 +23,7 @@ export function getTextColorForBackground(rgb: string): string { export function removeMarkdown(md: string): string { return md - .replace(/(.*?)<\/spoiler>/gs, '$1') // spoiler tags - keep inner text + .replace(/\[spoiler\](.*?)\[\/spoiler\]/gs, '$1') // spoiler tags - keep inner text .replace(/\[([^\]]*?)\]\([^)]*\)/g, '$1') // [text](url) -> text .replace(/ /g, ' ') //   -> space .replace(/^>\s*/gm, '') // greentext at line start diff --git a/src/views/faq/faq.tsx b/src/views/faq/faq.tsx index dcb7caab..73cec35e 100644 --- a/src/views/faq/faq.tsx +++ b/src/views/faq/faq.tsx @@ -188,8 +188,8 @@ const FAQ = () => {
Can I mark a submission as a spoiler?
All boards allow you to mask plot-spoiling content. To mark your image as a spoiler, check the [x Spoiler?] box before submission. Spoilerizing text - makes it unreadable to others until they mouse over it. To spoilerize a comment, place {``} tags around the text you wish to hide (ex. " - {``}SPIKE DIES!{``}"). + makes it unreadable to others until they mouse over it. To spoilerize a comment, place {`[spoiler][/spoiler]`} tags around the text you wish to hide + (ex. "{`[spoiler]`}SPIKE DIES!{`[/spoiler]`}").
From ca9f743cefd66ef31953d7b7060f68d808983306 Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 21:09:04 +0800 Subject: [PATCH 12/19] fix(vite.config.js): remove deprecated rolldown dep optimizer config --- vite.config.js | 58 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/vite.config.js b/vite.config.js index a5cce09e..c4c61fe1 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,12 +1,47 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import { resolve } from 'path'; -import { nodePolyfills } from 'vite-plugin-node-polyfills'; import { VitePWA } from 'vite-plugin-pwa'; +function adaptReactPluginForRolldown(plugin) { + if (!plugin?.config || plugin.name !== 'vite:react-babel') { + return plugin; + } + + return { + ...plugin, + async config(userConfig, configEnv) { + const config = await plugin.config.call(this, userConfig, configEnv); + const optimizeDeps = config?.optimizeDeps; + + if (optimizeDeps?.esbuildOptions?.jsx !== 'automatic') { + return config; + } + + const { esbuildOptions, ...remainingOptimizeDeps } = optimizeDeps; + + return { + ...config, + optimizeDeps: { + ...remainingOptimizeDeps, + rolldownOptions: { + ...optimizeDeps.rolldownOptions, + transform: { + ...optimizeDeps.rolldownOptions?.transform, + jsx: optimizeDeps.rolldownOptions?.transform?.jsx ?? { + runtime: 'automatic', + }, + }, + }, + }, + }; + }, + }; +} + export default defineConfig({ plugins: [ - react({ + ...react({ babel: { plugins: [ [ @@ -17,16 +52,7 @@ export default defineConfig({ ], ], }, - }), - nodePolyfills({ - globals: { - Buffer: true, - global: true, - process: true, - }, - protocolImports: true, - include: ['crypto', 'stream', 'util', 'buffer', 'events'], - }), + }).map(adaptReactPluginForRolldown), VitePWA({ registerType: 'autoUpdate', strategies: 'injectManifest', @@ -146,6 +172,14 @@ export default defineConfig({ stream: 'stream-browserify', crypto: 'crypto-browserify', buffer: 'buffer', + events: 'events', + process: 'process', + 'node:buffer': 'buffer', + 'node:crypto': 'crypto-browserify', + 'node:events': 'events', + 'node:process': 'process', + 'node:stream': 'stream-browserify', + 'node:util': 'util', 'util/': 'util', util: 'util', }, From cac3d0969839560d89a623fccb0a5835ea8350f3 Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 21:11:33 +0800 Subject: [PATCH 13/19] Update default.json --- public/translations/sq/default.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/translations/sq/default.json b/public/translations/sq/default.json index 2c4b78ce..e49c7218 100644 --- a/public/translations/sq/default.json +++ b/public/translations/sq/default.json @@ -2,7 +2,7 @@ "what_is_5chan": "Çfarë është 5chan?", "go": "shko", "5chan_description": "5chan është një imageboard plotësisht i decentralizuar dhe me burim të hapur, ku kushdo mund të krijojë dhe të zotërojë kriptografikisht borda të pakufizuara. Pronarët e bordave hostojnë dhe moderojnë bordin e tyre dhe vendosin <1>Rules e tij. Të gjitha të dhënat janë vetëm teksti dhe ndahen peer-to-peer, duke përfshirë lidhjet për imazhe të ngulitura. Shikoni <2>FAQs për të mësuar më shumë. Mos ngurroni të klikoni në një bord më poshtë që ju intereson dhe filloni!", - "no_global_rules_info": "5chan është një aplikacion pa server, ky faqe është vetëm një mënyrë për ta hapur. Për të shmangur varësinë nga disponueshmëria e faqes, <1>shkarkoni aplikacionin.", + "no_global_rules_info": "5chan është një aplikacion pa server, kjo faqe është vetëm një mënyrë për ta hapur. Për të shmangur varësinë nga disponueshmëria e faqes, <1>shkarkoni aplikacionin.", "boards": "forume", "popular_threads": "Threadet e njohur", "options": "Mundësitë", From c69c46442beb8159bddc39bc7856597438509a2f Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 21:42:03 +0800 Subject: [PATCH 14/19] chore(deps): upgrade bitsocial-react-hooks --- package.json | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index ee79da0e..549aaeae 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "GPL-2.0-only", "private": true, "dependencies": { - "@bitsocialhq/bitsocial-react-hooks": "https://github.com/bitsocialhq/bitsocial-react-hooks.git#b341bd331a6e4cf9611e4303248549d0bcc459d9", + "@bitsocialhq/bitsocial-react-hooks": "https://github.com/bitsocialhq/bitsocial-react-hooks.git#f8cab283d34a422464a61502c248fa2df1040aa1", "@capacitor/app": "7.0.1", "@capacitor/status-bar": "7.0.1", "@capawesome/capacitor-android-edge-to-edge-support": "7.2.2", diff --git a/yarn.lock b/yarn.lock index 87eeb80a..2120c486 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1023,9 +1023,9 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.28.5" -"@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#b341bd331a6e4cf9611e4303248549d0bcc459d9": +"@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#f8cab283d34a422464a61502c248fa2df1040aa1": version "0.1.0" - resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#b341bd331a6e4cf9611e4303248549d0bcc459d9" + resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#f8cab283d34a422464a61502c248fa2df1040aa1" dependencies: "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#10ed04e3866dd986a7f802bc9efd027f0e7d465b" "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git" From ae744d0f78207fb5b14d82b122e5386226764f29 Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 21:44:33 +0800 Subject: [PATCH 15/19] feat(posts): add purge UI feedback for mods Show Purged author/ID, red content message, and file-deleted media when post.commentModeration.purged is true. Mirrors removal UI pattern. --- public/translations/ar/default.json | 4 ++- public/translations/bn/default.json | 4 ++- public/translations/cs/default.json | 4 ++- public/translations/da/default.json | 4 ++- public/translations/de/default.json | 4 ++- public/translations/el/default.json | 4 ++- public/translations/en/default.json | 2 ++ public/translations/es/default.json | 4 ++- public/translations/fa/default.json | 4 ++- public/translations/fi/default.json | 4 ++- public/translations/fil/default.json | 4 ++- public/translations/fr/default.json | 4 ++- public/translations/he/default.json | 4 ++- public/translations/hi/default.json | 4 ++- public/translations/hu/default.json | 4 ++- public/translations/id/default.json | 4 ++- public/translations/it/default.json | 4 ++- public/translations/ja/default.json | 4 ++- public/translations/ko/default.json | 4 ++- public/translations/mr/default.json | 4 ++- public/translations/nl/default.json | 4 ++- public/translations/no/default.json | 4 ++- public/translations/pl/default.json | 4 ++- public/translations/pt/default.json | 4 ++- public/translations/ro/default.json | 4 ++- public/translations/ru/default.json | 4 ++- public/translations/sq/default.json | 4 ++- public/translations/sv/default.json | 4 ++- public/translations/te/default.json | 4 ++- public/translations/th/default.json | 4 ++- public/translations/tr/default.json | 4 ++- public/translations/uk/default.json | 4 ++- public/translations/ur/default.json | 4 ++- public/translations/vi/default.json | 4 ++- public/translations/zh/default.json | 4 ++- .../comment-content/comment-content.tsx | 7 ++-- .../comment-media/comment-media.tsx | 19 +++++++++-- src/components/post-desktop/post-desktop.tsx | 32 +++++++++++++------ src/components/post-mobile/post-mobile.tsx | 20 ++++++++---- src/views/post/post.tsx | 1 + 40 files changed, 163 insertions(+), 54 deletions(-) diff --git a/public/translations/ar/default.json b/public/translations/ar/default.json index f4709908..5f92bc10 100644 --- a/public/translations/ar/default.json +++ b/public/translations/ar/default.json @@ -297,5 +297,7 @@ "link_to_file": "رابط للملف", "support_5chan": "دعم 5chan", "images": "صور", - "load_more": "تحميل المزيد" + "load_more": "تحميل المزيد", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/bn/default.json b/public/translations/bn/default.json index d80e12d2..cc91f65e 100644 --- a/public/translations/bn/default.json +++ b/public/translations/bn/default.json @@ -297,5 +297,7 @@ "link_to_file": "ফাইলের লিংক", "support_5chan": "5chan সমর্থন করুন", "images": "ছবি", - "load_more": "আরও লোড করুন" + "load_more": "আরও লোড করুন", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/cs/default.json b/public/translations/cs/default.json index a553dbac..eb773273 100644 --- a/public/translations/cs/default.json +++ b/public/translations/cs/default.json @@ -297,5 +297,7 @@ "link_to_file": "Odkaz na soubor", "support_5chan": "Podpořte 5chan", "images": "obrázky", - "load_more": "Načíst více" + "load_more": "Načíst více", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/da/default.json b/public/translations/da/default.json index f17e1c51..3ba23a9d 100644 --- a/public/translations/da/default.json +++ b/public/translations/da/default.json @@ -297,5 +297,7 @@ "link_to_file": "Link til fil", "support_5chan": "Støt 5chan", "images": "billeder", - "load_more": "Indlæs mere" + "load_more": "Indlæs mere", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/de/default.json b/public/translations/de/default.json index b5a6aab3..1fc40ccb 100644 --- a/public/translations/de/default.json +++ b/public/translations/de/default.json @@ -297,5 +297,7 @@ "link_to_file": "Link zur Datei", "support_5chan": "5chan unterstützen", "images": "Bilder", - "load_more": "Mehr laden" + "load_more": "Mehr laden", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/el/default.json b/public/translations/el/default.json index 190721b2..f02b9182 100644 --- a/public/translations/el/default.json +++ b/public/translations/el/default.json @@ -297,5 +297,7 @@ "link_to_file": "Σύνδεσμος προς αρχείο", "support_5chan": "Υποστηρίξτε το 5chan", "images": "εικόνες", - "load_more": "Φόρτωση περισσότερων" + "load_more": "Φόρτωση περισσότερων", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/en/default.json b/public/translations/en/default.json index b8f959f2..a7bd9f24 100644 --- a/public/translations/en/default.json +++ b/public/translations/en/default.json @@ -228,6 +228,8 @@ "bitsocial_account": "Bitsocial Account", "purge": "purge", "purge_confirm": "Purging permanently removes this content and all its replies from the database. Continue?", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible.", "mod_queue": "Mod Queue", "moderation_queue": "Moderation Queue", "queue_is_empty": "Queue is empty", diff --git a/public/translations/es/default.json b/public/translations/es/default.json index f6358d5e..e33fde9a 100644 --- a/public/translations/es/default.json +++ b/public/translations/es/default.json @@ -297,5 +297,7 @@ "link_to_file": "Enlace al archivo", "support_5chan": "Apoyar 5chan", "images": "imágenes", - "load_more": "Cargar más" + "load_more": "Cargar más", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/fa/default.json b/public/translations/fa/default.json index 5dc0d85c..9f9215ab 100644 --- a/public/translations/fa/default.json +++ b/public/translations/fa/default.json @@ -297,5 +297,7 @@ "link_to_file": "لینک به فایل", "support_5chan": "از 5chan پشتیبانی کنید", "images": "تصاویر", - "load_more": "بارگذاری بیشتر" + "load_more": "بارگذاری بیشتر", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/fi/default.json b/public/translations/fi/default.json index 6e5af732..dc149e31 100644 --- a/public/translations/fi/default.json +++ b/public/translations/fi/default.json @@ -297,5 +297,7 @@ "link_to_file": "Linkki tiedostoon", "support_5chan": "Tue 5chan", "images": "kuvat", - "load_more": "Lataa lisää" + "load_more": "Lataa lisää", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/fil/default.json b/public/translations/fil/default.json index 35f6181c..4f81dde7 100644 --- a/public/translations/fil/default.json +++ b/public/translations/fil/default.json @@ -297,5 +297,7 @@ "link_to_file": "Link sa File", "support_5chan": "Suportahan ang 5chan", "images": "mga larawan", - "load_more": "Mag-load ng higit pa" + "load_more": "Mag-load ng higit pa", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/fr/default.json b/public/translations/fr/default.json index feaabafe..b753237b 100644 --- a/public/translations/fr/default.json +++ b/public/translations/fr/default.json @@ -297,5 +297,7 @@ "link_to_file": "Lien vers le fichier", "support_5chan": "Soutenir 5chan", "images": "images", - "load_more": "Charger plus" + "load_more": "Charger plus", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/he/default.json b/public/translations/he/default.json index 53a4a99e..33301fa7 100644 --- a/public/translations/he/default.json +++ b/public/translations/he/default.json @@ -297,5 +297,7 @@ "link_to_file": "קישור לקובץ", "support_5chan": "תמוך ב-5chan", "images": "תמונות", - "load_more": "טען עוד" + "load_more": "טען עוד", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/hi/default.json b/public/translations/hi/default.json index 31b5368d..3350c6a3 100644 --- a/public/translations/hi/default.json +++ b/public/translations/hi/default.json @@ -297,5 +297,7 @@ "link_to_file": "फ़ाइल का लिंक", "support_5chan": "5chan का समर्थन करें", "images": "छवियाँ", - "load_more": "और लोड करें" + "load_more": "और लोड करें", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/hu/default.json b/public/translations/hu/default.json index 9f3d3ce8..9e59e9fb 100644 --- a/public/translations/hu/default.json +++ b/public/translations/hu/default.json @@ -297,5 +297,7 @@ "link_to_file": "Link a fájlhoz", "support_5chan": "5chan támogatása", "images": "képek", - "load_more": "További betöltése" + "load_more": "További betöltése", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/id/default.json b/public/translations/id/default.json index 44e812cd..2f7a0fb8 100644 --- a/public/translations/id/default.json +++ b/public/translations/id/default.json @@ -297,5 +297,7 @@ "link_to_file": "Tautan ke File", "support_5chan": "Dukung 5chan", "images": "gambar", - "load_more": "Muat lebih banyak" + "load_more": "Muat lebih banyak", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/it/default.json b/public/translations/it/default.json index 104cdbcf..576982a4 100644 --- a/public/translations/it/default.json +++ b/public/translations/it/default.json @@ -297,5 +297,7 @@ "link_to_file": "Link al file", "support_5chan": "Supporta 5chan", "images": "immagini", - "load_more": "Carica altro" + "load_more": "Carica altro", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/ja/default.json b/public/translations/ja/default.json index e574f2e4..d85e5980 100644 --- a/public/translations/ja/default.json +++ b/public/translations/ja/default.json @@ -297,5 +297,7 @@ "link_to_file": "ファイルへのリンク", "support_5chan": "5chanをサポート", "images": "画像", - "load_more": "さらに読み込む" + "load_more": "さらに読み込む", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/ko/default.json b/public/translations/ko/default.json index 38db9b2c..805d153d 100644 --- a/public/translations/ko/default.json +++ b/public/translations/ko/default.json @@ -297,5 +297,7 @@ "link_to_file": "파일 링크", "support_5chan": "5chan 지원", "images": "이미지", - "load_more": "더 보기" + "load_more": "더 보기", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/mr/default.json b/public/translations/mr/default.json index bcf2dbc1..300b93fb 100644 --- a/public/translations/mr/default.json +++ b/public/translations/mr/default.json @@ -297,5 +297,7 @@ "link_to_file": "फाइलची लिंक", "support_5chan": "5chan चे समर्थन करा", "images": "प्रतिमा", - "load_more": "अधिक लोड करा" + "load_more": "अधिक लोड करा", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/nl/default.json b/public/translations/nl/default.json index 4a0cbdcc..ff0e635e 100644 --- a/public/translations/nl/default.json +++ b/public/translations/nl/default.json @@ -297,5 +297,7 @@ "link_to_file": "Link naar bestand", "support_5chan": "Steun 5chan", "images": "afbeeldingen", - "load_more": "Meer laden" + "load_more": "Meer laden", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/no/default.json b/public/translations/no/default.json index de8d48ee..8d7772c6 100644 --- a/public/translations/no/default.json +++ b/public/translations/no/default.json @@ -297,5 +297,7 @@ "link_to_file": "Lenke til fil", "support_5chan": "Støtt 5chan", "images": "bilder", - "load_more": "Last inn mer" + "load_more": "Last inn mer", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/pl/default.json b/public/translations/pl/default.json index 593fd2e9..99f2106a 100644 --- a/public/translations/pl/default.json +++ b/public/translations/pl/default.json @@ -297,5 +297,7 @@ "link_to_file": "Link do pliku", "support_5chan": "Wspieraj 5chan", "images": "obrazy", - "load_more": "Załaduj więcej" + "load_more": "Załaduj więcej", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/pt/default.json b/public/translations/pt/default.json index 89e601ab..68ed4625 100644 --- a/public/translations/pt/default.json +++ b/public/translations/pt/default.json @@ -297,5 +297,7 @@ "link_to_file": "Link para o arquivo", "support_5chan": "Apoiar 5chan", "images": "imagens", - "load_more": "Carregar mais" + "load_more": "Carregar mais", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/ro/default.json b/public/translations/ro/default.json index 9a2858c6..114a7db4 100644 --- a/public/translations/ro/default.json +++ b/public/translations/ro/default.json @@ -297,5 +297,7 @@ "link_to_file": "Link către fișier", "support_5chan": "Sprijiniți 5chan", "images": "imagini", - "load_more": "Încarcă mai mult" + "load_more": "Încarcă mai mult", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/ru/default.json b/public/translations/ru/default.json index 95c81fc1..6aaf2dc3 100644 --- a/public/translations/ru/default.json +++ b/public/translations/ru/default.json @@ -297,5 +297,7 @@ "link_to_file": "Ссылка на файл", "support_5chan": "Поддержать 5chan", "images": "изображения", - "load_more": "Загрузить ещё" + "load_more": "Загрузить ещё", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/sq/default.json b/public/translations/sq/default.json index e49c7218..e0f57c87 100644 --- a/public/translations/sq/default.json +++ b/public/translations/sq/default.json @@ -297,5 +297,7 @@ "link_to_file": "Lidhje me skedarin", "support_5chan": "Mbështetni 5chan", "images": "imazhe", - "load_more": "Ngarko më shumë" + "load_more": "Ngarko më shumë", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/sv/default.json b/public/translations/sv/default.json index fa89c8bc..82acf314 100644 --- a/public/translations/sv/default.json +++ b/public/translations/sv/default.json @@ -297,5 +297,7 @@ "link_to_file": "Länk till fil", "support_5chan": "Stöd 5chan", "images": "bilder", - "load_more": "Ladda mer" + "load_more": "Ladda mer", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/te/default.json b/public/translations/te/default.json index fe0c9722..4222b055 100644 --- a/public/translations/te/default.json +++ b/public/translations/te/default.json @@ -297,5 +297,7 @@ "link_to_file": "ఫైల్‌కు లింక్", "support_5chan": "5chanకు మద్దతు ఇవ్వండి", "images": "చిత్రాలు", - "load_more": "మరింత లోడ్ చేయండి" + "load_more": "మరింత లోడ్ చేయండి", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/th/default.json b/public/translations/th/default.json index 1ab00f2e..a6bd6e41 100644 --- a/public/translations/th/default.json +++ b/public/translations/th/default.json @@ -297,5 +297,7 @@ "link_to_file": "ลิงก์ไปยังไฟล์", "support_5chan": "สนับสนุน 5chan", "images": "รูปภาพ", - "load_more": "โหลดเพิ่มเติม" + "load_more": "โหลดเพิ่มเติม", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/tr/default.json b/public/translations/tr/default.json index 5b97218d..4df9f35c 100644 --- a/public/translations/tr/default.json +++ b/public/translations/tr/default.json @@ -297,5 +297,7 @@ "link_to_file": "Dosyaya bağlantı", "support_5chan": "5chan'ı Destekle", "images": "görseller", - "load_more": "Daha fazla yükle" + "load_more": "Daha fazla yükle", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/uk/default.json b/public/translations/uk/default.json index 07ad6144..6869d4a4 100644 --- a/public/translations/uk/default.json +++ b/public/translations/uk/default.json @@ -297,5 +297,7 @@ "link_to_file": "Посилання на файл", "support_5chan": "Підтримати 5chan", "images": "зображення", - "load_more": "Завантажити ще" + "load_more": "Завантажити ще", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/ur/default.json b/public/translations/ur/default.json index 470e7d03..e3795b5d 100644 --- a/public/translations/ur/default.json +++ b/public/translations/ur/default.json @@ -297,5 +297,7 @@ "link_to_file": "فائل کا لنک", "support_5chan": "5chan کی حمایت کریں", "images": "تصاویر", - "load_more": "مزید لوڈ کریں" + "load_more": "مزید لوڈ کریں", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/vi/default.json b/public/translations/vi/default.json index 0a345bfa..b1e19345 100644 --- a/public/translations/vi/default.json +++ b/public/translations/vi/default.json @@ -297,5 +297,7 @@ "link_to_file": "Liên kết đến tệp", "support_5chan": "Hỗ trợ 5chan", "images": "hình ảnh", - "load_more": "Tải thêm" + "load_more": "Tải thêm", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/public/translations/zh/default.json b/public/translations/zh/default.json index 9c91aa60..c4af4f73 100644 --- a/public/translations/zh/default.json +++ b/public/translations/zh/default.json @@ -297,5 +297,7 @@ "link_to_file": "链接到文件", "support_5chan": "支持 5chan", "images": "图片", - "load_more": "加载更多" + "load_more": "加载更多", + "purged": "purged", + "this_post_was_purged": "Purging from board database — this process is irreversible." } diff --git a/src/components/comment-content/comment-content.tsx b/src/components/comment-content/comment-content.tsx index 38145f0e..b44ea9e4 100644 --- a/src/components/comment-content/comment-content.tsx +++ b/src/components/comment-content/comment-content.tsx @@ -71,6 +71,7 @@ const CommentContent = ({ comment: post }: { comment: Comment }) => { const isMobile = useIsMobile(); const { cid, content, deleted, edit, original, parentCid, postCid, pendingApproval, quotedCids, reason, removed, state, subplebbitAddress } = post || {}; + const purged = post?.commentModeration?.purged; const banned = !!post?.author?.subplebbit?.banExpiresAt; const [showFullComment, setShowFullComment] = useState(false); @@ -127,11 +128,13 @@ const CommentContent = ({ comment: post }: { comment: Comment }) => {
{isReply && !hasFailedState && - !(deleted || removed) && + !(deleted || removed || purged) && (filteredQuotedCids.length > 0 ? filteredQuotedCids.map((cid: string) => ) : shouldShowReplyingToReply && )} - {removed ? ( + {purged ? ( + {capitalize(t('this_post_was_purged'))} + ) : removed ? ( reason ? ( <> ({t('this_post_was_removed')}) diff --git a/src/components/comment-media/comment-media.tsx b/src/components/comment-media/comment-media.tsx index 5ec52d13..30b7ed6d 100644 --- a/src/components/comment-media/comment-media.tsx +++ b/src/components/comment-media/comment-media.tsx @@ -20,13 +20,26 @@ interface MediaProps { linkHeight?: number; linkWidth?: number; parentCid?: string; + purged?: boolean; removed?: boolean; spoiler?: boolean; showThumbnail?: boolean; setShowThumbnail: (showThumbnail: boolean) => void; } -const Thumbnail = ({ commentMediaInfo, deleted, displayHeight, displayWidth, isFloatingEmbed, isOutOfFeed, isReply, removed, spoiler, setShowThumbnail }: MediaProps) => { +const Thumbnail = ({ + commentMediaInfo, + deleted, + displayHeight, + displayWidth, + isFloatingEmbed, + isOutOfFeed, + isReply, + purged, + removed, + spoiler, + setShowThumbnail, +}: MediaProps) => { const isMobile = useIsMobile(); const { patternThumbnailUrl, thumbnail, type, url } = commentMediaInfo || {}; @@ -133,7 +146,7 @@ const Thumbnail = ({ commentMediaInfo, deleted, displayHeight, displayWidth, isF ) ) : null; - return deleted || removed ? ( + return deleted || removed || purged ? ( File deleted ) : spoiler ? ( }) => { const { t } = useTranslation(); const { author, cid, deleted, locked, pinned, parentCid, postCid, reason, removed, state, subplebbitAddress, timestamp } = post || {}; + const purged = post?.commentModeration?.purged; const title = post?.title?.trim(); const { address, shortAddress } = author || {}; const displayName = author?.displayName?.trim(); @@ -222,7 +223,7 @@ const PostInfo = ({ const handleUserAddressClick = useAuthorAddressClick(); const numberOfPostsByAuthor = (() => { - if (!showUserID || deleted || removed || !shortAddress || !postCid || typeof document === 'undefined') { + if (!showUserID || deleted || removed || purged || !shortAddress || !postCid || typeof document === 'undefined') { return 0; } @@ -239,7 +240,7 @@ const PostInfo = ({ ? isReply ? alert(t('this_reply_was_deleted')) : alert(t('this_thread_was_deleted')) - : removed + : removed || purged ? isReply ? alert(t('this_reply_was_removed')) : alert(t('this_thread_was_removed')) @@ -266,7 +267,7 @@ const PostInfo = ({ return (
{isHidden ? parentCid && : } - + {title && (title.length <= 75 ? ( {title} @@ -276,11 +277,13 @@ const PostInfo = ({ ))} - + {deleted ? ( capitalize(t('deleted')) ) : removed ? ( capitalize(t('removed')) + ) : purged ? ( + capitalize(t('purged')) ) : displayName ? ( displayName.length <= 20 ? ( displayName @@ -292,7 +295,7 @@ const PostInfo = ({ ) : ( capitalize(t('anonymous')) )} - {!(deleted || removed) && authorRole && ( + {!(deleted || removed || purged) && authorRole && ( {' '} ## Board {authorRole}{' '} @@ -310,6 +313,8 @@ const PostInfo = ({ t('deleted') ) : removed ? ( t('removed') + ) : purged ? ( + t('purged') ) : !cid && pseudonymityMode ? ( {hasFailedState ? capitalize(t('failed')) : capitalize(t('pending'))} ) : ( @@ -481,7 +486,7 @@ const PostInfo = ({ )} - {!(removed || deleted) && !isModQueue && } + {!(removed || deleted || purged) && !isModQueue && } {cid && parentCid && } {cid && !parentCid && } @@ -544,6 +549,7 @@ interface PostMediaProps { hasThumbnail: boolean; spoiler: boolean; deleted: boolean; + purged: boolean; removed: boolean; linkHeight: number; linkWidth: number; @@ -559,6 +565,7 @@ const PostMedia = ({ hasThumbnail, spoiler, deleted, + purged, removed, linkHeight, linkWidth, @@ -663,6 +670,7 @@ const PostMedia = ({ - {link && !hidden && !(deleted || removed) && isValidURL(link) && ( + {link && !hidden && !(deleted || removed || purged) && isValidURL(link) && ( )} - {!hidden && (!(removed || deleted) || ((removed || deleted) && reason)) && } + {!hidden && (!(removed || deleted || purged) || ((removed || deleted) && reason)) && }
); @@ -763,6 +773,7 @@ const PostDesktop = ({ }: PostProps) => { const { t } = useTranslation(); const { author, cid, content, deleted, link, linkHeight, linkWidth, pinned, postCid, removed, spoiler, state, subplebbitAddress, thumbnailUrl, parentCid } = post || {}; + const purged = post?.commentModeration?.purged; const params = useParams(); const location = useLocation(); const navigationType = useNavigationType(); @@ -969,12 +980,13 @@ const PostDesktop = ({ )} - {link && !isHidden && !(deleted || removed) && isValidURL(link) && ( + {link && !isHidden && !(deleted || removed || purged) && isValidURL(link) && ( - {!isHidden && !content && !(deleted || removed) &&
} + {!isHidden && !content && !(deleted || removed || purged) &&
} {!isHidden && }
{!isHidden && !isInPendingPostView && showReplies && repliesCount > 0 && !isInPostPageView && ( diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index 5032efd8..c62efbd6 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -59,6 +59,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos const directories = useDirectories(); const { author, cid, deleted, link, linkHeight, linkWidth, locked, parentCid, pinned, postCid, reason, removed, state, subplebbitAddress, timestamp, thumbnailUrl } = post || {}; + const purged = post?.commentModeration?.purged; const boardPath = subplebbitAddress ? getBoardPath(subplebbitAddress, directories) : undefined; const displayBoardPath = boardPath && subplebbitAddress @@ -217,7 +218,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos ? isReply ? alert(t('this_reply_was_deleted')) : alert(t('this_thread_was_deleted')) - : removed + : removed || purged ? isReply ? alert(t('this_reply_was_removed')) : alert(t('this_thread_was_removed')) @@ -246,13 +247,15 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos <>
- + - + {removed ? ( capitalize(t('removed')) ) : deleted ? ( capitalize(t('deleted')) + ) : purged ? ( + capitalize(t('purged')) ) : displayName ? ( displayName.length <= 20 ? ( displayName @@ -264,7 +267,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos ) : ( capitalize(t('anonymous')) )}{' '} - {!(deleted || removed) && authorRole && ( + {!(deleted || removed || purged) && authorRole && ( {' '} ## Board {authorRole}{' '} @@ -285,6 +288,8 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos lowerCase(t('removed')) ) : deleted ? ( lowerCase(t('deleted')) + ) : purged ? ( + lowerCase(t('purged')) ) : !cid && pseudonymityMode ? ( {hasFailedState ? capitalize(t('failed')) : capitalize(t('pending'))} ) : ( @@ -423,7 +428,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos )}
- {(hasThumbnail || link) && !(deleted || removed) && } + {(hasThumbnail || link) && !(deleted || removed || purged) && } ); }; @@ -431,6 +436,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos const PostMediaContent = ({ post, link }: { post: any; link: string }) => { const [showThumbnail, setShowThumbnail] = useState(true); const { thumbnailUrl, linkWidth, linkHeight, spoiler, deleted, removed, parentCid } = post || {}; + const purged = post?.commentModeration?.purged; const commentMediaInfo = useCommentMediaInfo(link, thumbnailUrl, linkWidth, linkHeight); return ( @@ -438,6 +444,7 @@ const PostMediaContent = ({ post, link }: { post: any; link: string }) => { - {!hidden && (!(removed || deleted) || ((removed || deleted) && reason)) && } + {!hidden && (!(removed || deleted || purged) || ((removed || deleted) && reason)) && }
diff --git a/src/views/post/post.tsx b/src/views/post/post.tsx index d22bbe75..e124021a 100644 --- a/src/views/post/post.tsx +++ b/src/views/post/post.tsx @@ -110,6 +110,7 @@ export const Post = memo( prev?.pinned === next?.pinned && prev?.removed === next?.removed && prev?.deleted === next?.deleted && + prev?.commentModeration?.purged === next?.commentModeration?.purged && prevProps.showAllReplies === nextProps.showAllReplies && prevProps.showReplies === nextProps.showReplies && prevProps.targetReplyCid === nextProps.targetReplyCid && From affea1b3ed867e2da3a9f5d1c7323c41fc346323 Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 21:46:14 +0800 Subject: [PATCH 16/19] fix(comment-content): use info text style for purge message instead of red caps --- src/components/comment-content/comment-content.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/comment-content/comment-content.tsx b/src/components/comment-content/comment-content.tsx index b44ea9e4..3efc10b5 100644 --- a/src/components/comment-content/comment-content.tsx +++ b/src/components/comment-content/comment-content.tsx @@ -133,7 +133,7 @@ const CommentContent = ({ comment: post }: { comment: Comment }) => { ? filteredQuotedCids.map((cid: string) => ) : shouldShowReplyingToReply && )} {purged ? ( - {capitalize(t('this_post_was_purged'))} + {capitalize(t('this_post_was_purged'))} ) : removed ? ( reason ? ( <> From da7757075fa8bef08a7e5ea67bab9bc8dcd4ddb6 Mon Sep 17 00:00:00 2001 From: plebeius Date: Fri, 6 Mar 2026 22:15:54 +0800 Subject: [PATCH 17/19] Update 5chan-directories.json --- src/data/5chan-directories.json | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/data/5chan-directories.json b/src/data/5chan-directories.json index fd4244ee..105e25cd 100644 --- a/src/data/5chan-directories.json +++ b/src/data/5chan-directories.json @@ -5,7 +5,7 @@ "updatedAt": 1771140295, "communities": [ { - "address": "anime-and-manga.eth", + "address": "anime-and-manga.bso", "title": "/a/ - Anime & Manga", "directoryCode": "a", "features": { @@ -21,7 +21,7 @@ } }, { - "address": "food-and-cooking.eth", + "address": "food-and-cooking.bso", "title": "/ck/ - Food & Cooking", "directoryCode": "ck", "features": { @@ -37,7 +37,7 @@ } }, { - "address": "politically-incorrect.eth", + "address": "politically-incorrect.bso", "title": "/pol/ - Politically Incorrect", "directoryCode": "pol", "features": { @@ -53,7 +53,7 @@ } }, { - "address": "business-and-finance.eth", + "address": "business-and-finance.bso", "title": "/biz/ - Business & Finance", "directoryCode": "biz", "features": { @@ -69,7 +69,7 @@ } }, { - "address": "science-and-math.eth", + "address": "science-and-math.bso", "title": "/sci/ - Science & Math", "directoryCode": "sci", "features": { @@ -85,7 +85,7 @@ } }, { - "address": "technology-posting.eth", + "address": "technology-posting.bso", "title": "/g/ - Technology", "directoryCode": "g", "features": { @@ -101,7 +101,7 @@ } }, { - "address": "videogame-generals.eth", + "address": "videogame-generals.bso", "title": "/vg/ - Video Game Generals", "directoryCode": "vg", "features": { @@ -117,7 +117,7 @@ } }, { - "address": "fitness-posting.eth", + "address": "fitness-posting.bso", "title": "/fit/ - Fitness", "directoryCode": "fit", "features": { @@ -133,7 +133,7 @@ } }, { - "address": "advice-posting.eth", + "address": "advice-posting.bso", "title": "/adv/ - Advice", "directoryCode": "adv", "features": { @@ -149,7 +149,7 @@ } }, { - "address": "worksafe-gif.eth", + "address": "worksafe-gif.bso", "title": "/wsg/ - Worksafe GIF", "directoryCode": "wsg", "features": { @@ -165,7 +165,7 @@ } }, { - "address": "do-it-yourself.eth", + "address": "do-it-yourself.bso", "title": "/diy/ - Do It Yourself", "directoryCode": "diy", "features": { @@ -181,7 +181,7 @@ } }, { - "address": "outdoors-posting.eth", + "address": "outdoors-posting.bso", "title": "/out/ - Outdoors", "directoryCode": "out", "features": { @@ -197,7 +197,7 @@ } }, { - "address": "artwork-critique.eth", + "address": "artwork-critique.bso", "title": "/ic/ - Artwork/Critique", "directoryCode": "ic", "features": { @@ -213,7 +213,7 @@ } }, { - "address": "music-posting.eth", + "address": "music-posting.bso", "title": "/mu/ - Music", "directoryCode": "mu", "features": { @@ -229,7 +229,7 @@ } }, { - "address": "international-sfw.eth", + "address": "international-sfw.bso", "title": "/int/ - International", "directoryCode": "int", "features": { @@ -245,7 +245,7 @@ } }, { - "address": "literature-posting.eth", + "address": "literature-posting.bso", "title": "/lit/ - Literature", "directoryCode": "lit", "features": { @@ -261,7 +261,7 @@ } }, { - "address": "television-and-film.eth", + "address": "television-and-film.bso", "title": "/tv/ - Television & Film", "directoryCode": "tv", "features": { @@ -277,7 +277,7 @@ } }, { - "address": "very-important-posts.eth", + "address": "very-important-posts.bso", "title": "/vip/ - Very Important Posts", "directoryCode": "vip", "features": { @@ -293,7 +293,7 @@ } }, { - "address": "adult-gif.eth", + "address": "adult-gif.bso", "title": "/gif/ - Adult GIF", "directoryCode": "gif", "features": { @@ -309,7 +309,7 @@ } }, { - "address": "international-nsfw.eth", + "address": "international-nsfw.bso", "title": "/bant/ - International/Random", "directoryCode": "bant", "features": { @@ -325,7 +325,7 @@ } }, { - "address": "random-nsfw.eth", + "address": "random-nsfw.bso", "title": "/b/ - Random", "directoryCode": "b", "features": { From 109811d144cff3db2b6cdbac7ee0ce46bb23989b Mon Sep 17 00:00:00 2001 From: plebeius Date: Sat, 7 Mar 2026 12:41:37 +0800 Subject: [PATCH 18/19] chore(deps): upgrade bitsocial-react-hooks --- package.json | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 549aaeae..7935d254 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "GPL-2.0-only", "private": true, "dependencies": { - "@bitsocialhq/bitsocial-react-hooks": "https://github.com/bitsocialhq/bitsocial-react-hooks.git#f8cab283d34a422464a61502c248fa2df1040aa1", + "@bitsocialhq/bitsocial-react-hooks": "https://github.com/bitsocialhq/bitsocial-react-hooks.git#56d97f7df902a037a36ecf15336493fe7bb93c2b", "@capacitor/app": "7.0.1", "@capacitor/status-bar": "7.0.1", "@capawesome/capacitor-android-edge-to-edge-support": "7.2.2", diff --git a/yarn.lock b/yarn.lock index 2120c486..700edfb0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1023,9 +1023,9 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.28.5" -"@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#f8cab283d34a422464a61502c248fa2df1040aa1": +"@bitsocialhq/bitsocial-react-hooks@https://github.com/bitsocialhq/bitsocial-react-hooks.git#56d97f7df902a037a36ecf15336493fe7bb93c2b": version "0.1.0" - resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#f8cab283d34a422464a61502c248fa2df1040aa1" + resolved "https://github.com/bitsocialhq/bitsocial-react-hooks.git#56d97f7df902a037a36ecf15336493fe7bb93c2b" dependencies: "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#10ed04e3866dd986a7f802bc9efd027f0e7d465b" "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git" From 08d929bb9713374b7c6715e1f0d79558151f8985 Mon Sep 17 00:00:00 2001 From: plebeius Date: Sat, 7 Mar 2026 12:46:37 +0800 Subject: [PATCH 19/19] fix(posts): render per-post IDs on initial board load --- src/components/post-desktop/post-desktop.tsx | 6 ++--- src/components/post-mobile/post-mobile.tsx | 6 ++--- src/hooks/use-board-pseudonymity-mode.ts | 13 ++++++++++ src/hooks/use-directories.ts | 27 +++++++++++++++++++- 4 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 src/hooks/use-board-pseudonymity-mode.ts diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index 87b02430..72a4ca6c 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -22,7 +22,7 @@ import useHide from '../../hooks/use-hide'; import useStateString from '../../hooks/use-state-string'; import useScrollToReply from '../../hooks/use-scroll-to-reply'; import { useCurrentTime } from '../../hooks/use-current-time'; -import { useSubplebbitField } from '../../hooks/use-stable-subplebbit'; +import { useBoardPseudonymityMode } from '../../hooks/use-board-pseudonymity-mode'; import CommentContent from '../comment-content'; import CommentMedia from '../comment-media'; import EditMenu from '../edit-menu/edit-menu'; @@ -214,11 +214,11 @@ const PostInfo = ({ const alertThresholdSeconds = getAlertThresholdSeconds(); const isOverThreshold = isAwaitingApproval && timeWaiting > alertThresholdSeconds; - const userID = address && getShortAddress(address); // shortened to 8 chars for display; users can verify the full user ID via "Copy user ID" in the post menu to guard against spoofing + const userID = address ? getShortAddress(address) : shortAddress; const userIDBackgroundColor = hashStringToColor(userID); const userIDTextColor = getTextColorForBackground(userIDBackgroundColor); - const pseudonymityMode = useSubplebbitField(subplebbitAddress, (sub) => sub?.features?.pseudonymityMode); + const pseudonymityMode = useBoardPseudonymityMode(subplebbitAddress); const showUserID = pseudonymityMode === 'per-post'; const handleUserAddressClick = useAuthorAddressClick(); diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index c62efbd6..8aee0776 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -21,7 +21,7 @@ import useHide from '../../hooks/use-hide'; import useStateString from '../../hooks/use-state-string'; import useScrollToReply from '../../hooks/use-scroll-to-reply'; import { useCurrentTime } from '../../hooks/use-current-time'; -import { useSubplebbitField } from '../../hooks/use-stable-subplebbit'; +import { useBoardPseudonymityMode } from '../../hooks/use-board-pseudonymity-mode'; import CommentContent from '../comment-content'; import CommentMedia from '../comment-media'; import LoadingEllipsis from '../loading-ellipsis'; @@ -192,7 +192,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos const canDeleteFailedPost = hasFailedState && typeof post?.index === 'number'; const postMenuProps = selectPostMenuProps(post); - const pseudonymityMode = useSubplebbitField(subplebbitAddress, (sub) => sub?.features?.pseudonymityMode); + const pseudonymityMode = useBoardPseudonymityMode(subplebbitAddress); const showUserID = pseudonymityMode === 'per-post'; const handleUserAddressClick = useAuthorAddressClick(); @@ -205,7 +205,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles, threadNumber }: Pos return Math.max(domCount, 1); })(); - const userID = address && getShortAddress(address); // shortened to 8 chars for display; users can verify the full user ID via "Copy user ID" in the post menu to guard against spoofing + const userID = address ? getShortAddress(address) : shortAddress; const userIDBackgroundColor = hashStringToColor(userID); const userIDTextColor = getTextColorForBackground(userIDBackgroundColor); diff --git a/src/hooks/use-board-pseudonymity-mode.ts b/src/hooks/use-board-pseudonymity-mode.ts new file mode 100644 index 00000000..eb77727e --- /dev/null +++ b/src/hooks/use-board-pseudonymity-mode.ts @@ -0,0 +1,13 @@ +import { useDirectoryByAddress } from './use-directories'; +import { useSubplebbitField } from './use-stable-subplebbit'; + +/** + * Prefer authoritative live board metadata when available, but fall back to the + * bundled directory entry so known boards can render IDs immediately on first load. + */ +export const useBoardPseudonymityMode = (subplebbitAddress: string | undefined): string | undefined => { + const directory = useDirectoryByAddress(subplebbitAddress); + const livePseudonymityMode = useSubplebbitField(subplebbitAddress, (sub) => sub?.features?.pseudonymityMode); + + return livePseudonymityMode ?? directory?.features?.pseudonymityMode; +}; diff --git a/src/hooks/use-directories.ts b/src/hooks/use-directories.ts index 80b68df4..3cfe5afe 100644 --- a/src/hooks/use-directories.ts +++ b/src/hooks/use-directories.ts @@ -50,6 +50,7 @@ const CACHE_MAX_AGE_MS = 60 * 60 * 1000; // 1 hour let cacheCommunities: DirectoryCommunity[] | null = null; let cacheMetadata: DirectoriesMetadata | null = null; let inFlightGitHubFetch: Promise | null = null; +const DIRECTORY_ALIAS_SUFFIXES = ['.bso', '.eth'] as const; const isRecord = (value: unknown): value is Record => typeof value === 'object' && value !== null; @@ -134,6 +135,30 @@ const adaptV2Directories = (value: Record): DirectoryCommunity[ return dedupeCommunities(communities); }; +const getDirectoryAddressLookupKey = (address: string): string => { + for (const suffix of DIRECTORY_ALIAS_SUFFIXES) { + if (address.endsWith(suffix)) { + return address.slice(0, -suffix.length); + } + } + + return address; +}; + +const findDirectoryByAddress = (directories: DirectoryCommunity[], address: string | undefined): DirectoryCommunity | undefined => { + if (!address) { + return undefined; + } + + const exactMatch = directories.find((community) => community.address === address); + if (exactMatch) { + return exactMatch; + } + + const addressLookupKey = getDirectoryAddressLookupKey(address); + return directories.find((community) => getDirectoryAddressLookupKey(community.address) === addressLookupKey); +}; + const adaptV1Communities = (value: Record): DirectoryCommunity[] => { if (!Array.isArray(value.communities)) { return []; @@ -376,7 +401,7 @@ export const useDirectoryAddresses = () => { export const useDirectoryByAddress = (address: string | undefined) => { const directories = useDirectories(); - return useMemo(() => (address ? directories.find((c) => c.address === address) : undefined), [directories, address]); + return useMemo(() => findDirectoryByAddress(directories, address), [directories, address]); }; export const useDirectoriesMetadata = () => {