From e2f47b539918c71260cea36bb2cd460380c2abce Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Thu, 30 Jan 2025 22:12:03 -0600 Subject: [PATCH 01/14] fix(finance): correct MMC amount in transfer message - Updated `finance-quick-transfer-modal.tsx` to use `value` as a fallback if `amount` is not greater than 0. - Ensures accurate MMC amount is displayed in the transfer message. --- .../finance/components/finance-quick-transfer-modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sections/finance/components/finance-quick-transfer-modal.tsx b/src/sections/finance/components/finance-quick-transfer-modal.tsx index e529b6a8..db135a27 100644 --- a/src/sections/finance/components/finance-quick-transfer-modal.tsx +++ b/src/sections/finance/components/finance-quick-transfer-modal.tsx @@ -124,7 +124,7 @@ function FinanceQuickTransferModal({ avatar: (contactInfo?.metadata?.picture as any)?.optimized?.uri ?? '', }, { - rawDescription: `${sessionData?.profile?.metadata?.displayName ?? address} sent you ${amount} MMC`, + rawDescription: `${sessionData?.profile?.metadata?.displayName ?? address} sent you ${amount > 0? amount : value} MMC`, message, } ); From c0f63af3cdd3080bed496bd0d052972f7d33b8ac Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Thu, 30 Jan 2025 22:12:34 -0600 Subject: [PATCH 02/14] refactor(user-profile): enhance ProfileTransfer functionality - **`profile-header.tsx`**: Removed direct usage of `ProfileTransfer` and its transfer button for other user profiles. - **`profile-transfer.tsx`**: Introduced tooltip behavior and additional UI improvements for the transfer button. Enhanced interactivity with popovers and streamlined styling. - **`profile-toolbar.tsx`**: Re-integrated `ProfileTransfer` component for authenticated sessions in the updated toolbar context. These changes improve the usability and accessibility of profile transfer actions while refining the user interface and overall experience. --- src/sections/user/profile-header.tsx | 7 +-- src/sections/user/profile-toolbar.tsx | 9 ++++ src/sections/user/profile-transfer.tsx | 73 ++++++++++++++++++++------ 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/sections/user/profile-header.tsx b/src/sections/user/profile-header.tsx index 5eb25957..daa018bf 100644 --- a/src/sections/user/profile-header.tsx +++ b/src/sections/user/profile-header.tsx @@ -31,7 +31,6 @@ import ProfileJoin from "@src/sections/user/profile-join.tsx"; import ProfileUserInfo from "@src/sections/user/profile-user-info.tsx"; import ProfileWrapper from './profile-wrapper'; import ProfileToolbar from "@src/sections/user/profile-toolbar.tsx"; -import ProfileTransfer from "@src/sections/user/profile-transfer.tsx"; // ---------------------------------------------------------------------- export interface ProfileHeaderProps { @@ -127,11 +126,7 @@ const ProfileHeader = ({ {profile?.id !== sessionData?.profile?.id && ( )} - { - sessionData?.authenticated && profile?.id !== sessionData?.profile?.id && ( - - ) - } + diff --git a/src/sections/user/profile-toolbar.tsx b/src/sections/user/profile-toolbar.tsx index fcb97a18..43cbbf97 100644 --- a/src/sections/user/profile-toolbar.tsx +++ b/src/sections/user/profile-toolbar.tsx @@ -7,6 +7,7 @@ import {FC} from "react"; import {Profile} from "@lens-protocol/api-bindings"; import {useTheme} from "@mui/material/styles"; import {useSelector} from "react-redux"; +import ProfileTransfer from "@src/sections/user/profile-transfer.tsx"; interface ProfileToolbarProps { profile: Profile; @@ -60,6 +61,14 @@ const ProfileToolbar: FC = ({profile, profileImage}) => { {sessionData?.profile && profile?.id === sessionData?.profile?.id && ( )} + + { + sessionData?.authenticated && profile?.id !== sessionData?.profile?.id && ( + + ) + } + + ) diff --git a/src/sections/user/profile-transfer.tsx b/src/sections/user/profile-transfer.tsx index 97e23f72..8cd8bcb4 100644 --- a/src/sections/user/profile-transfer.tsx +++ b/src/sections/user/profile-transfer.tsx @@ -1,31 +1,51 @@ -import {Profile} from "@lens-protocol/api-bindings"; -import {FC} from "react"; -import FinanceQuickTransferModal from "@src/sections/finance/components/finance-quick-transfer-modal.tsx"; -import LoadingButton from "@mui/lab/LoadingButton"; -import {useBoolean} from "@src/hooks/use-boolean.ts"; +import { Profile } from '@lens-protocol/api-bindings'; +import { FC, useCallback, useRef, useState } from 'react'; +import FinanceQuickTransferModal from '@src/sections/finance/components/finance-quick-transfer-modal.tsx'; +import LoadingButton from '@mui/lab/LoadingButton'; +import { useBoolean } from '@src/hooks/use-boolean.ts'; +import Iconify from '@src/components/iconify'; +import Typography from '@mui/material/Typography'; +import Popover from '@mui/material/Popover'; interface ProfileTransferProps { profile: Profile; } -const ProfileTransfer: FC = ({profile}) => { +const ProfileTransfer: FC = ({ profile }) => { + const [openTooltipSend, setOpenTooltipSend] = useState(false); + const navRefSend = useRef(null); const confirm = useBoolean(); const handleOpen = () => { confirm.onTrue(); - } + }; const handleTransferFinish = () => { confirm.onFalse(); - } + }; + + const handleOpenSend = useCallback(() => { + setOpenTooltipSend(true); + }, []); + + const handleCloseSend = useCallback(() => { + setOpenTooltipSend(false); + }, []); return ( <> - - Send + + = ({profile}) => { onFinish={handleTransferFinish} contactInfo={profile} /> + + + Send + - ) -} + ); +}; export default ProfileTransfer; From 4d14245034dae0731258e7beafb8edf83a85ca89 Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Thu, 30 Jan 2025 22:14:53 -0600 Subject: [PATCH 03/14] refactor(finance): adjust profile display font size - Updated `finance-display-profile-info.tsx` to include a `fontSize` style of `1.3rem` for the profile display name. - Ensures improved readability for profile names in 'profile' mode. --- .../finance/components/finance-display-profile-info.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sections/finance/components/finance-display-profile-info.tsx b/src/sections/finance/components/finance-display-profile-info.tsx index 2f802c68..5801c957 100644 --- a/src/sections/finance/components/finance-display-profile-info.tsx +++ b/src/sections/finance/components/finance-display-profile-info.tsx @@ -37,7 +37,7 @@ const FinanceDisplayProfileInfo: FC = ({initialList, ca { mode === 'profile' ? - ( + ( {selectedProfile?.metadata?.displayName ?? 'No profile selected'} ) : null } From 7e37fbc583d1327d81e392e4cffb8ae7083875e5 Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Thu, 30 Jan 2025 22:35:04 -0600 Subject: [PATCH 04/14] feat: add trimming utility and integrate in publication view - Introduced `trimPublicationContentExtraText` in `src/utils/text-transform.ts`. This utility trims text based on specific special characters. - Updated `publication-details-view.tsx` to utilize this trimming utility when rendering publication content with Markdown. --- .../view/publication-details-view.tsx | 3 +- src/utils/text-transform.ts | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/sections/publication/view/publication-details-view.tsx b/src/sections/publication/view/publication-details-view.tsx index df918bb7..07f5c918 100644 --- a/src/sections/publication/view/publication-details-view.tsx +++ b/src/sections/publication/view/publication-details-view.tsx @@ -33,6 +33,7 @@ import LoadingButton from '@mui/lab/LoadingButton'; import { useDispatch, useSelector } from 'react-redux'; import { openLoginModal } from '@redux/auth'; import { appId, PublicationType, usePublications } from '@lens-protocol/react-web'; +import {trimPublicationContentExtraText} from "@src/utils/text-transform.ts"; const MAX_LINES = 5; @@ -272,7 +273,7 @@ export default function PublicationDetailsView({ id }: Props) { opacity: 0.8, }} > - + {showButton && ( diff --git a/src/components/carousel/variants/carousel-mixed.tsx b/src/components/carousel/variants/carousel-mixed.tsx index 92f9756e..72c1083b 100644 --- a/src/components/carousel/variants/carousel-mixed.tsx +++ b/src/components/carousel/variants/carousel-mixed.tsx @@ -108,7 +108,6 @@ export default function CarouselMixed({ data }: Props) { genre: getMovieGenres(post).split(', '), images: { vertical: getMediaUri(getPosterCid(post)), - horizontal: getMediaUri(getPosterHorizontalCid(post)), wallpaper: getMediaUri(getWallpaperCid(post)), }, likes: post?.stats?.upvotes ?? 0, @@ -139,7 +138,6 @@ export default function CarouselMixed({ data }: Props) { genre: getMovieGenres(post).split(', '), images: { vertical: getMediaUri(getPosterCid(post)), - horizontal: getMediaUri(getPosterHorizontalCid(post)), wallpaper: getMediaUri(getWallpaperCid(post)), }, likes: post?.stats?.upvotes ?? 0, diff --git a/src/components/carousel/variants/carousel-poster-horizontal.tsx b/src/components/carousel/variants/carousel-poster-horizontal.tsx index ce5ca138..b515f87b 100644 --- a/src/components/carousel/variants/carousel-poster-horizontal.tsx +++ b/src/components/carousel/variants/carousel-poster-horizontal.tsx @@ -74,7 +74,6 @@ export default function CarouselPosterHorizontal({ data }: Props) { genre={getMovieGenres(post).split(', ')} images={{ vertical: getMediaUri(getPosterCid(post)), - horizontal: getMediaUri(getPosterHorizontalCid(post)), wallpaper: getMediaUri(getWallpaperCid(post)), }} likes={post?.stats?.upvotes ?? 0} diff --git a/src/components/poster/variants/poster-top-titles.tsx b/src/components/poster/variants/poster-top-titles.tsx index 86d44168..5c6aabec 100644 --- a/src/components/poster/variants/poster-top-titles.tsx +++ b/src/components/poster/variants/poster-top-titles.tsx @@ -79,6 +79,7 @@ const PosterTopTitles = ({ post }: { post: any }) => { width: '100%', height: '100%', opacity: 0.2, + filter: "blur(5px) !important", backgroundSize: 'cover', backgroundPosition: 'center', backgroundRepeat: 'no-repeat', diff --git a/src/layouts/_common/header-balance.tsx b/src/layouts/_common/header-balance.tsx index dbf1a63a..9f1800af 100644 --- a/src/layouts/_common/header-balance.tsx +++ b/src/layouts/_common/header-balance.tsx @@ -45,9 +45,6 @@ export default function HeaderBalance() { {formatBalanceNumber(balance)} - - MMC - ); From d94988f331cb2b6c895bbcb9d9b75115ce03b0df Mon Sep 17 00:00:00 2001 From: Geolffrey Mena Date: Sun, 2 Feb 2025 12:57:16 -0600 Subject: [PATCH 07/14] style: remove flex --- src/components/carousel/variants/carousel-top-titles.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/carousel/variants/carousel-top-titles.tsx b/src/components/carousel/variants/carousel-top-titles.tsx index 87118c5f..90e7b674 100644 --- a/src/components/carousel/variants/carousel-top-titles.tsx +++ b/src/components/carousel/variants/carousel-top-titles.tsx @@ -52,7 +52,7 @@ export default function CarouselTopTitles({ posts, category }: Props) { > {posts.map((post: any) => ( - + ))} From 70aaac3080e7cc6542ef56e60d153e9b49ca4cdb Mon Sep 17 00:00:00 2001 From: Geolffrey Mena Date: Mon, 3 Feb 2025 10:01:57 -0600 Subject: [PATCH 08/14] style: remove flex --- src/utils/finance-graphs/groupedTransactions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/finance-graphs/groupedTransactions.ts b/src/utils/finance-graphs/groupedTransactions.ts index ef906fd6..e9eaffbf 100644 --- a/src/utils/finance-graphs/groupedTransactions.ts +++ b/src/utils/finance-graphs/groupedTransactions.ts @@ -207,7 +207,7 @@ const parseTransactionTypeLabel = (type: string): string => { case 'approved': return 'Approved'; case 'collected': - return 'Paid'; + return 'Content Unlocked'; // case 'released': // return 'Released'; From 19207189548057eb73843c1669ba06853520bea7 Mon Sep 17 00:00:00 2001 From: Geolffrey Mena Date: Mon, 3 Feb 2025 10:38:35 -0600 Subject: [PATCH 09/14] fix: fullfill padding on attestations --- src/sections/user/profile-right-sidebar.tsx | 39 ++++++++++++--------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/sections/user/profile-right-sidebar.tsx b/src/sections/user/profile-right-sidebar.tsx index 9458cc07..e84b7f66 100644 --- a/src/sections/user/profile-right-sidebar.tsx +++ b/src/sections/user/profile-right-sidebar.tsx @@ -1,21 +1,22 @@ import Stack from "@mui/material/Stack"; import Typography from "@mui/material/Typography"; -import {CopyableText} from "@src/components/copyable-text"; +import { CopyableText } from "@src/components/copyable-text"; import Divider from "@mui/material/Divider"; -import {truncateAddress} from "@src/utils/wallet.ts"; -import {OpenableText} from "@src/components/openable-text"; +import { truncateAddress } from "@src/utils/wallet.ts"; +import { OpenableText } from "@src/components/openable-text"; import Box from "@mui/material/Box"; -import {randomColors} from "@src/components/poster/variants/poster-latest-content.tsx"; -import {IconRosetteDiscountCheckFilled} from "@tabler/icons-react"; -import {FC} from "react"; -import {ProfileHeaderProps} from "@src/sections/user/profile-header.tsx"; -import {styled} from "@mui/material/styles"; -import {useSelector} from "react-redux"; +import { randomColors } from "@src/components/poster/variants/poster-latest-content.tsx"; +import { IconRosetteDiscountCheckFilled } from "@tabler/icons-react"; +import { FC } from "react"; +import { ProfileHeaderProps } from "@src/sections/user/profile-header.tsx"; +import { styled } from "@mui/material/styles"; +import { useSelector } from "react-redux"; // ---------------------------------------------------------------------- +// TODO: move to envs const urlAttestationBase = 'https://polygon-amoy.easscan.org/attestation/view/'; -interface ProfileRightSidebarProps extends ProfileHeaderProps{ +interface ProfileRightSidebarProps extends ProfileHeaderProps { sidebarProps: { isAuthorized?: boolean; attestation?: string; @@ -25,10 +26,14 @@ interface ProfileRightSidebarProps extends ProfileHeaderProps{ attestationLoading: boolean; } } -const ProfileRightSidebar: FC = ({profile, sidebarProps}) => { + +const ProfileRightSidebar: FC = ({ profile, sidebarProps }) => { const sessionData = useSelector((state: any) => state.auth.session); - const {isAuthorized, authorizedLoading, accessLoading, hasAccess, attestation, attestationLoading} = sidebarProps; - const attestationAddress = `0x${BigInt(attestation ?? '').toString(16)}`; + const { isAuthorized, authorizedLoading, accessLoading, hasAccess, attestation, attestationLoading } = sidebarProps; + const hex = BigInt(attestation ?? '').toString(16) + // add padding to attestation smaller than 256 bits + const cleanedHex = hex.length < 64 ? `${'0'.repeat(64 - hex.length)}${hex}` : hex; + const attestationAddress = `0x${cleanedHex}`; return ( = ({profile, sidebarProp } const StyledBoxGradient = styled(Box)<{ color1?: string; color2?: string }>(({ - theme, - color1, - color2, - }) => { + theme, + color1, + color2, +}) => { const defaultColor1 = theme.palette.primary.main; const defaultColor2 = theme.palette.secondary.main; From 48469068040adf8ba32ceb036f7ee01077793e94 Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Mon, 3 Feb 2025 13:34:13 -0600 Subject: [PATCH 10/14] refactor(notifications): move bundler error to warnings - Removed `ERRORS.BUNDLER_UNAVAILABLE` from `src/utils/notifications/errors.ts`. - Added `WARNING.BUNDLER_UNAVAILABLE` to `src/utils/notifications/warnings.ts` with updated message. - Replaced `notifyError` with `notifyWarning` for bundler unavailability in `src/hooks/use-account-session.ts`. This transition classifies the bundler unavailability as a warning, ensuring better contextual distinction for session-related notifications. --- src/hooks/use-account-session.ts | 6 +++--- src/utils/notifications/errors.ts | 2 -- src/utils/notifications/warnings.ts | 2 ++ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hooks/use-account-session.ts b/src/hooks/use-account-session.ts index bf073540..48baf021 100644 --- a/src/hooks/use-account-session.ts +++ b/src/hooks/use-account-session.ts @@ -9,12 +9,12 @@ import { setAuthLoading, setSession, setBalance } from '@redux/auth'; import { useSession, useLogout } from '@lens-protocol/react-web'; // NOTIFICATIONS IMPORTS -import { ERRORS } from '@notifications/errors'; -import { notifyError } from '@notifications/internal-notifications'; +import { notifyWarning } from '@notifications/internal-notifications'; // WEB3AUTH IMPORTS import { useWeb3Auth } from '@src/hooks/use-web3-auth'; import { useWeb3Session } from '@src/hooks/use-web3-session'; +import {WARNING} from "@notifications/warnings.ts"; // ---------------------------------------------------------------------- @@ -51,7 +51,7 @@ export const useAccountSession = (): UseAccountSessionHook => { dispatch(setBalance({ balance: 0 })); dispatch(setSession({ session: { ...data, authenticated: false } })); dispatch(setAuthLoading({ isSessionLoading: false })); - if (!silent) notifyError(ERRORS.BUNDLER_UNAVAILABLE); + if (!silent) notifyWarning(WARNING.BUNDLER_UNAVAILABLE); }, [web3Auth.status]); // Automatic checks on mount + interval diff --git a/src/utils/notifications/errors.ts b/src/utils/notifications/errors.ts index 5ee1f121..f3d1438d 100644 --- a/src/utils/notifications/errors.ts +++ b/src/utils/notifications/errors.ts @@ -3,7 +3,6 @@ */ export enum ERRORS { NOT_LOGGED_IN = 'NOT_LOGGED_IN', - BUNDLER_UNAVAILABLE = 'BUNDLER_UNAVAILABLE', UNKNOWN_ERROR = 'UNKNOWN_ERROR', METAMASK_CONNECTING_ERROR = 'METAMASK_CONNECTING_ERROR', WITHDRAW_FAILED_ERROR = 'WITHDRAW_FAILED_ERROR', @@ -98,7 +97,6 @@ export const ERROR_MESSAGES: Record = { // Withdraw error [ERRORS.FIRST_LOGIN_ERROR]: 'You must login first to withdraw funds.', - [ERRORS.BUNDLER_UNAVAILABLE]: 'Your session is expired. Please re-login to continue.', // Deposit error [ERRORS.DEPOSIT_FAILED_ERROR]: 'Please login to deposit funds.', diff --git a/src/utils/notifications/warnings.ts b/src/utils/notifications/warnings.ts index 3d0cb68e..f69dbe41 100644 --- a/src/utils/notifications/warnings.ts +++ b/src/utils/notifications/warnings.ts @@ -7,6 +7,7 @@ export enum WARNING { INVALID_DEPOSIT_AMOUNT = 'INVALID_DEPOSIT_AMOUNT', INVALID_WITHDRAW_AMOUNT = 'INVALID_WITHDRAW_AMOUNT', INVALID_WALLET_ADDRESS = 'INVALID_WALLET_ADDRESS', + BUNDLER_UNAVAILABLE = 'BUNDLER_UNAVAILABLE', } /** @@ -18,4 +19,5 @@ export const WARNING_MESSAGES: Record = { [WARNING.INVALID_DEPOSIT_AMOUNT]: 'Invalid deposit amount.', [WARNING.INVALID_WITHDRAW_AMOUNT]: 'Invalid withdraw amount.', [WARNING.INVALID_WALLET_ADDRESS]: 'Invalid wallet address.', + [WARNING.BUNDLER_UNAVAILABLE]: 'Session expired. Login again.', }; From 1963c8c79f6317d63f2ef97a6a387526355b80b0 Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Mon, 3 Feb 2025 19:41:35 -0600 Subject: [PATCH 11/14] refactor(utils): enhance text cleaning and email detection - Refactored `trimPublicationContentExtraText` to modularize logic: - Extracted `removeSpecialChars` function for removing predefined patterns. - Added `detectEmail` and `removeEmail` functions to handle email detection and removal. - Updated logic to ensure processed text ends with a period. - Improved readability and maintainability by splitting responsibilities. --- src/utils/text-transform.ts | 105 ++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 23 deletions(-) diff --git a/src/utils/text-transform.ts b/src/utils/text-transform.ts index 7cbd1c69..abdda77e 100644 --- a/src/utils/text-transform.ts +++ b/src/utils/text-transform.ts @@ -10,34 +10,93 @@ export const pascalToUpperSnake = (str: string): string => { .replace(/^_/, ''); // Removes the initial underscore if it exists }; + +/** + * An array of strings containing various special character patterns and names. + * The strings in this array include names or identifiers preceded by + * special characters such as dashes, question marks, or periods. + * Some entries also contain only special characters or brace-like structures. + */ +const specialChars = [ + '—Huggo', + '?—Nick Riganas', + '.—Rhino', + '—Eric Johnson', + '—Jwelch5742', + '—yusufpiskin', + '—Maths Jesperson', + '—Mark Logan', + '—Snow Leopard', + '—Claudio Carvalho, Rio de Janeiro, Brazil', + '—Johnny-the-Film-Sentinel-2187', + '—grantss', + '—Ed Stephan', + '—filmfactsman', + '—Col Needham', + '—Tony Fontana', + '—garykmcd', + '—', + '?—', + '.—', + '{}', +]; + +/** + * Removes special characters from the given text string and returns the cleaned string. + * + * @param {string} text - The input string from which special characters will be removed. + * @return {string} - The resulting string after special characters are removed. + */ +function removeSpecialChars(text: string): string { + // Loop through the special characters and replace them with spaces + for (const char of specialChars) { + text = text.replace(char, '').trim(); + } + return text; +} + +/** + * Detects whether the given text contains a valid email address pattern. + * + * @param {string} text - The string to be checked for an email address. + * @return {boolean} Returns `true` if the text contains a valid email address, otherwise `false`. + */ +function detectEmail(text: string): boolean { + const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/; + return emailRegex.test(text); +} + /** - * Trims additional content from a publication string based on specific special characters. + * Removes an email address from the provided text string, if present. * - * This function searches the input string for specific special characters - * (e.g., ".—", "?—"). If one of these characters is found, the function - * returns the portion of the string that appears before the special character, - * appending a period (".") at the end. If none of the special characters are - * found, the original string is returned unchanged. + * @param {string} text - The input string potentially containing an email address. + * @return {string} The modified string with the email address removed and trimmed of extra spaces. + */ +function removeEmail(text: string): string { + const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/; + return text.replace(emailRegex, '').trim(); // Remove the email and trim any extra spaces +} + +/** + * Processes and trims extra content from a publication text, including special characters, + * email addresses, and patterns at the end of the text. * - * @param {string} text - The input string to be trimmed or returned as-is. - * @returns {string} - The trimmed string if a special character is found; otherwise, the original string. + * @param {string} text - The input string representing the publication content to be processed. + * @returns {string} The processed and cleaned text after applying trimming rules. */ export const trimPublicationContentExtraText = (text: string): string => { - // Define the special characters to look for - const specialChars = ['.—', '?—']; - - // Iterate over each special character - for (const specialChar of specialChars) { - // Find the index of the special character in the input string - const index = text.indexOf(specialChar); - - // If the special character is found - if (index !== -1) { - // Return the text before the special character and add a period at the end - return `${text.substring(0, index)}.` - } + const hasEmail = detectEmail(text); + + if (hasEmail) { + text = removeEmail(text); } - // If none of the special characters are found, return the original text - return text; + let cleanedText = removeSpecialChars(text); + + // Verify if the last character is a period, if not, add one + if (cleanedText.charAt(cleanedText.length - 1) !== '.') { + cleanedText += '.'; + } + + return `${cleanedText}`; }; From 77406f2692d179e093417d0f907e27a5fc007cb8 Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Mon, 3 Feb 2025 19:54:19 -0600 Subject: [PATCH 12/14] refactor(utils): centralize email regex for reuse - Added a detailed `emailRegex` with extended documentation in `text-transform.ts` to centralize email validation logic. - Updated `detectEmail` and `removeEmail` functions to reuse the new `emailRegex` constant, improving maintainability and consistency. --- src/utils/text-transform.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/utils/text-transform.ts b/src/utils/text-transform.ts index abdda77e..7cde1119 100644 --- a/src/utils/text-transform.ts +++ b/src/utils/text-transform.ts @@ -41,6 +41,23 @@ const specialChars = [ '{}', ]; + +/** + * A regular expression pattern used for matching and validating email addresses. + * + * This pattern supports common email formats, where: + * - The local part can contain alphanumeric characters, dots, underscores, + * percent signs, plus signs, and hyphens. + * - The domain part is structured as one or more labels separated by dots, + * with each label containing alphanumeric characters or hyphens. + * - The top-level domain must be at least two characters long and consist + * only of alphabetic characters. + * + * Flags: + * - The "g" flag enables global matching, allowing multiple occurrences + * of email addresses to be matched in a single string. + */ +const emailRegex = /[a-zA-Z0-9][a-zA-Z0-9._%+-]*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}/g; /** * Removes special characters from the given text string and returns the cleaned string. * @@ -62,7 +79,6 @@ function removeSpecialChars(text: string): string { * @return {boolean} Returns `true` if the text contains a valid email address, otherwise `false`. */ function detectEmail(text: string): boolean { - const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/; return emailRegex.test(text); } @@ -73,8 +89,7 @@ function detectEmail(text: string): boolean { * @return {string} The modified string with the email address removed and trimmed of extra spaces. */ function removeEmail(text: string): string { - const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/; - return text.replace(emailRegex, '').trim(); // Remove the email and trim any extra spaces + return text.replace(emailRegex, '').trim(); } /** From df33aff15b4729f7eca71a924b45d26909701ee9 Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Mon, 3 Feb 2025 20:00:57 -0600 Subject: [PATCH 13/14] fix(utils): improve email regex to avoid partial matches - Updated `emailRegex` in `src/utils/text-transform.ts` to include word boundary markers (`\b`) at both ends. - This change ensures more accurate email matching and prevents partial matches in strings. --- src/utils/text-transform.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/text-transform.ts b/src/utils/text-transform.ts index 7cde1119..b9d67d1c 100644 --- a/src/utils/text-transform.ts +++ b/src/utils/text-transform.ts @@ -57,7 +57,9 @@ const specialChars = [ * - The "g" flag enables global matching, allowing multiple occurrences * of email addresses to be matched in a single string. */ -const emailRegex = /[a-zA-Z0-9][a-zA-Z0-9._%+-]*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}/g; +const emailRegex = /\b[a-zA-Z0-9][a-zA-Z0-9._%+-]*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}\b/g; + + /** * Removes special characters from the given text string and returns the cleaned string. * From 2872a0200958b85ad52e9e414fbe4ae0602e3293 Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Mon, 3 Feb 2025 20:03:39 -0600 Subject: [PATCH 14/14] refactor(utils): simplify period-check logic in text transform - Updated `text-transform.ts` to replace `charAt` and length check with `endsWith` for verifying the presence of a period. - This improves code readability and leverages a more intuitive string method. --- src/utils/text-transform.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/text-transform.ts b/src/utils/text-transform.ts index b9d67d1c..6e2a6109 100644 --- a/src/utils/text-transform.ts +++ b/src/utils/text-transform.ts @@ -111,7 +111,7 @@ export const trimPublicationContentExtraText = (text: string): string => { let cleanedText = removeSpecialChars(text); // Verify if the last character is a period, if not, add one - if (cleanedText.charAt(cleanedText.length - 1) !== '.') { + if (!cleanedText.endsWith('.')) { cleanedText += '.'; }