From 9012a65963a48e4f85c7a64eb1359a58efa31993 Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Tue, 24 Sep 2024 17:19:15 +0530 Subject: [PATCH 01/11] notif --- src/App.tsx | 6 +- src/blocks/notification/Notification.tsx | 83 +--------------- src/blocks/notification/Notification.types.ts | 10 +- src/common/components/NotificationOverlay.tsx | 97 +++++++++++++++++++ src/common/components/NotificationToast.tsx | 42 ++++++++ src/common/components/index.ts | 2 + src/common/hooks/index.ts | 1 + src/common/hooks/useStream.tsx | 77 +++++++++++++++ src/contexts/AppContext.tsx | 81 +++++++++------- src/hooks/useStream.ts | 10 +- 10 files changed, 280 insertions(+), 129 deletions(-) create mode 100644 src/common/components/NotificationOverlay.tsx create mode 100644 src/common/components/NotificationToast.tsx create mode 100644 src/common/hooks/useStream.tsx diff --git a/src/App.tsx b/src/App.tsx index 07e5a4bf84..d170a09927 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -53,6 +53,8 @@ import SpaceContextProvider from 'contexts/SpaceContext'; import { SpaceWidgetSection } from 'sections/space/SpaceWidgetSection'; import { blocksColors, getBlocksCSSVariables } from 'blocks'; import APP_PATHS from 'config/AppPaths'; +import { CONSTANTS } from '@pushprotocol/restapi'; +import { useStream } from 'common'; dotenv.config(); @@ -336,6 +338,8 @@ export default function App() { location?.pathname.includes('/snap') || location?.pathname.includes(APP_PATHS.DiscordVerification); + useStream(); + return ( {/* {(!isActive || !allowedChain) && ( @@ -356,7 +360,7 @@ export default function App() { getTextVariantStyles('h5-semibold', 'components-in-app-notification-text-default')} -`; - -const NotificationDescription = styled.span` - ${() => getTextVariantStyles('bes-regular', 'components-in-app-notification-text-secondary')} - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 3; - line-clamp: 3; - -webkit-box-orient: vertical; -`; - -const IconContainer = styled.div` - padding: var(--spacing-sm) var(--spacing-xs); - border-radius: var(--radius-xxs) var(--radius-none) var(--radius-none) var(--radius-xxs); - background: radial-gradient(79.55% 79.55% at 50% 50%, #344efd 0%, #171717 100%); -`; - -const CloseButton = styled.div` - background-color: var(--surface-transparent); - cursor: pointer; - color: var(--components-in-app-notification-icon-default); - padding: var(--spacing-none); - position: absolute; - right: var(--spacing-xxs); - top: var(--spacing-xxs); -`; - -const Notification: FC = ({ onClose, title, description, image, onClick }) => { +const Notification: FC = ({ overlay, onClick }) => { const handleNotificationClick = () => onClick?.(); - const handleNotificationClose = () => { - onClose?.(); - notification.hide(); - }; - - return ( - - {image} - { - e.stopPropagation(); - handleNotificationClose(); - }} - > - - - - {title} - {description} - - - ); + return
{overlay}
; }; // Store the toastId(s) in an array to manage multiple notifications diff --git a/src/blocks/notification/Notification.types.ts b/src/blocks/notification/Notification.types.ts index 9121f9b3ea..edae2fc5c7 100644 --- a/src/blocks/notification/Notification.types.ts +++ b/src/blocks/notification/Notification.types.ts @@ -1,16 +1,10 @@ import { ReactNode } from 'react'; export type NotificationProps = { - /* Svg React component to be passed as the image. */ - image: ReactNode; - /* Title of the notification */ - title: string; - /* Description of the notification */ - description: string; + /* Custom React component to be passed as the image. */ + overlay: ReactNode; /* Optional onClick event for the notification */ onClick?: () => void; - /* Optional onClose action for the notification */ - onClose?: () => void; /* Position of the notification */ position?: 'bottom-right' | 'bottom-left'; /* Optional duration of the notification component */ diff --git a/src/common/components/NotificationOverlay.tsx b/src/common/components/NotificationOverlay.tsx new file mode 100644 index 0000000000..c1fa627d24 --- /dev/null +++ b/src/common/components/NotificationOverlay.tsx @@ -0,0 +1,97 @@ +import { FC, ReactNode } from 'react'; +import styled from 'styled-components'; +import { Cross } from 'blocks'; +import { getTextVariantStyles } from 'blocks/Blocks.utils'; +import { Box } from 'blocks'; +import { notification } from 'blocks'; + +const NotificationContainer = styled.div` + position: relative; + background-color: var(--components-in-app-notification-background-default); + border-radius: var(--radius-xxs); + box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: row; + align-items: stretch; + max-height: 111px; + min-width: 397px; + max-width: 100%; + cursor: pointer; + box-sizing: border-box; + border: var(--border-sm) solid var(--components-in-app-notification-stroke-bg); +`; +const TextContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + padding: var(--spacing-sm); + flex: 1; + box-sizing: border-box; +`; + +const NotificationTitle = styled.span` + ${() => getTextVariantStyles('h5-semibold', 'components-in-app-notification-text-default')} +`; + +const NotificationDescription = styled.span` + ${() => getTextVariantStyles('bes-regular', 'components-in-app-notification-text-secondary')} + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 3; + line-clamp: 3; + -webkit-box-orient: vertical; +`; + +const IconContainer = styled.div` + padding: var(--spacing-sm) var(--spacing-xs); + border-radius: var(--radius-xxs) var(--radius-none) var(--radius-none) var(--radius-xxs); + background: radial-gradient(79.55% 79.55% at 50% 50%, #344efd 0%, #171717 100%); +`; + +const CloseButton = styled.div` + background-color: var(--surface-transparent); + cursor: pointer; + color: var(--components-in-app-notification-icon-default); + padding: var(--spacing-none); + position: absolute; + right: var(--spacing-xxs); + top: var(--spacing-xxs); +`; + +type NotificationOverlayProps = { + image: ReactNode; + /* Title of the notification */ + title: string; + /* Description of the notification */ + description: string; + /* Optional onClose action for the notification */ + onClose?: () => void; +}; + +const NotificationOverlay: FC = ({ onClose, title, description, image }) => { + const handleNotificationClose = () => { + onClose?.(); + notification.hide(); + }; + return ( + + {image} + { + e.stopPropagation(); + handleNotificationClose(); + }} + > + + + + {title} + {description} + + + ); +}; + +export { NotificationOverlay }; diff --git a/src/common/components/NotificationToast.tsx b/src/common/components/NotificationToast.tsx new file mode 100644 index 0000000000..e2cc9971cd --- /dev/null +++ b/src/common/components/NotificationToast.tsx @@ -0,0 +1,42 @@ +import { NotificationEvent } from '@pushprotocol/restapi'; +import { NotificationItem, chainNameType } from '@pushprotocol/uiweb'; +import { Box, Text } from 'blocks'; +import { useBlocksTheme } from 'blocks/Blocks.hooks'; +import { FC } from 'react'; +import { css, useTheme } from 'styled-components'; + +type NotificationToastProps = { + notification: NotificationEvent | null; +}; + +const NotificationToast: FC = ({ notification }) => { + const payload = notification?.message?.payload; + const { mode } = useBlocksTheme(); + return ( + + {notification && ( + + )} + + ); +}; + +export { NotificationToast }; diff --git a/src/common/components/index.ts b/src/common/components/index.ts index 2e2904520a..4814569fec 100644 --- a/src/common/components/index.ts +++ b/src/common/components/index.ts @@ -5,3 +5,5 @@ export * from './UnsubscribeChannelDropdown'; export * from './ModalHeader'; export * from './StakingVariant'; export * from './TokenFaucet'; +export * from './NotificationOverlay'; +export * from './NotificationToast'; diff --git a/src/common/hooks/index.ts b/src/common/hooks/index.ts index d872d65587..1ee603cd54 100644 --- a/src/common/hooks/index.ts +++ b/src/common/hooks/index.ts @@ -1,3 +1,4 @@ export { useIsVisible } from './useIsVisible'; export { usePushStakingStats } from './usePushStakingStats'; export { useDisclosure } from './useDisclosure'; +export { useStream } from './useStream'; diff --git a/src/common/hooks/useStream.tsx b/src/common/hooks/useStream.tsx new file mode 100644 index 0000000000..20ca77e6bc --- /dev/null +++ b/src/common/hooks/useStream.tsx @@ -0,0 +1,77 @@ +import { CONSTANTS, NotificationEvent } from '@pushprotocol/restapi'; +import { useEffect, useState } from 'react'; +import { notification } from 'blocks'; +import { useSelector } from 'react-redux'; +import { NotificationOverlay, NotificationToast } from 'common'; + +export const useStream = () => { + const [isStreamConnected, setIsStreamConnected] = useState(false); + const [notificationFeed, setNotificationFeed] = useState(null); + const { userPushSDKInstance } = useSelector((state: any) => { + return state.user; + }); + const attachListeners = async () => { + userPushSDKInstance?.stream?.on(CONSTANTS.STREAM.CONNECT, (err: Error) => { + console.debug( + 'src::common::hooks::useStream::attachListeners::CONNECT::', + userPushSDKInstance?.uid, + userPushSDKInstance?.stream?.uid, + userPushSDKInstance?.stream + ); + setIsStreamConnected(true); + }); + + userPushSDKInstance?.stream?.on(CONSTANTS.STREAM.DISCONNECT, (err: Error) => { + console.debug( + 'src::common::hooks::useStream::attachListeners::DISCONNECT::', + userPushSDKInstance?.uid, + userPushSDKInstance?.stream?.uid, + userPushSDKInstance?.stream + ); + setIsStreamConnected(false); + }); + userPushSDKInstance?.stream?.on(CONSTANTS.STREAM.NOTIF, (data: NotificationEvent) => { + console.debug( + 'src::common::hooks::useStream::attachListeners::NOTIF::', + userPushSDKInstance, + userPushSDKInstance?.uid, + userPushSDKInstance?.stream?.uid, + userPushSDKInstance?.stream, + data + ); + //confirm if only needed for inbox and discuss the working in older file for video + // if (data.event === NotificationEventType.INBOX) + //shift to app.tsx maybe + + notification.show({ + overlay: , + }); + setNotificationFeed(data); + }); + }; + // const removeListeners = () => { + // userPushSDKInstance?.stream?.off(CONSTANTS.STREAM.CONNECT); + // userPushSDKInstance?.stream?.off(CONSTANTS.STREAM.DISCONNECT); + // userPushSDKInstance?.stream?.off(CONSTANTS.STREAM.NOTIF); + // }; + useEffect(() => { + (async () => { + if (userPushSDKInstance && userPushSDKInstance?.stream && userPushSDKInstance?.readmode()) + await attachListeners(); + })(); + + // Cleanup listener on unmount + return () => { + // (async()=>{ + // await userPushSDKInstance.reinit([ + // CONSTANTS.STREAM.NOTIF, // Listen for notification events + // CONSTANTS.STREAM.CONNECT, // Listen for connection events + // CONSTANTS.STREAM.DISCONNECT, // Listen for disconnection events + // ]); + // })(); + // removeListeners(); + }; + }, [userPushSDKInstance]); + + return { isStreamConnected, notificationFeed }; // Return the event data so components can use it +}; diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx index 534e2c72fd..a3464ec467 100644 --- a/src/contexts/AppContext.tsx +++ b/src/contexts/AppContext.tsx @@ -23,7 +23,7 @@ import { LocalPeerType, Web3NameListType, handleConnectWalletAndEnableProfileProps, - onboardingProgressI + onboardingProgressI, } from 'types/context'; import { GlobalContext } from './GlobalContext'; @@ -46,14 +46,14 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { const [connectedUser, setConnectedUser] = useState(); const [localPeer, setLocalPeer] = useState({ peer: '', - peerID: '' + peerID: '', }); const [connectedPeerID, setConnectedPeerID] = useState({ - peerID: '' + peerID: '', }); const [blockedLoading, setBlockedLoading] = useState({ enabled: false, - title: null + title: null, }); const [displayQR, setDisplayQR] = useState(false); @@ -66,7 +66,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { const { isModalOpen: isMetamaskPushSnapOpen, showModal: showMetamaskPushSnap, - ModalComponent: MetamaskPushSnapModalComponent + ModalComponent: MetamaskPushSnapModalComponent, } = useModalBlur(); const dispatch = useDispatch(); @@ -77,7 +77,12 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { toastMessage: toastMessage || 'Please connect your wallet to continue', toastTitle: 'Connect Wallet', toastType: 'ERROR', - getToastIcon: (size) => + getToastIcon: (size) => ( + + ), }); } @@ -96,7 +101,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { remember = false, showToast = false, toastMessage = undefined, - wallet + wallet, }: handleConnectWalletAndEnableProfileProps) => { shouldInitializeRef.current = false; // Directly modify the ref to disable useEffect execution @@ -105,7 +110,12 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { toastMessage: toastMessage || 'Please connect your wallet to continue', toastTitle: 'Connect Wallet', toastType: 'ERROR', - getToastIcon: (size) => + getToastIcon: (size) => ( + + ), }); } @@ -193,7 +203,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { userInstance = await PushAPI.initialize({ account: readOnlyWallet, env: appConfig.appEnv, - alpha: { feature: ['SCALABILITY_V2'] } + alpha: { feature: ['SCALABILITY_V2'] }, }); console.debug('src::contexts::AppContext::initializePushSdkGuestMode::User Instance Initialized', userInstance); @@ -221,9 +231,10 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { decryptedPGPPrivateKey: null, env: appConfig.appEnv, account: account, - alpha: { feature: ['SCALABILITY_V2'] } + alpha: { feature: ['SCALABILITY_V2'] }, }); - + // if (!(userPushSDKInstance?.stream && userPushSDKInstance?.stream?.disconnected)) + await setupStream(userInstance); console.debug('src::contexts::AppContext::initializePushSdkReadMode::User Instance Initialized', userInstance); dispatch(setUserPushSDKInstance(userInstance)); return userInstance; @@ -255,14 +266,14 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { env: appConfig.appEnv, account: currentAddress, progressHook: onboardingProgressReformatter, - alpha: { feature: ['SCALABILITY_V2'] } + alpha: { feature: ['SCALABILITY_V2'] }, }); } else { userInstance = await PushAPI.initialize(librarySigner!, { env: appConfig.appEnv, account: currentAddress, progressHook: onboardingProgressReformatter, - alpha: { feature: ['SCALABILITY_V2'] } + alpha: { feature: ['SCALABILITY_V2'] }, }); } @@ -273,7 +284,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { title: 'Push Profile Setup Complete', spinnerType: LOADER_SPINNER_TYPE.COMPLETED, progressEnabled: false, - progress: 100 + progress: 100, }); } dispatch(setUserPushSDKInstance(userInstance)); @@ -290,21 +301,19 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { const setupStream = async (userInstance: any) => { // Connect stream as well - const stream = await userInstance.initStream([ - CONSTANTS.STREAM.CONNECT, - CONSTANTS.STREAM.DISCONNECT, - CONSTANTS.STREAM.CHAT, - CONSTANTS.STREAM.CHAT_OPS, - CONSTANTS.STREAM.NOTIF, - CONSTANTS.STREAM.VIDEO - ]); - - stream.on(CONSTANTS.STREAM.CONNECT, () => { - console.debug('src::contexts::AppContext::setupStream::CONNECT::'); - }); - - await stream.connect(); - console.debug('src::contexts::AppContext::setupStream::User Intance Stream Connected', userInstance); + if (!userInstance.stream) { + const stream = await userInstance.initStream([ + CONSTANTS.STREAM.CONNECT, + CONSTANTS.STREAM.DISCONNECT, + CONSTANTS.STREAM.CHAT, + CONSTANTS.STREAM.CHAT_OPS, + CONSTANTS.STREAM.NOTIF, + CONSTANTS.STREAM.VIDEO, + ]); + + await stream.connect(); + console.debug('src::contexts::AppContext::setupStream::User Intance Stream Connected', userInstance); + } }; // To reformat errors @@ -314,7 +323,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { hookInfo: progressHook, spinnerType: LOADER_SPINNER_TYPE.PROCESSING, progress: 0, - errorMessage: '' + errorMessage: '', }; if (progressHook) { @@ -417,7 +426,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { progressEnabled: onboardingProgress.progress ? true : false, progress: onboardingProgress.progress, progressNotice: onboardingProgress.hookInfo.progressInfo, - errorMessage: onboardingProgress.errorMessage + errorMessage: onboardingProgress.errorMessage, }); }; @@ -457,7 +466,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { sigType: '', signature: '', linkedListHash: '', - privateKey: '' + privateKey: '', }; } @@ -488,18 +497,18 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { account: account, env: appConfig.appEnv, signer: signer, - progressHook: onboardingProgressReformatter + progressHook: onboardingProgressReformatter, }); const createdUser = await PushAPI.user.get({ account: account, - env: appConfig.appEnv + env: appConfig.appEnv, }); const pvtkey = await PushAPI.chat.decryptPGPKey({ encryptedPGPPrivateKey: createdUser.encryptedPrivateKey, signer: signer, env: appConfig.appEnv, toUpgrade: true, - progressHook: onboardingProgressReformatter + progressHook: onboardingProgressReformatter, }); const createdConnectedUser = { ...createdUser, privateKey: pvtkey }; @@ -544,7 +553,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { removePGPKeyForUser, storePGPKeyForUser, isUserProfileUnlocked, - setUserProfileUnlocked + setUserProfileUnlocked, }} > {children} diff --git a/src/hooks/useStream.ts b/src/hooks/useStream.ts index a061d847ee..60b8a503d9 100644 --- a/src/hooks/useStream.ts +++ b/src/hooks/useStream.ts @@ -73,9 +73,13 @@ const useSDKStream = () => { useEffect(() => { if (userPushSDKInstance?.signer) { (async () => { - const stream = await userPushSDKInstance.initStream([STREAM.CONNECT, STREAM.DISCONNECT, STREAM.NOTIF]); - stream.connect(); - setStream(stream); + if (userPushSDKInstance?.stream && userPushSDKInstance?.stream?.disconnected) { + setStream(userPushSDKInstance?.stream); + } else { + const stream = await userPushSDKInstance.initStream([STREAM.CONNECT, STREAM.DISCONNECT, STREAM.NOTIF]); + stream.connect(); + setStream(stream); + } })(); } }, [userPushSDKInstance]); From ac3c3e0a8aa646afd9ad9220a4a548c1356eb05a Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Fri, 27 Sep 2024 13:03:37 +0530 Subject: [PATCH 02/11] added notification toast --- package.json | 2 +- src/common/Common.utils.tsx | 12 +++++++++ src/common/components/NotificationToast.tsx | 10 ++----- src/common/hooks/useStream.tsx | 29 ++++----------------- yarn.lock | 10 +++---- 5 files changed, 25 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index daeee90645..3e3d4597eb 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@mui/material": "^5.5.0", "@pushprotocol/restapi": "1.7.25", "@pushprotocol/socket": "0.5.3", - "@pushprotocol/uiweb": "1.4.3", + "@pushprotocol/uiweb": "2.0.0-exp.1", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-switch": "^1.1.0", diff --git a/src/common/Common.utils.tsx b/src/common/Common.utils.tsx index 917c02a7b7..9d535ee387 100644 --- a/src/common/Common.utils.tsx +++ b/src/common/Common.utils.tsx @@ -1,5 +1,8 @@ +import { NotificationEvent } from '@pushprotocol/restapi'; import { LOGO_ALIAS_CHAIN } from './Common.constants'; import { networkName } from 'helpers/UtilityHelper'; +import { NotificationToast } from './components'; +import { notification } from 'blocks'; export const getSelectChains = (chainIdList: Array) => { return chainIdList?.map((key: number) => { @@ -11,3 +14,12 @@ export const getSelectChains = (chainIdList: Array) => { }; }); }; + +export const handleNotificationToast = (data: NotificationEvent) => { + notification.show({ + overlay: , + }); + setTimeout(() => { + notification.hide(); + }, 10000); +}; diff --git a/src/common/components/NotificationToast.tsx b/src/common/components/NotificationToast.tsx index e2cc9971cd..e5ee1f146e 100644 --- a/src/common/components/NotificationToast.tsx +++ b/src/common/components/NotificationToast.tsx @@ -1,9 +1,8 @@ import { NotificationEvent } from '@pushprotocol/restapi'; import { NotificationItem, chainNameType } from '@pushprotocol/uiweb'; -import { Box, Text } from 'blocks'; +import { Box } from 'blocks'; import { useBlocksTheme } from 'blocks/Blocks.hooks'; import { FC } from 'react'; -import { css, useTheme } from 'styled-components'; type NotificationToastProps = { notification: NotificationEvent | null; @@ -15,12 +14,7 @@ const NotificationToast: FC = ({ notification }) => { return ( {notification && ( { const [isStreamConnected, setIsStreamConnected] = useState(false); @@ -39,21 +39,11 @@ export const useStream = () => { userPushSDKInstance?.stream, data ); - //confirm if only needed for inbox and discuss the working in older file for video - // if (data.event === NotificationEventType.INBOX) - //shift to app.tsx maybe - - notification.show({ - overlay: , - }); + handleNotificationToast(data); setNotificationFeed(data); }); }; - // const removeListeners = () => { - // userPushSDKInstance?.stream?.off(CONSTANTS.STREAM.CONNECT); - // userPushSDKInstance?.stream?.off(CONSTANTS.STREAM.DISCONNECT); - // userPushSDKInstance?.stream?.off(CONSTANTS.STREAM.NOTIF); - // }; + useEffect(() => { (async () => { if (userPushSDKInstance && userPushSDKInstance?.stream && userPushSDKInstance?.readmode()) @@ -61,17 +51,8 @@ export const useStream = () => { })(); // Cleanup listener on unmount - return () => { - // (async()=>{ - // await userPushSDKInstance.reinit([ - // CONSTANTS.STREAM.NOTIF, // Listen for notification events - // CONSTANTS.STREAM.CONNECT, // Listen for connection events - // CONSTANTS.STREAM.DISCONNECT, // Listen for disconnection events - // ]); - // })(); - // removeListeners(); - }; + return () => {}; }, [userPushSDKInstance]); - return { isStreamConnected, notificationFeed }; // Return the event data so components can use it + return { isStreamConnected, notificationFeed }; }; diff --git a/yarn.lock b/yarn.lock index 2723d406ec..493943796e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3991,9 +3991,9 @@ __metadata: languageName: node linkType: hard -"@pushprotocol/uiweb@npm:1.4.3": - version: 1.4.3 - resolution: "@pushprotocol/uiweb@npm:1.4.3" +"@pushprotocol/uiweb@npm:2.0.0-exp.1": + version: 2.0.0-exp.1 + resolution: "@pushprotocol/uiweb@npm:2.0.0-exp.1" dependencies: "@livekit/components-react": "npm:^1.2.2" "@livekit/components-styles": "npm:^1.0.6" @@ -4035,7 +4035,7 @@ __metadata: react-dom: 17.0.2 styled-components: ^6.0.8 viem: ^1.3.0 - checksum: 10/3b8453da5e94b148d3ad0dfe41170e75b6bc3731c6a64cd655f35e573ec5bddca70c29174ab041cd1aede95195e37c2bac8167a97d1cd4ab7156e8b9446e3a70 + checksum: 10/bb5b439b0f1981906fe19bd4c0f0df3cb6f31a2a557aad1cf6f41d3531a922fc1c99ebe4334ebbe198095d84805920c03eb80ce9fad1facfbd4633030529de8f languageName: node linkType: hard @@ -18298,7 +18298,7 @@ __metadata: "@mui/material": "npm:^5.5.0" "@pushprotocol/restapi": "npm:1.7.25" "@pushprotocol/socket": "npm:0.5.3" - "@pushprotocol/uiweb": "npm:1.4.3" + "@pushprotocol/uiweb": "npm:2.0.0-exp.1" "@radix-ui/react-dialog": "npm:^1.1.1" "@radix-ui/react-dropdown-menu": "npm:^2.1.1" "@radix-ui/react-switch": "npm:^1.1.0" From 945261198114c6f06e331836a50f87bb0ce010e6 Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Fri, 27 Sep 2024 13:33:56 +0530 Subject: [PATCH 03/11] fixed unused code --- src/App.tsx | 2 +- src/common/Common.utils.tsx | 6 +++--- src/common/hooks/useStream.tsx | 3 +-- src/contexts/AppContext.tsx | 1 - 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index d170a09927..689006e6f4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -360,7 +360,7 @@ export default function App() { { notification.show({ overlay: , }); - setTimeout(() => { - notification.hide(); - }, 10000); + // setTimeout(() => { + // notification.hide(); + // }, 10000); }; diff --git a/src/common/hooks/useStream.tsx b/src/common/hooks/useStream.tsx index a5e896bc57..07c042e77b 100644 --- a/src/common/hooks/useStream.tsx +++ b/src/common/hooks/useStream.tsx @@ -36,8 +36,7 @@ export const useStream = () => { userPushSDKInstance, userPushSDKInstance?.uid, userPushSDKInstance?.stream?.uid, - userPushSDKInstance?.stream, - data + userPushSDKInstance?.stream ); handleNotificationToast(data); setNotificationFeed(data); diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx index a3464ec467..9a9952921e 100644 --- a/src/contexts/AppContext.tsx +++ b/src/contexts/AppContext.tsx @@ -233,7 +233,6 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { account: account, alpha: { feature: ['SCALABILITY_V2'] }, }); - // if (!(userPushSDKInstance?.stream && userPushSDKInstance?.stream?.disconnected)) await setupStream(userInstance); console.debug('src::contexts::AppContext::initializePushSdkReadMode::User Instance Initialized', userInstance); dispatch(setUserPushSDKInstance(userInstance)); From 12f68e19abab89c1bd43eb091d0c23cde27d9737 Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Fri, 27 Sep 2024 16:42:33 +0530 Subject: [PATCH 04/11] fixed review comments --- src/App.tsx | 5 +- src/blocks/notification/Notification.tsx | 89 ++++++++++++++++- src/blocks/notification/Notification.types.ts | 9 +- src/common/Common.utils.tsx | 12 --- ...cationToast.tsx => InAppNotifications.tsx} | 6 +- src/common/components/NotificationOverlay.tsx | 97 ------------------- src/common/components/index.ts | 3 +- src/common/hooks/index.ts | 2 +- ...seStream.tsx => useInAppNotifications.tsx} | 15 +-- src/contexts/AppContext.tsx | 2 + src/hooks/useStream.ts | 2 +- 11 files changed, 113 insertions(+), 129 deletions(-) rename src/common/components/{NotificationToast.tsx => InAppNotifications.tsx} (86%) delete mode 100644 src/common/components/NotificationOverlay.tsx rename src/common/hooks/{useStream.tsx => useInAppNotifications.tsx} (84%) diff --git a/src/App.tsx b/src/App.tsx index 689006e6f4..7a48139272 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -53,8 +53,7 @@ import SpaceContextProvider from 'contexts/SpaceContext'; import { SpaceWidgetSection } from 'sections/space/SpaceWidgetSection'; import { blocksColors, getBlocksCSSVariables } from 'blocks'; import APP_PATHS from 'config/AppPaths'; -import { CONSTANTS } from '@pushprotocol/restapi'; -import { useStream } from 'common'; +import { useInAppNotifications } from 'common'; dotenv.config(); @@ -338,7 +337,7 @@ export default function App() { location?.pathname.includes('/snap') || location?.pathname.includes(APP_PATHS.DiscordVerification); - useStream(); + useInAppNotifications(); return ( diff --git a/src/blocks/notification/Notification.tsx b/src/blocks/notification/Notification.tsx index 7db468e422..808bc13476 100644 --- a/src/blocks/notification/Notification.tsx +++ b/src/blocks/notification/Notification.tsx @@ -2,11 +2,94 @@ import { FC } from 'react'; import styled from 'styled-components'; import { NotificationProps } from './Notification.types'; import { toast } from 'sonner'; +import { Cross } from 'blocks'; +import { getTextVariantStyles } from 'blocks/Blocks.utils'; -const Notification: FC = ({ overlay, onClick }) => { - const handleNotificationClick = () => onClick?.(); +const NotificationContainer = styled.div` + position: relative; + background-color: var(--components-in-app-notification-background-default); + border-radius: var(--radius-xxs); + box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: row; + align-items: stretch; + max-height: 111px; + min-width: 397px; + max-width: 100%; + cursor: pointer; + box-sizing: border-box; + border: var(--border-sm) solid var(--components-in-app-notification-stroke-bg); +`; +const TextContainer = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + padding: var(--spacing-sm); + flex: 1; + box-sizing: border-box; +`; + +const NotificationTitle = styled.span` + ${() => getTextVariantStyles('h5-semibold', 'components-in-app-notification-text-default')} +`; + +const NotificationDescription = styled.span` + ${() => getTextVariantStyles('bes-regular', 'components-in-app-notification-text-secondary')} + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 3; + line-clamp: 3; + -webkit-box-orient: vertical; +`; - return
{overlay}
; +const IconContainer = styled.div` + padding: var(--spacing-sm) var(--spacing-xs); + border-radius: var(--radius-xxs) var(--radius-none) var(--radius-none) var(--radius-xxs); + background: radial-gradient(79.55% 79.55% at 50% 50%, #344efd 0%, #171717 100%); +`; + +const CloseButton = styled.div` + background-color: var(--surface-transparent); + cursor: pointer; + color: var(--components-in-app-notification-icon-default); + padding: var(--spacing-none); + position: absolute; + right: var(--spacing-xxs); + top: var(--spacing-xxs); +`; +const Container = styled.div``; + +const Notification: FC = ({ overlay, onClick, onClose, image, title = '', description = '' }) => { + const handleNotificationClick = () => onClick?.(); + const handleNotificationClose = () => { + onClose?.(); + notification.hide(); + }; + return ( + + {overlay ? ( + <>{overlay} + ) : ( + + {image && {image}} + { + e.stopPropagation(); + handleNotificationClose(); + }} + > + + + + {title} + {description} + + + )} + + ); }; // Store the toastId(s) in an array to manage multiple notifications diff --git a/src/blocks/notification/Notification.types.ts b/src/blocks/notification/Notification.types.ts index edae2fc5c7..ddef83e811 100644 --- a/src/blocks/notification/Notification.types.ts +++ b/src/blocks/notification/Notification.types.ts @@ -1,8 +1,15 @@ import { ReactNode } from 'react'; export type NotificationProps = { + image?: ReactNode; + /* Title of the notification */ + title?: string; + /* Description of the notification */ + description?: string; + /* Optional onClose action for the notification */ + onClose?: () => void; /* Custom React component to be passed as the image. */ - overlay: ReactNode; + overlay?: ReactNode; /* Optional onClick event for the notification */ onClick?: () => void; /* Position of the notification */ diff --git a/src/common/Common.utils.tsx b/src/common/Common.utils.tsx index 87f780f678..917c02a7b7 100644 --- a/src/common/Common.utils.tsx +++ b/src/common/Common.utils.tsx @@ -1,8 +1,5 @@ -import { NotificationEvent } from '@pushprotocol/restapi'; import { LOGO_ALIAS_CHAIN } from './Common.constants'; import { networkName } from 'helpers/UtilityHelper'; -import { NotificationToast } from './components'; -import { notification } from 'blocks'; export const getSelectChains = (chainIdList: Array) => { return chainIdList?.map((key: number) => { @@ -14,12 +11,3 @@ export const getSelectChains = (chainIdList: Array) => { }; }); }; - -export const handleNotificationToast = (data: NotificationEvent) => { - notification.show({ - overlay: , - }); - // setTimeout(() => { - // notification.hide(); - // }, 10000); -}; diff --git a/src/common/components/NotificationToast.tsx b/src/common/components/InAppNotifications.tsx similarity index 86% rename from src/common/components/NotificationToast.tsx rename to src/common/components/InAppNotifications.tsx index e5ee1f146e..6d03cd26ea 100644 --- a/src/common/components/NotificationToast.tsx +++ b/src/common/components/InAppNotifications.tsx @@ -4,11 +4,11 @@ import { Box } from 'blocks'; import { useBlocksTheme } from 'blocks/Blocks.hooks'; import { FC } from 'react'; -type NotificationToastProps = { +type InAppNotificationsProps = { notification: NotificationEvent | null; }; -const NotificationToast: FC = ({ notification }) => { +const InAppNotifications: FC = ({ notification }) => { const payload = notification?.message?.payload; const { mode } = useBlocksTheme(); return ( @@ -33,4 +33,4 @@ const NotificationToast: FC = ({ notification }) => { ); }; -export { NotificationToast }; +export { InAppNotifications }; diff --git a/src/common/components/NotificationOverlay.tsx b/src/common/components/NotificationOverlay.tsx deleted file mode 100644 index c1fa627d24..0000000000 --- a/src/common/components/NotificationOverlay.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { FC, ReactNode } from 'react'; -import styled from 'styled-components'; -import { Cross } from 'blocks'; -import { getTextVariantStyles } from 'blocks/Blocks.utils'; -import { Box } from 'blocks'; -import { notification } from 'blocks'; - -const NotificationContainer = styled.div` - position: relative; - background-color: var(--components-in-app-notification-background-default); - border-radius: var(--radius-xxs); - box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.05); - display: flex; - flex-direction: row; - align-items: stretch; - max-height: 111px; - min-width: 397px; - max-width: 100%; - cursor: pointer; - box-sizing: border-box; - border: var(--border-sm) solid var(--components-in-app-notification-stroke-bg); -`; -const TextContainer = styled.div` - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: flex-start; - padding: var(--spacing-sm); - flex: 1; - box-sizing: border-box; -`; - -const NotificationTitle = styled.span` - ${() => getTextVariantStyles('h5-semibold', 'components-in-app-notification-text-default')} -`; - -const NotificationDescription = styled.span` - ${() => getTextVariantStyles('bes-regular', 'components-in-app-notification-text-secondary')} - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 3; - line-clamp: 3; - -webkit-box-orient: vertical; -`; - -const IconContainer = styled.div` - padding: var(--spacing-sm) var(--spacing-xs); - border-radius: var(--radius-xxs) var(--radius-none) var(--radius-none) var(--radius-xxs); - background: radial-gradient(79.55% 79.55% at 50% 50%, #344efd 0%, #171717 100%); -`; - -const CloseButton = styled.div` - background-color: var(--surface-transparent); - cursor: pointer; - color: var(--components-in-app-notification-icon-default); - padding: var(--spacing-none); - position: absolute; - right: var(--spacing-xxs); - top: var(--spacing-xxs); -`; - -type NotificationOverlayProps = { - image: ReactNode; - /* Title of the notification */ - title: string; - /* Description of the notification */ - description: string; - /* Optional onClose action for the notification */ - onClose?: () => void; -}; - -const NotificationOverlay: FC = ({ onClose, title, description, image }) => { - const handleNotificationClose = () => { - onClose?.(); - notification.hide(); - }; - return ( - - {image} - { - e.stopPropagation(); - handleNotificationClose(); - }} - > - - - - {title} - {description} - - - ); -}; - -export { NotificationOverlay }; diff --git a/src/common/components/index.ts b/src/common/components/index.ts index 4814569fec..708d034ffc 100644 --- a/src/common/components/index.ts +++ b/src/common/components/index.ts @@ -5,5 +5,4 @@ export * from './UnsubscribeChannelDropdown'; export * from './ModalHeader'; export * from './StakingVariant'; export * from './TokenFaucet'; -export * from './NotificationOverlay'; -export * from './NotificationToast'; +export * from './InAppNotifications'; diff --git a/src/common/hooks/index.ts b/src/common/hooks/index.ts index 1ee603cd54..c01f5fcdb9 100644 --- a/src/common/hooks/index.ts +++ b/src/common/hooks/index.ts @@ -1,4 +1,4 @@ export { useIsVisible } from './useIsVisible'; export { usePushStakingStats } from './usePushStakingStats'; export { useDisclosure } from './useDisclosure'; -export { useStream } from './useStream'; +export { useInAppNotifications } from './useInAppNotifications'; diff --git a/src/common/hooks/useStream.tsx b/src/common/hooks/useInAppNotifications.tsx similarity index 84% rename from src/common/hooks/useStream.tsx rename to src/common/hooks/useInAppNotifications.tsx index 07c042e77b..08332b3c4f 100644 --- a/src/common/hooks/useStream.tsx +++ b/src/common/hooks/useInAppNotifications.tsx @@ -2,11 +2,10 @@ import { CONSTANTS, NotificationEvent } from '@pushprotocol/restapi'; import { useEffect, useState } from 'react'; import { notification } from 'blocks'; import { useSelector } from 'react-redux'; -import { NotificationToast, handleNotificationToast } from 'common'; +import { InAppNotifications } from 'common'; -export const useStream = () => { +export const useInAppNotifications = () => { const [isStreamConnected, setIsStreamConnected] = useState(false); - const [notificationFeed, setNotificationFeed] = useState(null); const { userPushSDKInstance } = useSelector((state: any) => { return state.user; }); @@ -38,8 +37,12 @@ export const useStream = () => { userPushSDKInstance?.stream?.uid, userPushSDKInstance?.stream ); - handleNotificationToast(data); - setNotificationFeed(data); + notification.show({ + overlay: , + }); + // setTimeout(() => { + // notification.hide(); + // }, 10000); }); }; @@ -53,5 +56,5 @@ export const useStream = () => { return () => {}; }, [userPushSDKInstance]); - return { isStreamConnected, notificationFeed }; + return { isStreamConnected }; }; diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx index 9a9952921e..25d778cde0 100644 --- a/src/contexts/AppContext.tsx +++ b/src/contexts/AppContext.tsx @@ -233,6 +233,8 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { account: account, alpha: { feature: ['SCALABILITY_V2'] }, }); + + // sets up stream in read mode await setupStream(userInstance); console.debug('src::contexts::AppContext::initializePushSdkReadMode::User Instance Initialized', userInstance); dispatch(setUserPushSDKInstance(userInstance)); diff --git a/src/hooks/useStream.ts b/src/hooks/useStream.ts index 60b8a503d9..2bb279512a 100644 --- a/src/hooks/useStream.ts +++ b/src/hooks/useStream.ts @@ -73,7 +73,7 @@ const useSDKStream = () => { useEffect(() => { if (userPushSDKInstance?.signer) { (async () => { - if (userPushSDKInstance?.stream && userPushSDKInstance?.stream?.disconnected) { + if (userPushSDKInstance?.stream && !userPushSDKInstance?.stream?.disconnected) { setStream(userPushSDKInstance?.stream); } else { const stream = await userPushSDKInstance.initStream([STREAM.CONNECT, STREAM.DISCONNECT, STREAM.NOTIF]); From 739402426f7a71e9224a788929b5937552daf59b Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Thu, 3 Oct 2024 14:20:18 +0530 Subject: [PATCH 05/11] notif changes --- package.json | 2 +- src/common/components/InAppNotifications.tsx | 49 +++++++++++--------- src/common/hooks/useInAppNotifications.tsx | 8 ++-- yarn.lock | 10 ++-- 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 3e3d4597eb..bca0d34bf3 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@mui/material": "^5.5.0", "@pushprotocol/restapi": "1.7.25", "@pushprotocol/socket": "0.5.3", - "@pushprotocol/uiweb": "2.0.0-exp.1", + "@pushprotocol/uiweb": "2.0.0-exp.2", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-switch": "^1.1.0", diff --git a/src/common/components/InAppNotifications.tsx b/src/common/components/InAppNotifications.tsx index 6d03cd26ea..c872155fb7 100644 --- a/src/common/components/InAppNotifications.tsx +++ b/src/common/components/InAppNotifications.tsx @@ -1,35 +1,40 @@ import { NotificationEvent } from '@pushprotocol/restapi'; import { NotificationItem, chainNameType } from '@pushprotocol/uiweb'; -import { Box } from 'blocks'; +import { Box, Link, notification } from 'blocks'; import { useBlocksTheme } from 'blocks/Blocks.hooks'; +import APP_PATHS from 'config/AppPaths'; import { FC } from 'react'; type InAppNotificationsProps = { - notification: NotificationEvent | null; + notificationDetails: NotificationEvent | null; }; -const InAppNotifications: FC = ({ notification }) => { - const payload = notification?.message?.payload; +const InAppNotifications: FC = ({ notificationDetails }) => { + const payload = notificationDetails?.message?.payload; const { mode } = useBlocksTheme(); return ( - - {notification && ( - - )} - + + + {notificationDetails && ( + notification.hide()} + notificationTitle={payload?.title} + notificationBody={payload?.body} + cta={payload?.cta} + image={payload?.embed} + app={notificationDetails?.channel?.name} + icon={notificationDetails?.channel?.icon} + url={notificationDetails?.channel?.url} + chainName={notificationDetails?.source as chainNameType} + theme={mode} + /> + )} + + ); }; diff --git a/src/common/hooks/useInAppNotifications.tsx b/src/common/hooks/useInAppNotifications.tsx index 08332b3c4f..dbcb1a6fa7 100644 --- a/src/common/hooks/useInAppNotifications.tsx +++ b/src/common/hooks/useInAppNotifications.tsx @@ -38,11 +38,11 @@ export const useInAppNotifications = () => { userPushSDKInstance?.stream ); notification.show({ - overlay: , + overlay: , }); - // setTimeout(() => { - // notification.hide(); - // }, 10000); + setTimeout(() => { + notification.hide(); + }, 5000); }); }; diff --git a/yarn.lock b/yarn.lock index 493943796e..2ef0dcd73b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3991,9 +3991,9 @@ __metadata: languageName: node linkType: hard -"@pushprotocol/uiweb@npm:2.0.0-exp.1": - version: 2.0.0-exp.1 - resolution: "@pushprotocol/uiweb@npm:2.0.0-exp.1" +"@pushprotocol/uiweb@npm:2.0.0-exp.2": + version: 2.0.0-exp.2 + resolution: "@pushprotocol/uiweb@npm:2.0.0-exp.2" dependencies: "@livekit/components-react": "npm:^1.2.2" "@livekit/components-styles": "npm:^1.0.6" @@ -4035,7 +4035,7 @@ __metadata: react-dom: 17.0.2 styled-components: ^6.0.8 viem: ^1.3.0 - checksum: 10/bb5b439b0f1981906fe19bd4c0f0df3cb6f31a2a557aad1cf6f41d3531a922fc1c99ebe4334ebbe198095d84805920c03eb80ce9fad1facfbd4633030529de8f + checksum: 10/77f4246b5e2cb96682218abf0664e433decc1b85c881d254c1f70f29c74a2381786051b87fcdea53f9a84bd595ce3a7305a8b2b28d8b5deac3530be48fc756cd languageName: node linkType: hard @@ -18298,7 +18298,7 @@ __metadata: "@mui/material": "npm:^5.5.0" "@pushprotocol/restapi": "npm:1.7.25" "@pushprotocol/socket": "npm:0.5.3" - "@pushprotocol/uiweb": "npm:2.0.0-exp.1" + "@pushprotocol/uiweb": "npm:2.0.0-exp.2" "@radix-ui/react-dialog": "npm:^1.1.1" "@radix-ui/react-dropdown-menu": "npm:^2.1.1" "@radix-ui/react-switch": "npm:^1.1.0" From a1b7177b71fc0a4eb011af4f502092f977c9ee3a Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Thu, 3 Oct 2024 17:38:48 +0530 Subject: [PATCH 06/11] fixed toast width --- src/blocks/notification/Notification.tsx | 8 +++++++- src/common/hooks/useInAppNotifications.tsx | 14 +++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/blocks/notification/Notification.tsx b/src/blocks/notification/Notification.tsx index f49f54d213..9750a8f66a 100644 --- a/src/blocks/notification/Notification.tsx +++ b/src/blocks/notification/Notification.tsx @@ -24,6 +24,12 @@ const NotificationContainer = styled.div` width: -webkit-fill-available; } `; +const StyledToaster = styled(Toaster)` + width: 397px; + @media${deviceMediaQ.mobileL} { + width: 100%; + } +`; const TextContainer = styled.div` display: flex; flex-direction: column; @@ -98,7 +104,7 @@ const NotificationItem: FC = ({ overlay, onClose, title, desc const Notification = () => { return ( - diff --git a/src/common/hooks/useInAppNotifications.tsx b/src/common/hooks/useInAppNotifications.tsx index 57372199f0..256f29710f 100644 --- a/src/common/hooks/useInAppNotifications.tsx +++ b/src/common/hooks/useInAppNotifications.tsx @@ -37,17 +37,13 @@ export const useInAppNotifications = () => { userPushSDKInstance?.stream?.uid, userPushSDKInstance?.stream ); - // notification.show({ - // overlay: , - // }); notification.show({ - title: 'Push Points are Live', - description: 'Complete Tasks on Push. Check-in, Earn Push Points, Unlock Rewards and Level up!', - image: , + overlay: , }); - // setTimeout(() => { - // notification.hide(); - // }, 5000); + + setTimeout(() => { + notification.hide(); + }, 5000); }); }; From cbcd48f7f5ad1bdb97d6c6ee82adc42258185770 Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Mon, 7 Oct 2024 14:42:58 +0530 Subject: [PATCH 07/11] added review changes --- src/blocks/notification/Notification.types.ts | 2 +- ...ions.tsx => InAppChannelNotifications.tsx} | 4 ++-- src/common/components/index.ts | 2 +- src/common/hooks/useInAppNotifications.tsx | 19 +++++++++++-------- 4 files changed, 15 insertions(+), 12 deletions(-) rename src/common/components/{InAppNotifications.tsx => InAppChannelNotifications.tsx} (90%) diff --git a/src/blocks/notification/Notification.types.ts b/src/blocks/notification/Notification.types.ts index ddef83e811..924f78109a 100644 --- a/src/blocks/notification/Notification.types.ts +++ b/src/blocks/notification/Notification.types.ts @@ -13,7 +13,7 @@ export type NotificationProps = { /* Optional onClick event for the notification */ onClick?: () => void; /* Position of the notification */ - position?: 'bottom-right' | 'bottom-left'; + position?: 'bottom-right' | 'bottom-left' | 'top-center'; /* Optional duration of the notification component */ duration?: number; }; diff --git a/src/common/components/InAppNotifications.tsx b/src/common/components/InAppChannelNotifications.tsx similarity index 90% rename from src/common/components/InAppNotifications.tsx rename to src/common/components/InAppChannelNotifications.tsx index 96b2995b4a..2096da8fd7 100644 --- a/src/common/components/InAppNotifications.tsx +++ b/src/common/components/InAppChannelNotifications.tsx @@ -9,7 +9,7 @@ type InAppNotificationsProps = { notificationDetails: NotificationEvent | null; }; -const InAppNotifications: FC = ({ notificationDetails }) => { +const InAppChannelNotifications: FC = ({ notificationDetails }) => { const payload = notificationDetails?.message?.payload; const { mode } = useBlocksTheme(); return ( @@ -38,4 +38,4 @@ const InAppNotifications: FC = ({ notificationDetails } ); }; -export { InAppNotifications }; +export { InAppChannelNotifications }; diff --git a/src/common/components/index.ts b/src/common/components/index.ts index 708d034ffc..bc9a270beb 100644 --- a/src/common/components/index.ts +++ b/src/common/components/index.ts @@ -5,4 +5,4 @@ export * from './UnsubscribeChannelDropdown'; export * from './ModalHeader'; export * from './StakingVariant'; export * from './TokenFaucet'; -export * from './InAppNotifications'; +export * from './InAppChannelNotifications'; diff --git a/src/common/hooks/useInAppNotifications.tsx b/src/common/hooks/useInAppNotifications.tsx index 256f29710f..1ef3eb79c3 100644 --- a/src/common/hooks/useInAppNotifications.tsx +++ b/src/common/hooks/useInAppNotifications.tsx @@ -1,11 +1,16 @@ -import { CONSTANTS, NotificationEvent } from '@pushprotocol/restapi'; import { useEffect, useState } from 'react'; -import { RewardPoints, notification } from 'blocks'; + +import { CONSTANTS, NotificationEvent } from '@pushprotocol/restapi'; import { useSelector } from 'react-redux'; -import { InAppNotifications } from 'common'; + +import { deviceSizes, notification } from 'blocks'; +import { InAppChannelNotifications } from 'common'; + +import { useDeviceWidthCheck } from 'hooks'; export const useInAppNotifications = () => { const [isStreamConnected, setIsStreamConnected] = useState(false); + const isMobile = useDeviceWidthCheck(parseInt(deviceSizes.mobileL)); const { userPushSDKInstance } = useSelector((state: any) => { return state.user; }); @@ -38,12 +43,10 @@ export const useInAppNotifications = () => { userPushSDKInstance?.stream ); notification.show({ - overlay: , + overlay: , + position: isMobile ? 'top-center' : 'bottom-right', + duration: 5000, }); - - setTimeout(() => { - notification.hide(); - }, 5000); }); }; From 964c78934f3d3cfc4d67f0eb6989e75e87e6e9a2 Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Mon, 7 Oct 2024 15:15:26 +0530 Subject: [PATCH 08/11] added review changes --- src/common/components/InAppChannelNotifications.tsx | 5 ++++- src/common/hooks/useInAppNotifications.tsx | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/common/components/InAppChannelNotifications.tsx b/src/common/components/InAppChannelNotifications.tsx index 2096da8fd7..ef8b4b4013 100644 --- a/src/common/components/InAppChannelNotifications.tsx +++ b/src/common/components/InAppChannelNotifications.tsx @@ -13,7 +13,10 @@ const InAppChannelNotifications: FC = ({ notificationDe const payload = notificationDetails?.message?.payload; const { mode } = useBlocksTheme(); return ( - + { overlay: , position: isMobile ? 'top-center' : 'bottom-right', duration: 5000, + onClick: () => { + notification.hide(); + }, }); }); }; From 9bb399757215107af3afe876000b312b43f2a08f Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Mon, 7 Oct 2024 16:46:08 +0530 Subject: [PATCH 09/11] update sdk to 1.5.0 --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index cfb6e45bbb..d97c238a00 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@mui/material": "^5.5.0", "@pushprotocol/restapi": "1.7.25", "@pushprotocol/socket": "0.5.3", - "@pushprotocol/uiweb": "2.0.0-exp.4", + "@pushprotocol/uiweb": "1.5.0", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-switch": "^1.1.0", diff --git a/yarn.lock b/yarn.lock index 3eb28dea33..e5fe044936 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3990,9 +3990,9 @@ __metadata: languageName: node linkType: hard -"@pushprotocol/uiweb@npm:2.0.0-exp.4": - version: 2.0.0-exp.4 - resolution: "@pushprotocol/uiweb@npm:2.0.0-exp.4" +"@pushprotocol/uiweb@npm:1.5.0": + version: 1.5.0 + resolution: "@pushprotocol/uiweb@npm:1.5.0" dependencies: "@livekit/components-react": "npm:^1.2.2" "@livekit/components-styles": "npm:^1.0.6" @@ -4034,7 +4034,7 @@ __metadata: react-dom: 17.0.2 styled-components: ^6.0.8 viem: ^1.3.0 - checksum: 10/2da2c1a0dd7356cb4bdfcb0866ec53f50a1891b2f8343ad21ba5fe6cae37dfe4cb9ab6cd6423cb381c64a01a8a83ecb51a1718cf7fc1173399d33763a9defc86 + checksum: 10/43eba2cab26c15c06dbaaade167e65f843dda4381b2daf9206c6931b4582c0282ac79f6ca9baafa687f3c86bd5ae2324bc5f01d853a9b7eb56aafa74f68e2e33 languageName: node linkType: hard @@ -18290,7 +18290,7 @@ __metadata: "@mui/material": "npm:^5.5.0" "@pushprotocol/restapi": "npm:1.7.25" "@pushprotocol/socket": "npm:0.5.3" - "@pushprotocol/uiweb": "npm:2.0.0-exp.4" + "@pushprotocol/uiweb": "npm:1.5.0" "@radix-ui/react-dialog": "npm:^1.1.1" "@radix-ui/react-dropdown-menu": "npm:^2.1.1" "@radix-ui/react-switch": "npm:^1.1.0" From 3c90b26878a4fadf9657de9277a90e97955e941b Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Mon, 7 Oct 2024 19:14:55 +0530 Subject: [PATCH 10/11] added review changes --- .../sendNotification/SendNotification.form.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/modules/sendNotification/SendNotification.form.ts b/src/modules/sendNotification/SendNotification.form.ts index f40857a0dd..1d3c3c848d 100644 --- a/src/modules/sendNotification/SendNotification.form.ts +++ b/src/modules/sendNotification/SendNotification.form.ts @@ -2,7 +2,7 @@ import { NotificationType } from '@pushprotocol/restapi'; import * as yup from 'yup'; import { SelectOption } from 'blocks/select/Select'; -import { getRequiredFieldMessage } from 'common'; +import { getMaxCharLimitFieldMessage, getRequiredFieldMessage } from 'common'; import { appConfig } from 'config'; export const getValidationSchema = (isSubsetRecipientPresent: boolean) => { @@ -10,16 +10,19 @@ export const getValidationSchema = (isSubsetRecipientPresent: boolean) => { channelAddress: yup.string().required(getRequiredFieldMessage('Delegate')), chainId: yup.string().required(getRequiredFieldMessage('Chain')), type: yup.string().required(getRequiredFieldMessage('Type')), - body: yup.string().required(getRequiredFieldMessage('Description')), + body: yup.string().required(getRequiredFieldMessage('Description')).max(500, getMaxCharLimitFieldMessage(500)), setting: yup.string().required(getRequiredFieldMessage('Setting')), recipient: yup.string().test('recipient', getRequiredFieldMessage('Recipient'), function (value) { return ( (this.parent.type !== 'SUBSET' || isSubsetRecipientPresent) && (this.parent.type !== 'TARGETTED' || !!value) ); }), - title: yup.string().test('title', getRequiredFieldMessage('Title'), function (value) { - return !this.parent.titleChecked || !!value; - }), + title: yup + .string() + .test('title', getRequiredFieldMessage('Title'), function (value) { + return !this.parent.titleChecked || !!value; + }) + .max(80, getMaxCharLimitFieldMessage(80)), mediaUrl: yup.string().test('mediaUrl', getRequiredFieldMessage('Media URL'), function (value) { return !this.parent.mediaUrlChecked || !!value; }), From 45772c125d8460c0a300c950f96f7711f91e80b7 Mon Sep 17 00:00:00 2001 From: Monalisha Mishra Date: Tue, 8 Oct 2024 19:14:54 +0530 Subject: [PATCH 11/11] added fix for notifications bugs --- src/common/Common.form.ts | 1 + src/common/Common.utils.tsx | 14 ++++++++++++++ src/common/hooks/useInAppNotifications.tsx | 5 +++-- src/contexts/AppContext.tsx | 2 +- src/hooks/useStream.ts | 3 --- .../sendNotification/SendNotification.form.ts | 6 +++--- 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/common/Common.form.ts b/src/common/Common.form.ts index a570b6652e..f05c23a617 100644 --- a/src/common/Common.form.ts +++ b/src/common/Common.form.ts @@ -1,6 +1,7 @@ export const URLRegex = /^(http:\/\/|https:\/\/|www\.)?([\w-]+\.)+[\w-]{2,}(\/[\w.-]*)*\/?$/; export const getRequiredFieldMessage = (name: string) => `${name} is required.`; +export const getValidURLMessage = (name: string) => `${name} is invalid.`; export const getMaxCharLimitFieldMessage = (limit: number) => `Maximum ${limit} characters allowed.`; diff --git a/src/common/Common.utils.tsx b/src/common/Common.utils.tsx index 917c02a7b7..356d97b016 100644 --- a/src/common/Common.utils.tsx +++ b/src/common/Common.utils.tsx @@ -11,3 +11,17 @@ export const getSelectChains = (chainIdList: Array) => { }; }); }; + +export const isValidURL = (str: string | undefined) => { + if (!str) return false; + const pattern = new RegExp( + '^(https?:\\/\\/)' + // protocol + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name + '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path + '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string + '(\\S*)?$', + 'i' + ); // fragment locator + return !!pattern.test(str); +}; diff --git a/src/common/hooks/useInAppNotifications.tsx b/src/common/hooks/useInAppNotifications.tsx index 0828cdbf88..592b596648 100644 --- a/src/common/hooks/useInAppNotifications.tsx +++ b/src/common/hooks/useInAppNotifications.tsx @@ -55,13 +55,14 @@ export const useInAppNotifications = () => { useEffect(() => { (async () => { - if (userPushSDKInstance && userPushSDKInstance?.stream && userPushSDKInstance?.readmode()) + if (userPushSDKInstance && userPushSDKInstance?.stream) { await attachListeners(); + } })(); // Cleanup listener on unmount return () => {}; - }, [userPushSDKInstance]); + }, [userPushSDKInstance?.account]); return { isStreamConnected }; }; diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx index 25d778cde0..15657b03cc 100644 --- a/src/contexts/AppContext.tsx +++ b/src/contexts/AppContext.tsx @@ -312,7 +312,7 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => { CONSTANTS.STREAM.VIDEO, ]); - await stream.connect(); + if (userInstance.readmode()) await stream.connect(); console.debug('src::contexts::AppContext::setupStream::User Intance Stream Connected', userInstance); } }; diff --git a/src/hooks/useStream.ts b/src/hooks/useStream.ts index 2bb279512a..e85636a82c 100644 --- a/src/hooks/useStream.ts +++ b/src/hooks/useStream.ts @@ -8,7 +8,6 @@ import { import { VideoCallContext } from 'contexts/VideoCallContext'; import { ADDITIONAL_META_TYPE } from '@pushprotocol/restapi/src/lib/payloads'; import { VideoCallStatus } from '@pushprotocol/restapi'; -import { showNotifcationToast } from 'components/reusables/toasts/toastController'; import { useSelector } from 'react-redux'; const useSDKStream = () => { @@ -60,8 +59,6 @@ const useSDKStream = () => { retry: true, }); } - } else { - showNotifcationToast(feedItem); } } } catch (e) { diff --git a/src/modules/sendNotification/SendNotification.form.ts b/src/modules/sendNotification/SendNotification.form.ts index 1d3c3c848d..c34f8a442e 100644 --- a/src/modules/sendNotification/SendNotification.form.ts +++ b/src/modules/sendNotification/SendNotification.form.ts @@ -2,7 +2,7 @@ import { NotificationType } from '@pushprotocol/restapi'; import * as yup from 'yup'; import { SelectOption } from 'blocks/select/Select'; -import { getMaxCharLimitFieldMessage, getRequiredFieldMessage } from 'common'; +import { getMaxCharLimitFieldMessage, getRequiredFieldMessage, getValidURLMessage, isValidURL } from 'common'; import { appConfig } from 'config'; export const getValidationSchema = (isSubsetRecipientPresent: boolean) => { @@ -26,8 +26,8 @@ export const getValidationSchema = (isSubsetRecipientPresent: boolean) => { mediaUrl: yup.string().test('mediaUrl', getRequiredFieldMessage('Media URL'), function (value) { return !this.parent.mediaUrlChecked || !!value; }), - ctaLink: yup.string().test('ctaLink', getRequiredFieldMessage('CTA Link'), function (value) { - return !this.parent.ctaLinkChecked || !!value; + ctaLink: yup.string().test('ctaLink', getValidURLMessage('CTA Link'), function (value) { + return this.parent.ctaLinkChecked ? !!value && isValidURL(value) : true; }), }); };