diff --git a/package.json b/package.json index d735d70537..a83c65feed 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@metamask/eth-sig-util": "^4.0.0", "@mui/icons-material": "^5.8.4", "@mui/material": "^5.5.0", - "@pushprotocol/restapi": "1.7.29", + "@pushprotocol/restapi": "^1.7.30", "@pushprotocol/socket": "0.5.3", "@pushprotocol/uiweb": "1.7.3", "@radix-ui/react-dialog": "^1.1.1", diff --git a/src/common/components/ChannelDetailsCard.tsx b/src/common/components/ChannelDetailsCard.tsx index cb58514427..17b0461dae 100644 --- a/src/common/components/ChannelDetailsCard.tsx +++ b/src/common/components/ChannelDetailsCard.tsx @@ -20,7 +20,7 @@ import { Tooltip, } from 'blocks'; import APP_PATHS from 'config/AppPaths'; -import { SubscribeChannelDropdown } from 'common/components/SubscribeChannelDropdown'; +import { ProfileModalVisibilityType, SubscribeChannelDropdown } from 'common/components/SubscribeChannelDropdown'; import { UnsubscribeChannelDropdown } from 'common/components/UnsubscribeChannelDropdown'; import { UserSetting } from 'helpers/channel/types'; import { appConfig } from 'config'; @@ -34,6 +34,8 @@ export type ChannelDetailsCardProps = { userSettings: UserSetting[]; width?: ResponsiveProp; subscribeButtonVariant?: ButtonProps['variant']; + onChangeProfileModalVisibility?: (show: ProfileModalVisibilityType) => void; // Function prop to control modal visibility + profileModalVisibility?: ProfileModalVisibilityType; }; const ChannelDetailsCard: FC = ({ @@ -45,6 +47,8 @@ const ChannelDetailsCard: FC = ({ userSettings, width, subscribeButtonVariant = 'tertiary', + onChangeProfileModalVisibility, + profileModalVisibility, }) => { let verifiedAliasChainIds = [ appConfig.coreContractChain, @@ -104,6 +108,8 @@ const ChannelDetailsCard: FC = ({ height="40px" > @@ -125,6 +131,8 @@ const ChannelDetailsCard: FC = ({ height="40px" > void; + onChangeProfileModalVisibility?: (show: ProfileModalVisibilityType) => void; // Function prop to control modal visibility + profileModalVisibility?: ProfileModalVisibilityType; }; -const SubscribeChannelDropdown: FC = (options) => { - const { children, channelDetails, onSuccess } = options; +const SubscribeChannelDropdown: FC = memo((options) => { + const { children, channelDetails, onSuccess, onChangeProfileModalVisibility, profileModalVisibility } = options; const { account, provider, wallet, chainId } = useAccount(); const { connectWallet } = useAppContext(); + // State to handle the temporary channel setting + const [tempChannelSetting, setTempChannelSettings] = useState(undefined); + // Get the userPushSDKInstance from the store + const { userPushSDKInstance } = useSelector((state: UserStoreType) => state.user); + const channelSettings = channelDetails && channelDetails?.channel_settings ? JSON.parse(channelDetails?.channel_settings) : null; const { mutate: subscribeChannel, isPending } = useSubscribeChannel(); const subscribeToast = useToast(); + useEffect(() => { + // If the user has account and the profile is unlocked, then run the optInHandler + if ( + profileModalVisibility?.isVisible && + profileModalVisibility?.channel_id === channelDetails.id && + userPushSDKInstance && + !userPushSDKInstance?.readmode() + ) { + onChangeProfileModalVisibility?.({ isVisible: false, channel_id: null }); + optInHandler(tempChannelSetting); + } + }, [profileModalVisibility, userPushSDKInstance]); + const optInHandler = async (channelSetting?: ChannelSetting[]) => { const hasAccount = wallet?.accounts?.length > 0; const connectedWallet = !hasAccount ? await connectWallet() : null; + // If the user has account or the wallet is connected, and the profile is locked, then show the profile modal and return + if ((hasAccount || connectedWallet) && userPushSDKInstance && userPushSDKInstance?.readmode()) { + onChangeProfileModalVisibility?.({ isVisible: true, channel_id: channelDetails.id }); + channelSetting && setTempChannelSettings(channelSetting); + return; + } + const walletAddress = hasAccount ? account : connectedWallet.accounts[0].address; const web3Provider = hasAccount ? provider : new ethers.providers.Web3Provider(connectedWallet.provider, 'any'); const onCoreNetwork = chainId === appConfig.coreContractChain; @@ -56,6 +92,8 @@ const SubscribeChannelDropdown: FC = (options) => ? getMinimalUserSetting(notifChannelSettingFormatString({ settings: channelSetting })) : null; + const decryptedPGPKeys = userPushSDKInstance?.decryptedPgpPvtKey ?? retrieveUserPGPKeyFromStorage(account); + subscribeChannel( { signer: _signer, @@ -63,10 +101,10 @@ const SubscribeChannelDropdown: FC = (options) => userAddress: convertAddressToAddrCaip(walletAddress, chainId), settings: minimalNotifSettings, env: appConfig.pushNodesEnv, + decryptedPGPKeys, }, { onSuccess: (response) => { - console.log('Response on the channels apge', response); if (response.status == '204') { onSuccess(); subscribeToast.showMessageToast({ @@ -81,7 +119,6 @@ const SubscribeChannelDropdown: FC = (options) => ), }); } else { - console.log('Error in the response >>', response); subscribeToast.showMessageToast({ toastTitle: 'Error', toastMessage: `There was an error opting into channel`, @@ -100,10 +137,11 @@ const SubscribeChannelDropdown: FC = (options) => }, } ); + tempChannelSetting && setTempChannelSettings(undefined); }; return ( - <> + {channelSettings && channelSettings.length ? ( ( @@ -126,8 +164,8 @@ const SubscribeChannelDropdown: FC = (options) => {children} )} - + ); -}; +}); export { SubscribeChannelDropdown }; diff --git a/src/common/components/UnsubscribeChannelDropdown.tsx b/src/common/components/UnsubscribeChannelDropdown.tsx index 48d0bdc553..34c3a3f54e 100644 --- a/src/common/components/UnsubscribeChannelDropdown.tsx +++ b/src/common/components/UnsubscribeChannelDropdown.tsx @@ -1,5 +1,5 @@ // React and other libraries -import { FC, ReactNode } from 'react'; +import { FC, ReactNode, useEffect, useState } from 'react'; import { MdCheckCircle, MdError } from 'react-icons/md'; import { useSelector } from 'react-redux'; @@ -23,6 +23,8 @@ import { useUnsubscribeChannel, useUpdateNotificationSettings } from 'queries'; // Components import { ManageSettingsDropdown } from './ManageSettingsDropdown'; import { UserStoreType } from 'types'; +import { ProfileModalVisibilityType } from './SubscribeChannelDropdown'; +import { retrieveUserPGPKeyFromStorage } from 'helpers/connectWalletHelper'; export type UnsubscribeChannelDropdownProps = { children: ReactNode; @@ -30,6 +32,8 @@ export type UnsubscribeChannelDropdownProps = { centeronMobile?: boolean; onSuccess: () => void; userSetting?: UserSetting[] | undefined; + onChangeProfileModalVisibility?: (show: ProfileModalVisibilityType) => void; // Function prop to control modal visibility + profileModalVisibility?: ProfileModalVisibilityType; }; const UnsubscribeChannelDropdown: FC = ({ @@ -37,11 +41,16 @@ const UnsubscribeChannelDropdown: FC = ({ channelDetail, onSuccess, userSetting, + profileModalVisibility, + onChangeProfileModalVisibility, }) => { const { account, chainId, provider, wallet } = useAccount(); const { handleConnectWalletAndEnableProfile } = useAppContext(); + // State to handle the temporary channel setting + const [tempSetting, setTempSettings] = useState(undefined); + // Get the userPushSDKInstance from the store const { userPushSDKInstance } = useSelector((state: UserStoreType) => state.user); const channelSetting = @@ -53,7 +62,30 @@ const UnsubscribeChannelDropdown: FC = ({ // This will get changed when new toast is made const unsubscribeToast = useToast(); + useEffect(() => { + // If the user has account and the profile is unlocked, then run the optInHandler + if ( + profileModalVisibility?.isVisible && + profileModalVisibility?.channel_id === channelDetail.id && + userPushSDKInstance && + !userPushSDKInstance?.readmode() + ) { + onChangeProfileModalVisibility?.({ isVisible: false, channel_id: null }); + if (tempSetting) { + handleSaveNotificationSettings(tempSetting); + } else { + handleOptOut(); + } + } + }, [profileModalVisibility, userPushSDKInstance]); + const handleSaveNotificationSettings = async (settings: UserSetting[]) => { + // If the profile is locked, then show the profile modal and return + if (userPushSDKInstance && userPushSDKInstance?.readmode()) { + onChangeProfileModalVisibility?.({ isVisible: true, channel_id: channelDetail.id }); + setTempSettings(settings); + return; + } const onCoreNetwork = chainId === appConfig.coreContractChain; const channelAddress = !onCoreNetwork ? (channelDetail.alias_address as string) : channelDetail.channel; @@ -84,7 +116,6 @@ const UnsubscribeChannelDropdown: FC = ({ ), }); } else { - console.log('Error in Saving notification settings', response); unsubscribeToast.showMessageToast({ toastTitle: 'Error', toastMessage: `There was an error in saving the settings`, @@ -103,26 +134,35 @@ const UnsubscribeChannelDropdown: FC = ({ }, } ); + setTempSettings(undefined); }; const handleOptOut = async () => { + // If the profile is locked, then show the profile modal and return + if (userPushSDKInstance && userPushSDKInstance?.readmode()) { + onChangeProfileModalVisibility?.({ isVisible: true, channel_id: channelDetail.id }); + return; + } const onCoreNetwork = chainId === appConfig.coreContractChain; const channelAddress = !onCoreNetwork ? (channelDetail.alias_address as string) : channelDetail.channel; const _signer = await provider.getSigner(account); + const decryptedPGPKeys = userPushSDKInstance?.decryptedPgpPvtKey ?? retrieveUserPGPKeyFromStorage(account); + unsubscribeChannel( { signer: _signer, channelAddress: convertAddressToAddrCaip(channelAddress, chainId), userAddress: convertAddressToAddrCaip(account, chainId), env: appConfig.pushNodesEnv, + decryptedPGPKeys, }, { onSuccess: (response) => { onSuccess(); - if (response.status === 'success') { + if (response.status === 204) { unsubscribeToast.showMessageToast({ toastTitle: 'Success', toastMessage: 'Successfully opted out of channel !', diff --git a/src/components/chat/unlockProfile/UnlockProfile.tsx b/src/components/chat/unlockProfile/UnlockProfile.tsx index df8ccd2c75..e586c93569 100644 --- a/src/components/chat/unlockProfile/UnlockProfile.tsx +++ b/src/components/chat/unlockProfile/UnlockProfile.tsx @@ -11,7 +11,7 @@ import { useAccount, useDeviceWidthCheck } from 'hooks'; import { retrieveUserPGPKeyFromStorage } from 'helpers/connectWalletHelper'; // Internal Configs -import { device, size } from 'config/Globals'; +import { size } from 'config/Globals'; // Assets import Tooltip from 'components/reusables/tooltip/Tooltip'; @@ -246,7 +246,7 @@ const UnlockProfile = ({ InnerComponentProps, onClose }: UnlockProfileModalProps {activeStatus.status === PROFILESTATE.UNLOCK_PROFILE && ( <> {!isLoading ? ( - + (props.type === UNLOCK_PROFILE_TYPE.MODAL ? 'column' : 'row')}; justify-content: space-between; - @media ${device.tablet} { + @media ${deviceMediaQ.tablet} { align-items: center; flex-direction: column; gap: 24px; @@ -383,7 +383,7 @@ const HorizontalBar = styled.div` ? `linear-gradient(to right, ${colorBrands['primary-500']}, ${props.theme.btn.disabledBg})` : colorBrands['primary-500']}; - @media ${device.tablet} { + @media ${deviceMediaQ.tablet} { width: 2px; height: 40px; } diff --git a/src/components/reusables/tooltip/Tooltip.tsx b/src/components/reusables/tooltip/Tooltip.tsx index 7a07f646bf..f3c831be96 100644 --- a/src/components/reusables/tooltip/Tooltip.tsx +++ b/src/components/reusables/tooltip/Tooltip.tsx @@ -1,4 +1,4 @@ -import { device } from 'config/Globals'; +import { deviceMediaQ } from 'blocks'; import * as React from 'react'; import styled from 'styled-components'; @@ -74,7 +74,7 @@ const Wrapper = styled.div` height: fit-content; display: inline-block; position: relative; - @media ${device.tablet} { + @media ${deviceMediaQ.tablet} { width: 100%; min-width: 100%; max-width: 100%; diff --git a/src/modules/channels/components/AllChannelsList.tsx b/src/modules/channels/components/AllChannelsList.tsx index 0e27159622..e10a6552d2 100644 --- a/src/modules/channels/components/AllChannelsList.tsx +++ b/src/modules/channels/components/AllChannelsList.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import { FC, useState } from 'react'; import InfiniteScroll from 'react-infinite-scroller'; import { css } from 'styled-components'; @@ -9,6 +9,10 @@ import { AllChannelsListItem } from './AllChannelsListItem'; import { SuggestedChannelListItem } from './SuggestedChannelListItem'; import { Box, deviceMediaQ, Spinner } from 'blocks'; +import { UNLOCK_PROFILE_TYPE } from 'components/chat/unlockProfile/UnlockProfile'; +import UnlockProfileWrapper from 'components/chat/unlockProfile/UnlockProfileWrapper'; +import { ProfileModalVisibilityType } from 'common'; + export type AllChannelListProps = { channels: ChannelDetails[]; hasMoreData: boolean; @@ -26,6 +30,12 @@ const AllChannelList: FC = ({ loadMore, suggestedChannels, }) => { + // State to handle the profile modal + const [profileModalVisibility, setProfileModalVisibility] = useState({ + isVisible: false, + channel_id: null, + }); + return ( = ({ ))} {channels.map((channel: ChannelDetails, index: number) => ( setProfileModalVisibility(data)} + profileModalVisibility={profileModalVisibility} key={`${index}`} channelDetails={channel} isLoading={isLoading} @@ -82,6 +94,31 @@ const AllChannelList: FC = ({ /> )} + + {/* Render Unlock profile modal if the profile is not enabled */} + {profileModalVisibility?.isVisible && ( + + + setProfileModalVisibility({ + isVisible: false, + channel_id: null, + }) + } + description="Unlock your profile to proceed." + /> + + )} ); }; diff --git a/src/modules/channels/components/AllChannelsListItem.tsx b/src/modules/channels/components/AllChannelsListItem.tsx index d9ba77f043..5b5c540ead 100644 --- a/src/modules/channels/components/AllChannelsListItem.tsx +++ b/src/modules/channels/components/AllChannelsListItem.tsx @@ -1,5 +1,5 @@ import { FC } from 'react'; -import { ChannelDetailsCard } from 'common'; +import { ChannelDetailsCard, ProfileModalVisibilityType } from 'common'; import { UserSetting } from 'helpers/channel/types'; import { ChannelDetails, useGetUserSubscriptions } from 'queries'; @@ -7,9 +7,16 @@ import { ChannelDetails, useGetUserSubscriptions } from 'queries'; export type AllChannelsListItemProps = { channelDetails: ChannelDetails | undefined; isLoading: boolean; + onChangeProfileModalVisibility?: (value: ProfileModalVisibilityType) => void; // Function prop to control modal visibility + profileModalVisibility?: ProfileModalVisibilityType; }; -const AllChannelsListItem: FC = ({ channelDetails, isLoading }) => { +const AllChannelsListItem: FC = ({ + channelDetails, + isLoading, + onChangeProfileModalVisibility, + profileModalVisibility, +}) => { /* Fetching User Subscribed Channel Details along with user settings */ const { data: userSubscription, @@ -31,6 +38,8 @@ const AllChannelsListItem: FC = ({ channelDetails, isL return ( void; // Function prop to control modal visibility + profileModalVisibility?: ProfileModalVisibilityType; }; -const SuggestedChannelListItem: FC = ({ channelAddress }) => { +const SuggestedChannelListItem: FC = ({ + channelAddress, + onChangeProfileModalVisibility, + profileModalVisibility, +}) => { const { data: channelDetails, isLoading } = useGetChannelDetails(channelAddress); return ( ); }; diff --git a/src/modules/dashboard/components/ChannelListItem.tsx b/src/modules/dashboard/components/ChannelListItem.tsx index ed5516035a..136256a351 100644 --- a/src/modules/dashboard/components/ChannelListItem.tsx +++ b/src/modules/dashboard/components/ChannelListItem.tsx @@ -28,7 +28,7 @@ import { import { UserSetting } from 'helpers/channel/types'; import { useAccount } from 'hooks'; -import { SubscribeChannelDropdown } from 'common/components/SubscribeChannelDropdown'; +import { ProfileModalVisibilityType, SubscribeChannelDropdown } from 'common/components/SubscribeChannelDropdown'; import { UnsubscribeChannelDropdown } from 'common/components/UnsubscribeChannelDropdown'; export type ChannelListItemProps = { @@ -39,12 +39,17 @@ export type ChannelListItemProps = { refetchChannels?: | (() => void) | ((options?: RefetchOptions | undefined) => Promise>); + + onChangeProfileModalVisibility?: (value: ProfileModalVisibilityType) => void; // Function prop to control modal visibility + profileModalVisibility?: ProfileModalVisibilityType; }; const ChannelListItem: FC = ({ allowSubscribe = true, channelAddress, refetchChannels, isLoading, + onChangeProfileModalVisibility, + profileModalVisibility, }) => { const { data: channelDetails, isLoading: isChannelLoading } = useGetChannelDetails(channelAddress); @@ -152,6 +157,8 @@ const ChannelListItem: FC = ({ {allowSubscribe && channelDetails && !isSubscribed && ( @@ -165,6 +172,8 @@ const ChannelListItem: FC = ({ {allowSubscribe && channelDetails && !!isSubscribed && ( = () => { const showMobileAndTabletView = isMobile; + // State to handle the profile modal + const [profileModalVisibility, setProfileModalVisibility] = useState({ + isVisible: false, + channel_id: null, + }); + return ( = () => { alignItems="flex-start" > {showMobileAndTabletView ? ( - + setProfileModalVisibility(data)} + profileModalVisibility={profileModalVisibility} + /> ) : ( - + setProfileModalVisibility(data)} + profileModalVisibility={profileModalVisibility} + /> + )} + + {/* Render Unlock profile modal if the profile is not enabled */} + {profileModalVisibility?.isVisible && ( + + + setProfileModalVisibility({ + isVisible: false, + channel_id: null, + }) + } + description="Unlock your profile to proceed." + /> + )} ); diff --git a/src/modules/dashboard/components/FeaturedChannelsList.tsx b/src/modules/dashboard/components/FeaturedChannelsList.tsx index 964215c8a5..54fc490e94 100644 --- a/src/modules/dashboard/components/FeaturedChannelsList.tsx +++ b/src/modules/dashboard/components/FeaturedChannelsList.tsx @@ -14,12 +14,19 @@ import { Box, HoverableSVG, Text, Link, NextIconSlider, PrevIconSlider, deviceSi import { FeaturedChannelDetailsProps } from '../configs'; import { useFeaturedChannelsCarouselButtons } from '../hooks/useFeaturedChannelsCarouselButtons'; import { useDeviceWidthCheck } from 'hooks'; +import { ProfileModalVisibilityType } from 'common'; export type FeaturedChannelsListProps = { featuredChannelsList: FeaturedChannelDetailsProps[]; + onChangeProfileModalVisibility?: (value: ProfileModalVisibilityType) => void; // Function prop to control modal visibility + profileModalVisibility?: ProfileModalVisibilityType; }; -const FeaturedChannelsList: FC = ({ featuredChannelsList }) => { +const FeaturedChannelsList: FC = ({ + featuredChannelsList, + onChangeProfileModalVisibility, + profileModalVisibility, +}) => { const isTablet = useDeviceWidthCheck(parseInt(deviceSizes.tablet)); const isXsLaptop = useDeviceWidthCheck(parseInt(deviceSizes.laptop)); @@ -104,7 +111,11 @@ const FeaturedChannelsList: FC = ({ featuredChannelsL `} > {featuredChannelsList.map((channel) => ( - + ))} diff --git a/src/modules/dashboard/components/FeaturedChannelsListItem.tsx b/src/modules/dashboard/components/FeaturedChannelsListItem.tsx index 6a4f8ecca9..0bcb0e2ac1 100644 --- a/src/modules/dashboard/components/FeaturedChannelsListItem.tsx +++ b/src/modules/dashboard/components/FeaturedChannelsListItem.tsx @@ -1,15 +1,17 @@ import { FC } from 'react'; import { useAccount } from 'hooks'; -import { ChannelDetailsCard } from 'common'; +import { ChannelDetailsCard, ProfileModalVisibilityType } from 'common'; import { UserSetting } from 'helpers/channel/types'; import { useGetChannelDetails, useGetUserSubscriptions } from 'queries'; type FeaturedChannelsListItemProps = { channelAddress: string; + onChangeProfileModalVisibility?: (value: ProfileModalVisibilityType) => void; // Function prop to control modal visibility + profileModalVisibility?: ProfileModalVisibilityType; }; const FeaturedChannelsListItem: FC = (props) => { - const { channelAddress } = props; + const { channelAddress, onChangeProfileModalVisibility, profileModalVisibility } = props; const { wallet } = useAccount(); const isWalletConnected = !!wallet?.accounts?.length; @@ -38,6 +40,8 @@ const FeaturedChannelsListItem: FC = (props) => { isSubscriptionLoading={isSubscriptionLoading} handleRefetch={handleRefetch} userSettings={JSON.parse(userSubscription?.[0]?.user_settings || '[]') as UserSetting[]} + onChangeProfileModalVisibility={onChangeProfileModalVisibility} + profileModalVisibility={profileModalVisibility} /> ); }; diff --git a/src/modules/dashboard/components/FeaturedChannelsMobileViewList.tsx b/src/modules/dashboard/components/FeaturedChannelsMobileViewList.tsx index bd5d0f9b09..031936791a 100644 --- a/src/modules/dashboard/components/FeaturedChannelsMobileViewList.tsx +++ b/src/modules/dashboard/components/FeaturedChannelsMobileViewList.tsx @@ -15,12 +15,19 @@ import { useFeaturedChannelsCarouselButtons } from '../hooks/useFeaturedChannels // Internal Configs import { FeaturedChannelDetailsProps } from '../configs'; +import { ProfileModalVisibilityType } from 'common'; export type FeaturedChannelsMobileViewListProps = { featuredChannelsList: FeaturedChannelDetailsProps[][]; + onChangeProfileModalVisibility?: (value: ProfileModalVisibilityType) => void; // Function prop to control modal visibility + profileModalVisibility?: ProfileModalVisibilityType; }; -const FeaturedChannelsMobileViewList: FC = ({ featuredChannelsList }) => { +const FeaturedChannelsMobileViewList: FC = ({ + featuredChannelsList, + onChangeProfileModalVisibility, + profileModalVisibility, +}) => { const CarouselOptions: EmblaOptionsType = { slidesToScroll: 'auto', align: 'start', @@ -115,7 +122,11 @@ const FeaturedChannelsMobileViewList: FC = flexDirection="column" > {channelListArray.map((channel: FeaturedChannelDetailsProps) => ( - + ))} ); diff --git a/src/modules/dashboard/components/SubscribedChannelsList.tsx b/src/modules/dashboard/components/SubscribedChannelsList.tsx index 6189df3f7e..2391bf3cdc 100644 --- a/src/modules/dashboard/components/SubscribedChannelsList.tsx +++ b/src/modules/dashboard/components/SubscribedChannelsList.tsx @@ -1,11 +1,16 @@ +import { useState } from 'react'; +import { css } from 'styled-components'; + //Hooks import { useGetUserSubscriptions } from 'queries'; // Components import { Box, Separator } from 'blocks'; import { ChannelListItem } from './ChannelListItem'; - import { EmptyChannelList } from './EmptyChannelList'; +import UnlockProfileWrapper, { UNLOCK_PROFILE_TYPE } from 'components/chat/unlockProfile/UnlockProfileWrapper'; + +import { ProfileModalVisibilityType } from 'common'; const SubscribedChannelsList = () => { const { data: subscribedChannels, isLoading, refetch, isSuccess } = useGetUserSubscriptions(); @@ -13,6 +18,12 @@ const SubscribedChannelsList = () => { // If there are channels then render them else render 5 skeletons const channelList = isLoading ? Array(5).fill(0) : subscribedChannels; + // State to handle the profile modal + const [profileModalVisibility, setProfileModalVisibility] = useState({ + isVisible: false, + channel_id: null, + }); + return ( <> {isSuccess && !isLoading && !subscribedChannels?.length && ( @@ -27,10 +38,37 @@ const SubscribedChannelsList = () => { channelAddress={channel.channel} isLoading={isLoading} refetchChannels={refetch} + onChangeProfileModalVisibility={(data) => setProfileModalVisibility(data)} + profileModalVisibility={profileModalVisibility} /> {index != channelList.length - 1 && } ))} + + {/* Render Unlock profile modal if the profile is not enabled */} + {profileModalVisibility?.isVisible && ( + + + setProfileModalVisibility({ + isVisible: false, + channel_id: null, + }) + } + description="Unlock your profile to proceed." + /> + + )} ); }; diff --git a/src/modules/dashboard/components/TrendingChannelsList.tsx b/src/modules/dashboard/components/TrendingChannelsList.tsx index 8ab807d68e..3bf6b16c2a 100644 --- a/src/modules/dashboard/components/TrendingChannelsList.tsx +++ b/src/modules/dashboard/components/TrendingChannelsList.tsx @@ -1,19 +1,23 @@ // React and other libraries +import { useState } from 'react'; +import { css } from 'styled-components'; //Hooks // import { useGetTrendingChannels } from 'queries/hooks'; -// //Constants +//Constants // import { firstEndDate, secondEndDate, startDate, trendingSource } from '../Dashboard.constants'; // import { appConfig } from 'config'; -// //Utility functions +//Utility functions // import { getTrendingChannelsData } from '../Dashboard.utils'; +import { ProfileModalVisibilityType } from 'common'; -// // Component +// Component // import { EmptyChannelList } from './EmptyChannelList'; import { Box, Separator } from 'blocks'; import { ChannelListItem } from './ChannelListItem'; +import UnlockProfileWrapper, { UNLOCK_PROFILE_TYPE } from 'components/chat/unlockProfile/UnlockProfileWrapper'; //Types // import { EnvKeys } from '../Dashboard.types'; @@ -71,6 +75,12 @@ const TrendingChannelsList = () => { // If there are channels then render them else render 5 skeletons // const channelList = isLoadingTrendingChannels ? Array(5).fill(0) : trendingChannels; + // State to handle the profile modal + const [profileModalVisibility, setProfileModalVisibility] = useState({ + isVisible: false, + channel_id: null, + }); + return ( <> {/* {isSuccess && !isLoadingTrendingChannels && !trendingChannels?.length && ( @@ -88,11 +98,38 @@ const TrendingChannelsList = () => { isLoading={false} // refetchChannels={handleRefetch} refetchChannels={() => {}} + onChangeProfileModalVisibility={(data) => setProfileModalVisibility(data)} + profileModalVisibility={profileModalVisibility} /> {/* {index != trendingChannels.length - 1 && } */} {index != channelList.length - 1 && } ))} + + {/* Render Unlock profile modal if the profile is not enabled */} + {profileModalVisibility?.isVisible && ( + + + setProfileModalVisibility({ + isVisible: false, + channel_id: null, + }) + } + description="Unlock your profile to proceed." + /> + + )} ); }; diff --git a/src/queries/services/user/subscribeToChannel.ts b/src/queries/services/user/subscribeToChannel.ts index 235e746b68..a4a5d7df11 100644 --- a/src/queries/services/user/subscribeToChannel.ts +++ b/src/queries/services/user/subscribeToChannel.ts @@ -7,14 +7,16 @@ export const subscribeToChannel = async ({ channelAddress, userAddress, settings, - env + env, + decryptedPGPKeys, }: SubscribeChannelParams): Promise => { const res = await PushAPI.channels.subscribeV2({ signer: signer, channelAddress: channelAddress, // channel address in CAIP userAddress: userAddress, // user address in CAIP settings: settings, - env + env, + pgpPrivateKey: decryptedPGPKeys, }); return res; }; diff --git a/src/queries/services/user/unsubscribeChannel.ts b/src/queries/services/user/unsubscribeChannel.ts index 00d8b07c0e..59b1302c27 100644 --- a/src/queries/services/user/unsubscribeChannel.ts +++ b/src/queries/services/user/unsubscribeChannel.ts @@ -6,13 +6,15 @@ export const unsubscribeChannel = async ({ signer, channelAddress, userAddress, - env + env, + decryptedPGPKeys, }: UnsubscribeChannelParams): Promise => { - const res = await PushAPI.channels.unsubscribe({ + const res = await PushAPI.channels.unsubscribeV2({ signer: signer, channelAddress: channelAddress, // channel address in CAIP userAddress: userAddress, // user address in CAIP - env + env, + pgpPrivateKey: decryptedPGPKeys, }); return res; }; diff --git a/src/queries/types/user.ts b/src/queries/types/user.ts index 9a393c2633..4c241d1af1 100644 --- a/src/queries/types/user.ts +++ b/src/queries/types/user.ts @@ -13,6 +13,7 @@ export type SubscribeChannelParams = { userAddress: string; settings?: string | null; env: Env; + decryptedPGPKeys?: string | null; }; export type SubsribeChannelResponse = { @@ -26,10 +27,11 @@ export type UnsubscribeChannelParams = { userAddress: string; settings?: string | null; env: Env; + decryptedPGPKeys?: string | null; }; export type UnsubscribeChannelResponse = { - status: string; + status: number; message: string; }; @@ -63,7 +65,7 @@ export type UserSocialStatusResponse = { email: string | null; telegram_username: string | null; discord_username: string | null; - }; +}; export type UserProfileDetailsResponse = { blockedUsersList: Array; @@ -72,4 +74,3 @@ export type UserProfileDetailsResponse = { picture: string; profileVerificationProof: string | null; }; - diff --git a/yarn.lock b/yarn.lock index 190897b887..7d280928b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3808,9 +3808,9 @@ __metadata: languageName: node linkType: hard -"@pushprotocol/restapi@npm:1.7.29": - version: 1.7.29 - resolution: "@pushprotocol/restapi@npm:1.7.29" +"@pushprotocol/restapi@npm:^1.7.30": + version: 1.7.30 + resolution: "@pushprotocol/restapi@npm:1.7.30" dependencies: "@metamask/eth-sig-util": "npm:^5.0.2" axios: "npm:^0.27.2" @@ -3833,7 +3833,7 @@ __metadata: peerDependenciesMeta: ethers: optional: true - checksum: 10/13afab4147598627c470f09706b859af116ffd4831bbb4de1e2f6b3490b5c10f5f06754b820a766614ac145912b9a455c974570a2763b82289aa57f37d55421a + checksum: 10/327dbd17b7b3f34d56e5326502358196fcf9320a2fcdc0b73efa60e959c90f7c9359f1ea5d53387dbc8dc0551bbd9f60685dffd688ef6215558fe9939f2aee8a languageName: node linkType: hard @@ -18017,7 +18017,7 @@ __metadata: "@metamask/eth-sig-util": "npm:^4.0.0" "@mui/icons-material": "npm:^5.8.4" "@mui/material": "npm:^5.5.0" - "@pushprotocol/restapi": "npm:1.7.29" + "@pushprotocol/restapi": "npm:^1.7.30" "@pushprotocol/socket": "npm:0.5.3" "@pushprotocol/uiweb": "npm:1.7.3" "@radix-ui/react-dialog": "npm:^1.1.1"