Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve proposal details visualization #260

Merged
merged 7 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/assets/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@
"yes": "Yes",
"no": "No",
"description": "Description",
"summary": "Summary",
"i understand": "I understand",
"my address": "My address",
"copy address": "Copy address",
"change network": "Change network",
"generating": "Generating...",
"balance": "Balance",
"go back": "Go back"
"go back": "Go back",
}
3 changes: 2 additions & 1 deletion src/assets/locales/en/messages/common.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"signer": "Signer",
"user": "User",
"update params": "Update params"
"update params": "Update params",
"update module params": "Update {{ module }} module params",
}
90 changes: 90 additions & 0 deletions src/components/InlineProfile/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { useNavigation } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import TypographyContentLoaders from 'components/ContentLoaders/Typography';
import CopiableAddress from 'components/CopiableAddress';
import ProfileImage from 'components/ProfileImage';
import Spacer from 'components/Spacer';
import Typography from 'components/Typography';
import { makeStyle } from 'config/theme';
import useGetProfile from 'hooks/profile/useGetProfile';
import { getProfileDisplayName } from 'lib/ProfileUtils';
import { RootNavigatorParamList } from 'navigation/RootNavigator';
import ROUTES from 'navigation/routes';
import React from 'react';
import { View } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { DesmosProfile } from 'types/desmos';

interface InlineProfileProps {
/**
* Address of the profile to display.
*/
readonly address: string;
/**
* Optional prefetched profile.
*/
readonly profile?: DesmosProfile;
}

/**
* Components that displays an user profile and if clicked opens the
* profile screen.
*/
const InlineProfile: React.FC<InlineProfileProps> = ({ address, profile }) => {
const styles = useStyles();
const [toDisplayProfile, setToDisplayProfile] = React.useState(profile);
const [profileLoading, setProfileLoading] = React.useState(profile === undefined);

const navigation = useNavigation<StackNavigationProp<RootNavigatorParamList>>();
const getProfile = useGetProfile();
const showProfile = React.useCallback(() => {
navigation.navigate(ROUTES.PROFILE, {
visitingProfile: address,
});
}, [address, navigation]);

React.useEffect(() => {
(async () => {
if (profile === undefined) {
setProfileLoading(true);
const fetchedProfile = await getProfile(address);
if (fetchedProfile.isOk()) {
setToDisplayProfile(fetchedProfile.value);
}
setProfileLoading(false);
}
})();
}, [address, getProfile, profile]);

if (toDisplayProfile === undefined && profileLoading === false) {
return (
<View style={styles.root}>
<CopiableAddress address={address} />
</View>
);
}

return (
<TouchableOpacity onPress={showProfile}>
<View style={styles.root}>
<ProfileImage profile={toDisplayProfile} loading={profileLoading} size={32} />
<Spacer paddingLeft={8} />
{profileLoading ? (
<TypographyContentLoaders.Regular16 width={180} />
) : (
<Typography.Regular16>{getProfileDisplayName(toDisplayProfile!)}</Typography.Regular16>
)}
</View>
</TouchableOpacity>
);
};

export default InlineProfile;

const useStyles = makeStyle(() => ({
root: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
},
}));
4 changes: 4 additions & 0 deletions src/components/Messages/MessageDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { EncodeObject } from '@cosmjs/proto-signing';
import React from 'react';
import { messageDetailsComponents } from './components';
import MsgUnknownComponents from './MsgUnknown';
import MsgUpdateParamsDetails from './common/MsgUpdateParamsDetails';

