diff --git a/package.json b/package.json index e000bd148..5ff057bfb 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@gorhom/bottom-sheet": "^4", "@metamask/eth-sig-util": "^5.0.0", "@notifee/react-native": "^9.1.8", - "@pushprotocol/restapi": "^1.7.28", + "@pushprotocol/restapi": "^1.7.30", "@pushprotocol/socket": "latest", "@react-native-async-storage/async-storage": "1.17.11", "@react-native-clipboard/clipboard": "^1.11.1", diff --git a/src/components/buttons/SubscriptionStatus.tsx b/src/components/buttons/SubscriptionStatus.tsx index c5e4b82f3..37121d371 100644 --- a/src/components/buttons/SubscriptionStatus.tsx +++ b/src/components/buttons/SubscriptionStatus.tsx @@ -1,5 +1,5 @@ import {Ionicons, MaterialIcons} from '@expo/vector-icons'; -import React, {useMemo, useState} from 'react'; +import React, {useEffect, useMemo, useState} from 'react'; import { ActivityIndicator, Pressable, @@ -7,32 +7,51 @@ import { Text, View, } from 'react-native'; -import {useSelector} from 'react-redux'; +import {useDispatch, useSelector} from 'react-redux'; import GLOBALS from 'src/Globals'; import PrimaryButton from 'src/components/buttons/PrimaryButton'; +import {usePushApi} from 'src/contexts/PushApiContext'; import {useToaster} from 'src/contexts/ToasterContext'; import {TimeoutHelper} from 'src/helpers/TimeoutHelper'; import useSubscriptions from 'src/hooks/channel/useSubscriptions'; +import {usePushApiMode} from 'src/hooks/pushapi/usePushApiMode'; import { Channel, + selectChannelPendingSubscription, selectIsLoadingSubscriptions, selectSubscriptions, + setChannelPendingSubscription, } from 'src/redux/channelSlice'; import {ToasterOptions} from '../indicators/Toaster'; +export type SubscriptionStatusProps = { + channel: Channel; + selectChannelForSettings: (channel: Channel) => void; +}; + +export type ChannelPendingSubscriptionType = { + channel_id: string | null; + status: boolean; +}; + const SubscriptionStatus = ({ selectChannelForSettings, channel: channelData, -}: { - channel: Channel; - selectChannelForSettings: (channel: Channel) => void; -}) => { +}: SubscriptionStatusProps) => { + const dispatch = useDispatch(); const [processing, setProcessing] = useState(false); + const subscriptions = useSelector(selectSubscriptions); + const channelPendingSubscription = useSelector( + selectChannelPendingSubscription, + ); const isLoadingSubscriptions = useSelector(selectIsLoadingSubscriptions); + const {subscribe} = useSubscriptions(); const {toastRef} = useToaster(); + const {showUnlockProfileModal, isUnlockProfileModalOpen} = usePushApi(); + const {isGreenStatus} = usePushApiMode(); const channelSettings = channelData.channel_settings; const channel = channelData.channel; @@ -41,7 +60,51 @@ const SubscriptionStatus = ({ return subscriptions?.[channel] !== undefined; }, [subscriptions, channel]); + useEffect(() => { + // If the channel is pending subscription and the unlock profile modal is not open + if ( + channelPendingSubscription.status && + channelPendingSubscription.channel_id === channelData.channel_id && + !isUnlockProfileModalOpen + ) { + // If the user is not guest, then subscribe/unsubscribe the channel + if (isGreenStatus) { + dispatch( + setChannelPendingSubscription({ + channel_id: null, + status: false, + }), + ); + handleChangeSubStatus(); + } else { + dispatch( + setChannelPendingSubscription({ + channel_id: null, + status: false, + }), + ); + } + } + }, [isGreenStatus]); + + const checkIfGuest = async () => { + console.log({isGreenStatus}); + // If the user is a guest, show the unlock profile modal + if (!isGreenStatus) { + dispatch( + setChannelPendingSubscription({ + channel_id: channelData.channel_id, + status: true, + }), + ); + showUnlockProfileModal(); + return true; + } + return false; + }; + const handleChangeSubStatus = async () => { + if (await checkIfGuest()) return; setProcessing(true); if (subscribed === true) { selectChannelForSettings(channelData); diff --git a/src/components/ui/ChannelsDisplayer.tsx b/src/components/ui/ChannelsDisplayer.tsx index f567dbf73..3847a4e4e 100644 --- a/src/components/ui/ChannelsDisplayer.tsx +++ b/src/components/ui/ChannelsDisplayer.tsx @@ -136,7 +136,12 @@ const ChannelsDisplayer = () => { onEndReached={loadMore} onEndReachedThreshold={0.8} renderItem={({item: channel}) => ( - + )} ListFooterComponent={() => { return isLoading || isLoadingMore ? ( diff --git a/src/contexts/PushApiContext.tsx b/src/contexts/PushApiContext.tsx index 5336bc90b..f73d0e504 100644 --- a/src/contexts/PushApiContext.tsx +++ b/src/contexts/PushApiContext.tsx @@ -36,6 +36,7 @@ type PushApiContextType = { getReadOnlyInstance: (overrideAccount?: string) => Promise; isLoading: boolean; showUnlockProfileModal: () => void; + isUnlockProfileModalOpen: boolean; }; export const PushApiContext = createContext({ @@ -47,6 +48,7 @@ export const PushApiContext = createContext({ getReadOnlyInstance: () => Promise.resolve(), isLoading: true, showUnlockProfileModal: () => {}, + isUnlockProfileModalOpen: false, }); export const usePushApi = () => { @@ -77,6 +79,7 @@ const PushApiContextProvider = ({children}: {children: React.ReactNode}) => { ModalComponent: UnlockProfileModal, hideModal: hideUnlockProfileModal, showModal: showUnlockProfileModal, + isModalOpen: isUnlockProfileModalOpen, } = useModalBlur(); const { @@ -234,6 +237,7 @@ const PushApiContextProvider = ({children}: {children: React.ReactNode}) => { userInfo, isLoading, showUnlockProfileModal, + isUnlockProfileModalOpen, }}> { const [loaded, setLoaded] = useState(false); @@ -81,6 +82,7 @@ const useSubscriptions = () => { ? // @ts-ignore baseClass.getMinimalUserSetting(pushSettings) : null; + const pgpPrivateKey = userPushSDKInstance?.decryptedPgpPvtKey; await channels.subscribeV2({ channelAddress: channelCaip, signer: signer, @@ -89,6 +91,7 @@ const useSubscriptions = () => { settings: settings, onSuccess: onSuccess, onError: onError, + pgpPrivateKey, }); } catch (e) { console.error(e); @@ -120,6 +123,7 @@ const useSubscriptions = () => { const {account, signer} = await getPushSigner(); if (isSignerEnabled && signer && account) { try { + const pgpPrivateKey = userPushSDKInstance?.decryptedPgpPvtKey; await channels.unsubscribeV2({ channelAddress: channelCaip, signer, @@ -127,6 +131,7 @@ const useSubscriptions = () => { env: envConfig.ENV as ENV, onSuccess: onSuccess, onError: onError, + pgpPrivateKey, }); } catch (e) { console.error(e); @@ -139,6 +144,7 @@ const useSubscriptions = () => { const refreshSubscriptions = async (force = false) => { try { if (loaded && !force) return; + console.log('Refreshing subscriptions'); dispatch(setLoadingSubscriptions(true)); const response = await userPushSDKInstance?.notification.subscriptions({ account: caip10ToWallet(userPushSDKInstance?.account), diff --git a/src/redux/channelSlice.ts b/src/redux/channelSlice.ts index 745819661..537d20ee7 100644 --- a/src/redux/channelSlice.ts +++ b/src/redux/channelSlice.ts @@ -1,4 +1,5 @@ import {PayloadAction, createSlice} from '@reduxjs/toolkit'; +import {ChannelPendingSubscriptionType} from 'src/components/buttons/SubscriptionStatus'; import { ChannelSetting, UserSetting, @@ -30,12 +31,17 @@ type ChannelSliceData = { channels: Array; subscriptions: SubscriptionsMapping; isLoadingSubscriptions: boolean; + channelPendingSubscription: ChannelPendingSubscriptionType; }; const initialState: ChannelSliceData = { channels: [], subscriptions: {}, isLoadingSubscriptions: false, + channelPendingSubscription: { + channel_id: null, + status: false, + }, }; const channelSlice = createSlice({ @@ -66,6 +72,12 @@ const channelSlice = createSlice({ setLoadingSubscriptions: (state, action: PayloadAction) => { state.isLoadingSubscriptions = action.payload; }, + setChannelPendingSubscription: ( + state, + action: PayloadAction, + ) => { + state.channelPendingSubscription = action.payload; + }, }, }); @@ -77,6 +89,7 @@ export const { removeChannelSubscription, setSubscriptions, setLoadingSubscriptions, + setChannelPendingSubscription, } = channelSlice.actions; type ReturnTypeChannel = {channel: ChannelSliceData}; @@ -88,5 +101,7 @@ export const selectSubscriptions = (state: ReturnTypeChannel) => state.channel.subscriptions; export const selectIsLoadingSubscriptions = (state: ReturnTypeChannel) => state.channel.isLoadingSubscriptions; +export const selectChannelPendingSubscription = (state: ReturnTypeChannel) => + state.channel.channelPendingSubscription; export default channelSlice.reducer; diff --git a/yarn.lock b/yarn.lock index d1f5fcd9d..6f0abf316 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4807,9 +4807,9 @@ __metadata: languageName: node linkType: hard -"@pushprotocol/restapi@npm:^1.7.28": - version: 1.7.28 - resolution: "@pushprotocol/restapi@npm:1.7.28" +"@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" @@ -4832,7 +4832,7 @@ __metadata: peerDependenciesMeta: ethers: optional: true - checksum: 10/63fe891a9adb7a9bb911d059bbcb633d432eeed2c71ec1c1ab54a91895ca59f205fd46b450f9f50890d9b1e74120180b0ac45b869a3bdf0c7077445235c45d65 + checksum: 10/327dbd17b7b3f34d56e5326502358196fcf9320a2fcdc0b73efa60e959c90f7c9359f1ea5d53387dbc8dc0551bbd9f60685dffd688ef6215558fe9939f2aee8a languageName: node linkType: hard @@ -16861,7 +16861,7 @@ __metadata: "@gorhom/bottom-sheet": "npm:^4" "@metamask/eth-sig-util": "npm:^5.0.0" "@notifee/react-native": "npm:^9.1.8" - "@pushprotocol/restapi": "npm:^1.7.28" + "@pushprotocol/restapi": "npm:^1.7.30" "@pushprotocol/socket": "npm:latest" "@react-native-async-storage/async-storage": "npm:1.17.11" "@react-native-clipboard/clipboard": "npm:^1.11.1"