Skip to content

Commit

Permalink
chore: state management for user and admin settings (#1271)
Browse files Browse the repository at this point in the history
  • Loading branch information
kalashshah authored Oct 10, 2023
1 parent 6573420 commit 23c378e
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 86 deletions.
18 changes: 3 additions & 15 deletions src/components/ChannelDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default function ChannelDetails({ isChannelExpired, setIsChannelExpired,
canVerify,
aliasDetails: { isAliasVerified, aliasAddrFromContract },
} = useSelector((state) => state.admin);
const { channelSettings } = useSelector((state) => state.channels);

const { CHANNEL_ACTIVE_STATE, CHANNNEL_DEACTIVATED_STATE } = useSelector((state) => state.channels);
const { processingState } = useSelector((state) => state.channelCreation);
Expand Down Expand Up @@ -142,19 +143,6 @@ export default function ChannelDetails({ isChannelExpired, setIsChannelExpired,
}
}, [account]);

const channelSettings = useMemo(() => {
if (delegatees) {
const delegatee = delegatees.find(({ channel }) => channel === channelAddress);
if (delegatee) {
const { channel_settings } = delegatee;
if (channel_settings !== null) {
return JSON.parse(channel_settings);
}
}
}
return [];
}, [delegatees, channelAddress]);

const removeDelegate = (walletAddress) => {
return epnsCommWriteProvider.removeDelegate(walletAddress);
};
Expand Down Expand Up @@ -335,7 +323,7 @@ export default function ChannelDetails({ isChannelExpired, setIsChannelExpired,
<ChannelInfoList
account={account}
isAddress={false}
items={channelSettings}
items={channelSettings[account]}
isLoading={false}
onClickEmptyListButton={navigateToNotifSettings}
emptyListButtonTitle='Add Setting'
Expand Down Expand Up @@ -624,4 +612,4 @@ const DelegateContainer = styled(Item)`
border-radius: 20px;
border: 1px solid;
border-color: ${(props) => props.theme.default.borderColor};
`;
`;
7 changes: 7 additions & 0 deletions src/components/InitState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
setUserChannelDetails,
} from 'redux/slices/adminSlice';
import { setProcessingState } from 'redux/slices/channelCreationSlice';
import { updateBulkChannelSettings } from 'redux/slices/channelSlice';
import { setPushAdmin } from 'redux/slices/contractSlice';
import { getChannelsSearch, getUserDelegations } from 'services';
import * as PushAPI from '@pushprotocol/restapi';
Expand Down Expand Up @@ -175,6 +176,12 @@ const InitState = () => {
}
const channelInformation = await Promise.all(channelInformationPromise);
dispatch(setDelegatees(channelInformation));
// get channel settings of all the channels
const channelSettings = {};
for (const channel of channelInformation) {
channelSettings[channel.channel] = channel.channel_settings ? JSON.parse(channel.channel_settings) : [];
}
dispatch(updateBulkChannelSettings(channelSettings));
} else {
dispatch(setDelegatees([]));
}
Expand Down
14 changes: 9 additions & 5 deletions src/components/ViewChannelItem.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// React + Web3 Essentials
import React, { useEffect } from 'react';
import React, { useEffect, useMemo } from 'react';

// External Packages
import Skeleton from '@yisheng90/react-loading';
Expand All @@ -11,6 +11,7 @@ import { toast as toaster } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.min.css';
import styled, { css, useTheme } from 'styled-components';
import axios from 'axios';
import { cloneDeep } from 'lodash';

// Internal Compoonents
import * as PushAPI from '@pushprotocol/restapi';
Expand All @@ -19,7 +20,7 @@ import MetaInfoDisplayer from 'components/MetaInfoDisplayer';
import LoaderSpinner, { LOADER_TYPE } from 'components/reusables/loaders/LoaderSpinner';
import { convertAddressToAddrCaip } from 'helpers/CaipHelper';
import useToast from 'hooks/useToast';
import { cacheChannelInfo, updateSubscriptionStatus } from 'redux/slices/channelSlice';
import { cacheChannelInfo } from 'redux/slices/channelSlice';
import { addNewWelcomeNotif, incrementStepIndex } from 'redux/slices/userJourneySlice';
import ChannelTutorial, { isChannelTutorialized } from 'segments/ChannelTutorial';
import NotificationToast from '../primaries/NotificationToast';
Expand Down Expand Up @@ -51,7 +52,7 @@ function ViewChannelItem({ channelObjectProp, loadTeaser, playTeaser }) {
(state) => state.contracts
);
const { canVerify } = useSelector((state) => state.admin);
const { channelsCache, CHANNEL_BLACKLIST, subscriptionStatus } = useSelector((state) => state.channels);
const { channelsCache, CHANNEL_BLACKLIST, subscriptionStatus, userSettings: currentUserSettings } = useSelector((state) => state.channels);
const { account, provider, chainId } = useAccount();

const onCoreNetwork = chainId === appConfig.coreContractChain;
Expand Down Expand Up @@ -186,6 +187,10 @@ function ViewChannelItem({ channelObjectProp, loadTeaser, playTeaser }) {

const generalToast = useToast();

const userSettings = useMemo(() => {
return cloneDeep(currentUserSettings);
}, [currentUserSettings]);

const formatAddress = (addressText) => {
return addressText.length > 40 ? `${shortenText(addressText, 4, 6)}` : addressText;
};
Expand Down Expand Up @@ -853,7 +858,6 @@ function ViewChannelItem({ channelObjectProp, loadTeaser, playTeaser }) {
channelDetail={channelObject}
setLoading={setTxInProgress}
onSuccessOptin={() => {
dispatch(updateSubscriptionStatus({ channelAddress: channelObject.channel, status: true }));
setSubscribed(true);
setSubscriberCount((prevSubscriberCount) => prevSubscriberCount + 1)
}}
Expand Down Expand Up @@ -886,9 +890,9 @@ function ViewChannelItem({ channelObjectProp, loadTeaser, playTeaser }) {
centerOnMobile={true}
channelDetail={channelObject}
setSubscribed={setSubscribed}
userSetting={userSettings[channelObject.channel]}
setSubscriberCount={setSubscriberCount}
onSuccessOptout={() => {
dispatch(updateSubscriptionStatus({ channelAddress: channelObject.channel, status: false }));
setSubscribed(false);
setSubscriberCount((prevSubscriberCount) => prevSubscriberCount - 1)
}}
Expand Down
13 changes: 8 additions & 5 deletions src/components/channel/AddSettingModalContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ const AddSettingModalContent = ({
const settingToEdit = InnerComponentProps?.settingToEdit || undefined;
const [isLoading, setIsLoading] = useState(false);
const [settingName, setSettingName] = useState(settingToEdit ? settingToEdit.description : '');
const [isDefault, setIsDefault] = useState<boolean>(settingToEdit && settingToEdit.isDefaultEnabled === true);
const [isDefault, setIsDefault] = useState<boolean>(
settingToEdit &&
((settingToEdit.type === 1 && settingToEdit.default) || (settingToEdit.type === 2 && settingToEdit.enabled))
);
const [isRange, setIsRange] = useState<boolean>(settingToEdit && settingToEdit.type === 2 ? true : false);
const [lowerLimit, setLowerLimit] = useState<string>(
settingToEdit && settingToEdit.type === 2 ? settingToEdit.lowerLimit.toString() : ''
Expand All @@ -75,7 +78,7 @@ const AddSettingModalContent = ({
settingToEdit && settingToEdit.type === 2 ? settingToEdit.upperLimit.toString() : ''
);
const [defaultValue, setDefaultValue] = useState<string>(
settingToEdit && settingToEdit.type === 2 ? settingToEdit.defaultValue.toString() : ''
settingToEdit && settingToEdit.type === 2 ? settingToEdit.default.toString() : ''
);
const [errorInfo, setErrorInfo] = useState<any>();

Expand Down Expand Up @@ -103,16 +106,16 @@ const AddSettingModalContent = ({
const settingData: ChannelSetting = isRange
? {
type: 2,
defaultValue: Number(defaultValue),
isDefaultEnabled: isDefault,
default: Number(defaultValue),
enabled: isDefault,
description: settingName,
index: index,
lowerLimit: Number(lowerLimit),
upperLimit: Number(upperLimit),
}
: {
type: 1,
isDefaultEnabled: isDefault,
default: isDefault,
description: settingName,
index: index,
};
Expand Down
71 changes: 22 additions & 49 deletions src/components/channel/NotificationSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ethers } from 'ethers';

// External Packages
import 'react-dropdown/style.css';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import 'react-toastify/dist/ReactToastify.min.css';
import { useNavigate } from 'react-router-dom';
import { PiPencilSimpleBold } from 'react-icons/pi';
Expand All @@ -25,6 +25,7 @@ import { appConfig } from 'config';
import useModalBlur, { MODAL_POSITION } from 'hooks/useModalBlur';
import { ChannelSetting } from 'helpers/channel/types';
import { getChannel } from 'services';
import { updateChannelSetting } from 'redux/slices/channelSlice';

// Constants
const CORE_CHAIN_ID = appConfig.coreContractChain;
Expand All @@ -33,6 +34,9 @@ function NotificationSettings() {
const { account, chainId } = useAccount();
const { coreChannelAdmin, delegatees } = useSelector((state: any) => state.admin);
const { epnsWriteProvider } = useSelector((state: any) => state.contracts);
const { channelSettings } = useSelector((state: any) => state.channels);

const dispatch = useDispatch();

const onCoreNetwork = CORE_CHAIN_ID === chainId;
const EDIT_SETTING_FEE = 50;
Expand All @@ -41,7 +45,6 @@ function NotificationSettings() {
const [settings, setSettings] = React.useState<ChannelSetting[]>([]);
const [settingToEdit, setSettingToEdit] = React.useState<ChannelSetting>(undefined);
const [isLoading, setIsLoading] = React.useState(false);
const [currentSettings, setCurrentSettings] = React.useState<ChannelSetting[]>([]);
const [isLoadingSettings, setIsLoadingSettings] = React.useState(true);

const {
Expand Down Expand Up @@ -75,7 +78,7 @@ function NotificationSettings() {
if (isAddSettingModalOpen === false) setSettingToEdit(undefined);
}, [isAddSettingModalOpen]);

React.useEffect(() => {
useEffect(() => {
if (!account) return;
if (!delegatees || !delegatees.length) {
setChannelAddress(account);
Expand All @@ -87,40 +90,11 @@ function NotificationSettings() {
}, [delegatees, account]);

useEffect(() => {
if (delegatees) {
const delegatee = delegatees.find(({ channel }) => channel === channelAddress);
if (delegatee) {
const { channel_settings } = delegatee;
if (channel_settings !== null) {
const parsedData = JSON.parse(channel_settings);
const settings: ChannelSetting[] = parsedData.map((setting: any) => {
if(setting.type === 1) {
return {
type: 1,
isDefaultEnabled: setting.default,
description: setting.description,
index: setting.index,
}
} else {
return {
type: 2,
isDefaultEnabled: setting.enabled === 1 ? true : false,
defaultValue: setting.default,
description: setting.description,
index: setting.index,
lowerLimit: setting.lowerLimit,
upperLimit: setting.upperLimit,
}
}
});
setSettings(settings);
setCurrentSettings(settings);
setIsLoadingSettings(false);
}
}
if (channelAddress && channelSettings[channelAddress]) {
setSettings(channelSettings[channelAddress] || []);
setIsLoadingSettings(false);
}
return null;
}, [delegatees, channelAddress]);
}, [channelAddress, channelSettings]);

// Notification Toast
const notificationToast = useToast(5000);
Expand Down Expand Up @@ -164,11 +138,12 @@ function NotificationSettings() {
settings.forEach((setting) => {
if (_notifSettings !== '') _notifSettings += '+';
if (_notifDescription !== '') _notifDescription += '+';
const isEnabled = setting.isDefaultEnabled ? '1' : '0';
if (setting.type === 1) {
_notifSettings += `${setting.type}-${isEnabled}`;
_notifSettings += `${setting.type}-${setting.default ? '1' : '0'}`;
} else if (setting.type === 2) {
_notifSettings += `${setting.type}-${isEnabled}-${setting.defaultValue}-${setting.lowerLimit}-${setting.upperLimit}`;
_notifSettings += `${setting.type}-${setting.enabled ? '1' : '0'}-${setting.default}-${setting.lowerLimit}-${
setting.upperLimit
}`;
}
_notifDescription += setting.description;
});
Expand All @@ -183,7 +158,7 @@ function NotificationSettings() {

console.log(tx);
await tx.wait();
setCurrentSettings(settings);
dispatch(updateChannelSetting({ channelAddress, settings }));
setIsLoading(false);

notificationToast.showMessageToast({
Expand All @@ -199,7 +174,6 @@ function NotificationSettings() {
});
} catch (err) {
setIsLoading(false);
console.log(err.message);
if (err.code == 'ACTION_REJECTED') {
// EIP-1193 userRejectedRequest error
notificationToast.showMessageToast({
Expand All @@ -226,37 +200,36 @@ function NotificationSettings() {
),
});
console.log('Error --> %o', err);
console.log({ err });
}
}
};

const settingsChanged = useMemo(() => {
if (!settings || !currentSettings) return false;
if (settings.length !== currentSettings.length) return true;
if (!settings || !channelSettings[account]) return false;
if (settings.length !== channelSettings[account].length) return true;
let isUnchanged = true;
for (let i = 0; i < settings.length; i++) {
const setting1 = settings[i];
const setting2 = currentSettings[i];
const setting2 = channelSettings[account][i];
if (setting1.type === 1) {
isUnchanged =
isUnchanged &&
setting1.type === setting2.type &&
setting1.description === setting2.description &&
setting1.isDefaultEnabled === setting2.isDefaultEnabled;
setting1.default === setting2.default;
} else if (setting1.type === 2) {
isUnchanged =
isUnchanged &&
setting1.type === setting2.type &&
setting1.description === setting2.description &&
setting1.defaultValue === setting2.defaultValue &&
setting1.isDefaultEnabled === setting2.isDefaultEnabled &&
setting1.default === setting2.default &&
setting1.enabled === setting2.enabled &&
setting1.lowerLimit === setting2.lowerLimit &&
setting1.upperLimit === setting2.upperLimit;
}
}
return isUnchanged === false;
}, [settings, currentSettings]);
}, [settings, channelSettings[account]]);

return (
<>
Expand Down
Loading

0 comments on commit 23c378e

Please sign in to comment.