export type MessageDetailsProps = {
/**
Expand All @@ -18,6 +19,9 @@ export type MessageDetailsProps = {

const MessageDetails: React.FC<MessageDetailsProps> = ({ message, toBroadcastMessage }) =>
React.useMemo(() => {
if (message.typeUrl.indexOf('MsgUpdateParams') > 0) {
return <MsgUpdateParamsDetails message={message} toBroadcastMessage={toBroadcastMessage} />;
}
const DetailsComponent = messageDetailsComponents[message.typeUrl] || MsgUnknownComponents;
return <DetailsComponent message={message} toBroadcastMessage={toBroadcastMessage} />;
}, [message, toBroadcastMessage]);
Expand Down
52 changes: 52 additions & 0 deletions src/components/Messages/common/MsgUpdateParamsDetails/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { EncodeObject } from '@desmoslabs/desmjs';
import { MessageDetailsComponent } from 'components/Messages/BaseMessage';
import BaseMessageDetails, {
MessageDetailsField,
} from 'components/Messages/BaseMessage/BaseMessageDetails';
import Typography from 'components/Typography';
import { formatCoin } from 'lib/FormatUtils';
import React from 'react';
import { useTranslation } from 'react-i18next';

const MsgUpdateParamsDetails: MessageDetailsComponent<EncodeObject> = ({ message }) => {
const { t } = useTranslation('messages.common');
const moduleName = React.useMemo(() => {
const [, name] = message.typeUrl.split('.');
return `${name[0].toUpperCase()}${name.substring(1)}`;
}, [message.typeUrl]);

const fields = React.useMemo<MessageDetailsField[]>(() => {
const result: MessageDetailsField[] = [];
Object.keys(message.value.params).forEach((key) => {
const objectValue = message.value.params[key];
let serializedValue: string;

if (typeof objectValue === 'object') {
// Special case for the coin object.
if (typeof objectValue.denom === 'string' && typeof objectValue.amount === 'string') {
serializedValue = formatCoin(objectValue);
} else {
serializedValue = JSON.stringify(objectValue, undefined, 4);
}
} else {
serializedValue = objectValue.toString();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work on boolean values as well? I saw in your preview Gif that the send_enabled parameter was rendered as a white square box for some reason.

Also, would it be better to check if the objectValue is either undefined or null and render it as null in both cases?

Copy link
Author

@manu0466 manu0466 Nov 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RiccardoM I have handled the case where objectValue is undefined or null.
About the boolean there was an error in the conversion of the /desmos.tokenfactory.v1.MsgUpdateParams.
I have update it to matche the proto definition.

}

result.push({
label: key,
value: serializedValue,
});
});
return result;
}, [message.value]);

return (
<BaseMessageDetails message={message} fields={fields}>
<Typography.Regular14>
{t('update module params', { module: moduleName })}
</Typography.Regular14>
</BaseMessageDetails>
);
};

export default MsgUpdateParamsDetails;
5 changes: 0 additions & 5 deletions src/components/Messages/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
MsgExecTypeUrl,
MsgSoftwareUpgradeTypeUrl,
MsgTransferTypeUrl,
MsgUpdateStakingModuleParamsTypeUrl,
SoftwareUpgradeProposalTypeUrl,
} from 'types/cosmos';
import MsgExecDetails from 'components/Messages/authz/MsgExecDetails';
Expand All @@ -26,7 +25,6 @@ import MsgDepositDetails from 'components/Messages/gov/MsgDepositDetails';
import MsgTransferDetails from 'components/Messages/ibc/MsgTransferDetails';
import MsgCreateValidatorDetails from 'components/Messages/staking/MsgCreateValidatorDetails';
import MsgEditValidatorDetails from 'components/Messages/staking/MsgEditValidatorDetails';
import MsgUpdateStakingModuleParams from 'components/Messages/staking/MsgUpdateParams';
import SoftwareUpgradeProposal from 'components/Messages/upgrade/v1beta1/SoftwareUpgradeProposal';
import MsgSoftwareUpgrade from 'components/Messages/upgrade/v1beta1/MsgSoftwareUpgrade';
import MsgMovePostDetails from 'components/Messages/posts/MsgMovePostDetails';
Expand Down Expand Up @@ -100,7 +98,6 @@ import MsgCreateDenomDetails from './tokenfactory/MsgCreateDenomDetails';
import MsgMintDetails from './tokenfactory/MsgMintDetails';
import MsgBurnDetails from './tokenfactory/MsgBurnDetails';
import MsgSetDenomMetadataDetails from './tokenfactory/MsgSetDenomMetadataDetails';
import MsgUpdateParamsDetails from './tokenfactory/MsgUpdateParamsDetails';

export const messageDetailsComponents: Record<string, MessageDetailsComponent<any>> = {
// x/authz
Expand Down Expand Up @@ -137,7 +134,6 @@ export const messageDetailsComponents: Record<string, MessageDetailsComponent<an
[Staking.v1beta1.MsgUndelegateTypeUrl]: MsgUndelegateComponentDetails,
[Staking.v1beta1.MsgCreateValidatorTypeUrl]: MsgCreateValidatorDetails,
[Staking.v1beta1.MsgEditValidatorTypeUrl]: MsgEditValidatorDetails,
[MsgUpdateStakingModuleParamsTypeUrl]: MsgUpdateStakingModuleParams,

// x/feegrant
[Feegrant.v1beta1.MsgGrantAllowanceTypeUrl]: MsgGrantAllowanceComponentDetails,
Expand Down Expand Up @@ -212,7 +208,6 @@ export const messageDetailsComponents: Record<string, MessageDetailsComponent<an
[TokenFactory.v1.MsgMintTypeUrl]: MsgMintDetails,
[TokenFactory.v1.MsgBurnTypeUrl]: MsgBurnDetails,
[TokenFactory.v1.MsgSetDenomMetadataTypeUrl]: MsgSetDenomMetadataDetails,
[TokenFactory.v1.MsgUpdateParamsTypeUrl]: MsgUpdateParamsDetails,

// x/upgrade
[SoftwareUpgradeProposalTypeUrl]: SoftwareUpgradeProposal,
Expand Down
66 changes: 0 additions & 66 deletions src/components/Messages/staking/MsgUpdateParams/index.tsx

This file was deleted.

This file was deleted.

Loading
Loading