From 3890792bb195a474817e961837c13bd6b05294a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 6 Nov 2025 16:49:37 +0100 Subject: [PATCH] pl-fe: don't assume everything that looks like a crypto address is a crypto address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-api/lib/request.ts | 1 - packages/pl-fe/src/components/account-hover-card.tsx | 1 - .../crypto-donate/components/crypto-address.tsx | 3 ++- .../components/detailed-crypto-address.tsx | 3 ++- .../ui/components/panels/profile-fields-panel.tsx | 2 +- .../ui/components/panels/profile-info-panel.tsx | 2 +- .../src/features/ui/components/profile-field.tsx | 11 ++++++++--- .../pl-fe/src/features/ui/util/async-components.ts | 4 +--- packages/pl-fe/src/features/video/index.tsx | 1 - packages/pl-fe/src/hooks/forms/use-image-field.ts | 1 - packages/pl-fe/src/modals/list-editor-modal/index.tsx | 1 - packages/pl-fe/src/pages/dashboard/user-index.tsx | 1 - packages/pl-fe/src/queries/admin/use-accounts.ts | 2 -- 13 files changed, 15 insertions(+), 18 deletions(-) diff --git a/packages/pl-api/lib/request.ts b/packages/pl-api/lib/request.ts index 05b28eef2..3c528dab7 100644 --- a/packages/pl-api/lib/request.ts +++ b/packages/pl-api/lib/request.ts @@ -70,7 +70,6 @@ const getAsyncRefreshHeader = (response: Pick): AsyncRefres return null; }; - interface RequestBody> { method?: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; body?: any; diff --git a/packages/pl-fe/src/components/account-hover-card.tsx b/packages/pl-fe/src/components/account-hover-card.tsx index fd1a8f1d2..a784bf8e4 100644 --- a/packages/pl-fe/src/components/account-hover-card.tsx +++ b/packages/pl-fe/src/components/account-hover-card.tsx @@ -80,7 +80,6 @@ const AccountHoverCard: React.FC = ({ visible = true }) => { }; }, []); - const { x, y, strategy, refs, context, placement } = useFloating({ open: !!account, elements: { diff --git a/packages/pl-fe/src/features/crypto-donate/components/crypto-address.tsx b/packages/pl-fe/src/features/crypto-donate/components/crypto-address.tsx index 622e6cff1..c0774611d 100644 --- a/packages/pl-fe/src/features/crypto-donate/components/crypto-address.tsx +++ b/packages/pl-fe/src/features/crypto-donate/components/crypto-address.tsx @@ -5,11 +5,12 @@ import HStack from 'pl-fe/components/ui/hstack'; import Icon from 'pl-fe/components/ui/icon'; import Stack from 'pl-fe/components/ui/stack'; import Text from 'pl-fe/components/ui/text'; -import { CryptoIcon } from 'pl-fe/features/ui/util/async-components'; import { useModalsActions } from 'pl-fe/stores/modals'; import { getTitle } from '../utils/coin-db'; +import CryptoIcon from './crypto-icon'; + interface ICryptoAddress { address: string; ticker: string; diff --git a/packages/pl-fe/src/features/crypto-donate/components/detailed-crypto-address.tsx b/packages/pl-fe/src/features/crypto-donate/components/detailed-crypto-address.tsx index 0c339b873..7efcce64a 100644 --- a/packages/pl-fe/src/features/crypto-donate/components/detailed-crypto-address.tsx +++ b/packages/pl-fe/src/features/crypto-donate/components/detailed-crypto-address.tsx @@ -2,10 +2,11 @@ import { QRCodeCanvas as QRCode } from 'qrcode.react'; import React from 'react'; import CopyableInput from 'pl-fe/components/copyable-input'; -import { CryptoIcon } from 'pl-fe/features/ui/util/async-components'; import { getTitle } from '../utils/coin-db'; +import CryptoIcon from './crypto-icon'; + interface IDetailedCryptoAddress { address: string; ticker: string; diff --git a/packages/pl-fe/src/features/ui/components/panels/profile-fields-panel.tsx b/packages/pl-fe/src/features/ui/components/panels/profile-fields-panel.tsx index c7842690e..fbdbff320 100644 --- a/packages/pl-fe/src/features/ui/components/panels/profile-fields-panel.tsx +++ b/packages/pl-fe/src/features/ui/components/panels/profile-fields-panel.tsx @@ -3,7 +3,7 @@ import React from 'react'; import Stack from 'pl-fe/components/ui/stack'; import Widget from 'pl-fe/components/ui/widget'; -import ProfileField from '../profile-field'; +import { ProfileField } from '../../util/async-components'; import type { Account } from 'pl-api'; diff --git a/packages/pl-fe/src/features/ui/components/panels/profile-info-panel.tsx b/packages/pl-fe/src/features/ui/components/panels/profile-info-panel.tsx index 60041531e..ee930ffdb 100644 --- a/packages/pl-fe/src/features/ui/components/panels/profile-info-panel.tsx +++ b/packages/pl-fe/src/features/ui/components/panels/profile-info-panel.tsx @@ -17,8 +17,8 @@ import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config'; import { accountScrobbleQueryOptions } from 'pl-fe/queries/accounts/account-scrobble'; import { capitalize } from 'pl-fe/utils/strings'; +import { ProfileField } from '../../util/async-components'; import ProfileFamiliarFollowers from '../profile-familiar-followers'; -import ProfileField from '../profile-field'; import ProfileStats from '../profile-stats'; import type { Account } from 'pl-api'; diff --git a/packages/pl-fe/src/features/ui/components/profile-field.tsx b/packages/pl-fe/src/features/ui/components/profile-field.tsx index 7c442b15e..b05a8ef62 100644 --- a/packages/pl-fe/src/features/ui/components/profile-field.tsx +++ b/packages/pl-fe/src/features/ui/components/profile-field.tsx @@ -7,14 +7,19 @@ import Markup from 'pl-fe/components/markup'; import { ParsedContent } from 'pl-fe/components/parsed-content'; import HStack from 'pl-fe/components/ui/hstack'; import Icon from 'pl-fe/components/ui/icon'; +import CryptoAddress from 'pl-fe/features/crypto-donate/components/crypto-address'; +import LightningAddress from 'pl-fe/features/crypto-donate/components/lightning-address'; +import coinDB from 'pl-fe/features/crypto-donate/utils/manifest-map'; import Emojify from 'pl-fe/features/emoji/emojify'; -import { CryptoAddress, LightningAddress } from 'pl-fe/features/ui/util/async-components'; import { unescapeHTML } from 'pl-fe/utils/html'; import type { Account } from 'pl-api'; const getTicker = (value: string): string => (value.match(/\$([a-zA-Z]*)/i) || [])[1]; -const isTicker = (value: string): boolean => Boolean(getTicker(value)); +const isTicker = (value: string): boolean => { + const ticker = getTicker(value); + return Boolean(ticker) && Boolean(coinDB[ticker.toLowerCase()]); +}; const isZapEmoji = (value: string) => /^\u26A1[\uFE00-\uFE0F]?$/.test(value); const isTimezoneLabel = (value: string) => /^time( |)zone$/i.test(value); @@ -49,7 +54,7 @@ const ProfileField: React.FC = ({ accountId, field, emojis }) => address={unescapeHTML(field.value)} /> ); - } else if (isZapEmoji(field.name)) { + } else if (isZapEmoji(field.name) && field.value.includes('@')) { return ; } diff --git a/packages/pl-fe/src/features/ui/util/async-components.ts b/packages/pl-fe/src/features/ui/util/async-components.ts index c4e4695b0..103db653a 100644 --- a/packages/pl-fe/src/features/ui/util/async-components.ts +++ b/packages/pl-fe/src/features/ui/util/async-components.ts @@ -125,15 +125,13 @@ export const Audio = lazy(() => import('pl-fe/features/audio')); export const ChatWidget = lazy(() => import('pl-fe/features/chats/components/chat-widget/chat-widget')); export const ComposeEditor = lazy(() => import('pl-fe/features/compose/editor')); export const ComposeForm = lazy(() => import('pl-fe/features/compose/components/compose-form')); -export const CryptoAddress = lazy(() => import('pl-fe/features/crypto-donate/components/crypto-address')); -export const CryptoIcon = lazy(() => import('pl-fe/features/crypto-donate/components/crypto-icon')); export const DatePicker = lazy(() => import('pl-fe/features/birthdays/date-picker')); export const DropdownNavigation = lazy(() => import('pl-fe/components/dropdown-navigation')); export const EmojiPicker = lazy(() => import('pl-fe/features/emoji/components/emoji-picker')); export const EventHeader = lazy(() => import('pl-fe/features/event/components/event-header')); -export const LightningAddress = lazy(() => import('pl-fe/features/crypto-donate/components/lightning-address')); export const MfaForm = lazy(() => import('pl-fe/features/security/mfa-form')); export const ModalRoot = lazy(() => import('pl-fe/features/ui/components/modal-root')); +export const ProfileField = lazy(() => import('pl-fe/features/ui/components/profile-field')); export const AccountHoverCard = lazy(() => import('pl-fe/components/account-hover-card')); export const StatusHoverCard = lazy(() => import('pl-fe/components/status-hover-card')); export const Video = lazy(() => import('pl-fe/features/video')); diff --git a/packages/pl-fe/src/features/video/index.tsx b/packages/pl-fe/src/features/video/index.tsx index 5530cccf7..d4193f2a8 100644 --- a/packages/pl-fe/src/features/video/index.tsx +++ b/packages/pl-fe/src/features/video/index.tsx @@ -240,7 +240,6 @@ const Video: React.FC = ({ e.stopPropagation(); }; - const handleMouseMove = useCallback(throttle(e => { if (seek.current && video.current) { const { x } = getPointerPosition(seek.current, e); diff --git a/packages/pl-fe/src/hooks/forms/use-image-field.ts b/packages/pl-fe/src/hooks/forms/use-image-field.ts index 4bbdcf6f9..f8d353504 100644 --- a/packages/pl-fe/src/hooks/forms/use-image-field.ts +++ b/packages/pl-fe/src/hooks/forms/use-image-field.ts @@ -3,7 +3,6 @@ import { useState } from 'react'; import { useSettings } from 'pl-fe/stores/settings'; import resizeImage from 'pl-fe/utils/resize-image'; - import { usePreview } from './use-preview'; interface UseImageFieldOpts { diff --git a/packages/pl-fe/src/modals/list-editor-modal/index.tsx b/packages/pl-fe/src/modals/list-editor-modal/index.tsx index 2d712c7ab..c01e1d242 100644 --- a/packages/pl-fe/src/modals/list-editor-modal/index.tsx +++ b/packages/pl-fe/src/modals/list-editor-modal/index.tsx @@ -19,7 +19,6 @@ const ListEditorModal: React.FC = ({ list const { isFetched } = useList(listId); - const onClickClose = () => { onClose('LIST_EDITOR'); }; diff --git a/packages/pl-fe/src/pages/dashboard/user-index.tsx b/packages/pl-fe/src/pages/dashboard/user-index.tsx index c4c7426ec..92dbac381 100644 --- a/packages/pl-fe/src/pages/dashboard/user-index.tsx +++ b/packages/pl-fe/src/pages/dashboard/user-index.tsx @@ -13,7 +13,6 @@ const messages = defineMessages({ heading: { id: 'column.admin.users', defaultMessage: 'Users' }, }); - const UserIndexPage: React.FC = () => { const [params] = useSearchParams(); const query = params.get('q') || ''; diff --git a/packages/pl-fe/src/queries/admin/use-accounts.ts b/packages/pl-fe/src/queries/admin/use-accounts.ts index 6088ce4c5..18dab2236 100644 --- a/packages/pl-fe/src/queries/admin/use-accounts.ts +++ b/packages/pl-fe/src/queries/admin/use-accounts.ts @@ -1,6 +1,5 @@ import { InfiniteData, useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; - import { importEntities } from 'pl-fe/actions/importer'; import { useAccount } from 'pl-fe/api/hooks/accounts/use-account'; import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; @@ -14,7 +13,6 @@ import { minifyAdminAccount, minifyAdminAccountList } from '../utils/minify-list import type { AdminPerformAccountActionParams, PaginatedResponse, AdminAccount, AdminGetAccountsParams, PaginationParams, AdminAccountAction } from 'pl-api'; - const useAdminAccounts = makePaginatedResponseQuery( (params: Omit) => ['admin', 'accountLists', params], (client, [params]) => client.admin.accounts.getAccounts(params).then(minifyAdminAccountList),