Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const MultiDelegationStakingPopup = (): JSX.Element => {
name: 'AnalyticsEventNames.Staking.STAKING_MULTI_DELEGATION_POPUP'
});
}, []);
const { walletActivities } = useWalletActivities({ sendAnalytics });
const { walletActivities, walletActivitiesStatus } = useWalletActivities({ sendAnalytics });
const { fiatCurrency } = useCurrencyStore();
const { executeWithPassword } = useWalletManager();
const isLoadingNetworkInfo = useWalletStore(networkInfoStatusSelector);
Expand Down Expand Up @@ -125,6 +125,7 @@ export const MultiDelegationStakingPopup = (): JSX.Element => {
walletStoreNetworkInfo: networkInfo,
walletStoreBlockchainProvider: blockchainProvider,
walletStoreWalletActivities: walletActivities,
walletStoreWalletActivitiesStatus: walletActivitiesStatus,
// TODO: LW-7575 make compactNumber reusable and not pass it here.
compactNumber: compactNumberWithUnit,
walletAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,15 @@ const buildGetActivityDetail =
walletInfo
} = get();

set({ fetchingActivityInfo: true });

if (activityDetail.type === 'rewards') {
const { activity, status, type } = activityDetail;
const poolInfos = await getPoolInfos(
activity.rewards.map(({ poolId }) => poolId),
stakePoolProvider
);
set({ fetchingActivityInfo: false });

return {
activity: {
Expand Down Expand Up @@ -128,7 +131,6 @@ const buildGetActivityDetail =
const { activity: tx, status, type, direction } = activityDetail;
const walletAssets = await firstValueFrom(wallet.assetInfo$);
const protocolParameters = await firstValueFrom(wallet.protocolParameters$);
set({ fetchingActivityInfo: true });

// Assets
const assetIds = getTransactionAssetsId(tx.body.outputs);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { OutsideHandlesProvider, Staking } from '@lace/staking';
import React, { useCallback } from 'react';
import React, { useCallback, useEffect } from 'react';
import {
useAnalyticsContext,
useBackgroundServiceAPIContext,
Expand All @@ -17,6 +17,9 @@ import {
MULTIDELEGATION_FIRST_VISIT_LS_KEY,
MULTIDELEGATION_FIRST_VISIT_SINCE_PORTFOLIO_PERSISTENCE_LS_KEY
} from '@utils/constants';
import { ActivityDetail } from '../../activity';
import { Drawer, DrawerNavigation } from '@lace/common';
import { useTranslation } from 'react-i18next';

export const MultiDelegationStaking = (): JSX.Element => {
const { theme } = useTheme();
Expand All @@ -38,7 +41,9 @@ export const MultiDelegationStaking = (): JSX.Element => {
fetchNetworkInfo,
networkInfo,
blockchainProvider,
currentChain
currentChain,
activityDetail,
resetActivityState
} = useWalletStore((state) => ({
getKeyAgentType: state.getKeyAgentType,
inMemoryWallet: state.inMemoryWallet,
Expand All @@ -50,8 +55,11 @@ export const MultiDelegationStaking = (): JSX.Element => {
fetchNetworkInfo: state.fetchNetworkInfo,
blockchainProvider: state.blockchainProvider,
walletInfo: state.walletInfo,
currentChain: state.currentChain
currentChain: state.currentChain,
activityDetail: state.activityDetail,
resetActivityState: state.resetActivityState
}));
const { t } = useTranslation();
const sendAnalytics = useCallback(() => {
// TODO implement analytics for the new flow
const analytics = {
Expand All @@ -66,7 +74,7 @@ export const MultiDelegationStaking = (): JSX.Element => {
name: 'AnalyticsEventNames.Staking.STAKING_MULTI_DELEGATION_BROWSER'
});
}, []);
const { walletActivities } = useWalletActivities({ sendAnalytics });
const { walletActivities, walletActivitiesStatus } = useWalletActivities({ sendAnalytics });
const { fiatCurrency } = useCurrencyStore();
const { executeWithPassword } = useWalletManager();
const [multidelegationFirstVisit, { updateLocalStorage: setMultidelegationFirstVisit }] = useLocalStorage(
Expand All @@ -80,6 +88,11 @@ export const MultiDelegationStaking = (): JSX.Element => {
const walletAddress = walletInfo.addresses?.[0].address?.toString();
const analytics = useAnalyticsContext();

// Reset current transaction details and close drawer if network (blockchainProvider) has changed
useEffect(() => {
resetActivityState();
}, [resetActivityState, blockchainProvider]);

return (
<OutsideHandlesProvider
{...{
Expand All @@ -106,6 +119,7 @@ export const MultiDelegationStaking = (): JSX.Element => {
walletStoreNetworkInfo: networkInfo,
walletStoreBlockchainProvider: blockchainProvider,
walletStoreWalletActivities: walletActivities,
walletStoreWalletActivitiesStatus: walletActivitiesStatus,
// TODO: LW-7575 make compactNumber reusable and not pass it here.
compactNumber: compactNumberWithUnit,
multidelegationFirstVisit,
Expand All @@ -118,6 +132,27 @@ export const MultiDelegationStaking = (): JSX.Element => {
}}
>
<Staking currentChain={currentChain} theme={theme.name} />
{/*
Note: Mounting the browser-extension activity details drawer here is just a workaround.
Ideally, the Drawer/Activity detail should be fully managed within the "Staking" component,
which contains the respective "Activity" section, but that would require moving/refactoring
large chunks of code, ATM tightly coupled with browser-extension state/logic,
to a separate package (core perhaps?).
*/}
<Drawer
visible={!!activityDetail}
onClose={resetActivityState}
navigation={
<DrawerNavigation
title={t('transactions.detail.title')}
onCloseIconClick={() => {
resetActivityState();
}}
/>
}
>
{activityDetail && priceResult && <ActivityDetail price={priceResult} />}
</Drawer>
</OutsideHandlesProvider>
);
};
24 changes: 23 additions & 1 deletion packages/staking/src/features/activity/Activity.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,23 @@
export const Activity = () => <>Activity placeholder</>;
import { StateStatus, useOutsideHandles } from 'features/outside-handles-provider';
import { getGroupedRewardsActivities } from './helpers/getGroupedRewardsHistory';
import { NoStakingActivity } from './NoStakingActivity';
import { RewardsHistory } from './RewardsHistory';

export const Activity = () => {
const { walletStoreWalletActivitiesStatus: walletActivitiesStatus, walletStoreWalletActivities: walletActivities } =
useOutsideHandles();
const groupedRewardsActivities = getGroupedRewardsActivities(walletActivities);

return (
<>
{walletActivitiesStatus === StateStatus.LOADED && groupedRewardsActivities.length === 0 ? (
<NoStakingActivity />
) : (
<RewardsHistory
walletActivitiesStatus={walletActivitiesStatus}
groupedRewardsActivities={groupedRewardsActivities}
/>
)}
</>
);
};
13 changes: 13 additions & 0 deletions packages/staking/src/features/activity/NoStakingActivity.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { style } from '@lace/ui';
import { theme } from 'features/theme';

export const sadFaceIcon = style({
height: theme.spacing.$112,
width: theme.spacing.$112,
});

export const noActivityText = style({
color: theme.colors.$activityNoActivityTextColor,
fontSize: theme.fontSizes.$14,
fontWeight: theme.fontWeights.$semibold,
});
17 changes: 17 additions & 0 deletions packages/staking/src/features/activity/NoStakingActivity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import SadFaceIcon from '@lace/core/src/ui/assets/icons/sad-face.component.svg';
import { Flex } from '@lace/ui';
import { Typography } from 'antd';
import { useTranslation } from 'react-i18next';
import * as styles from './NoStakingActivity.css';

export const NoStakingActivity = () => {
const { t } = useTranslation();
return (
<Flex h="$fill" flexDirection="column" alignItems="center" justifyContent="center" gap="$8">
<SadFaceIcon className={styles.sadFaceIcon} />
<Typography.Text className={styles.noActivityText}>
{t('activity.rewardsHistory.noStakingActivityYet')}
</Typography.Text>
</Flex>
);
};
29 changes: 29 additions & 0 deletions packages/staking/src/features/activity/RewardsHistory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { AssetActivityListProps, GroupedAssetActivityList } from '@lace/core';
import { Box, Text } from '@lace/ui';
import { Skeleton } from 'antd';
import { StateStatus } from 'features/outside-handles-provider';
import { useTranslation } from 'react-i18next';

const LACE_APP_ID = 'lace-app';

type RewardsHistoryProps = {
groupedRewardsActivities: AssetActivityListProps[];
walletActivitiesStatus: StateStatus;
};
export const RewardsHistory = ({ groupedRewardsActivities, walletActivitiesStatus }: RewardsHistoryProps) => {
const { t } = useTranslation();

return (
<>
<Box mb="$16">
<Text.SubHeading>{t('activity.rewardsHistory.title')}</Text.SubHeading>
</Box>
<Skeleton loading={walletActivitiesStatus !== StateStatus.LOADED}>
<GroupedAssetActivityList
lists={groupedRewardsActivities}
infiniteScrollProps={{ scrollableTarget: LACE_APP_ID }}
/>
</Skeleton>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { AssetActivityListProps } from '@lace/core';

export const getGroupedRewardsActivities = (walletActivities: AssetActivityListProps[]) =>
walletActivities
.map((group) => ({
...group,
items: group.items.filter((item) => item.type === 'rewards'),
}))
.filter((group) => group.items.length > 0);
2 changes: 2 additions & 0 deletions packages/staking/src/features/i18n/translations/en.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Translations } from '../types';

export const en: Translations = {
'activity.rewardsHistory.noStakingActivityYet': 'No staking activity yet.',
'activity.rewardsHistory.title': 'History',
'browsePools.stakePoolTableBrowser.addPool': 'Add pool',
'browsePools.stakePoolTableBrowser.disabledTooltip': 'Maximum number of pools selected',
'browsePools.stakePoolTableBrowser.emptyMessage': 'No results matching your search',
Expand Down
6 changes: 6 additions & 0 deletions packages/staking/src/features/i18n/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ type KeysStructure = {
close: '';
};
};
activity: {
rewardsHistory: {
title: '';
noStakingActivityYet: '';
};
};
browsePools: {
stakePoolTableBrowser: {
searchInputPlaceholder: '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export type OutsideHandlesContextValue = {
walletStoreGetKeyAgentType: () => string;
walletStoreInMemoryWallet: Wallet.ObservableWallet;
walletStoreWalletActivities: AssetActivityListProps[];
walletStoreWalletActivitiesStatus: StateStatus;
walletStoreWalletUICardanoCoin: Wallet.CoinId;
walletManagerExecuteWithPassword: <T>(
password: string,
Expand Down
2 changes: 1 addition & 1 deletion packages/staking/src/features/staking/StakingView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const StakingView = () => {
</Box>
<Navigation>
{(activePage) => (
<Box mt="$40">
<Box mt="$40" h="$fill">
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This makes the "Activity" page (and any other "Staking" tab) container fill the available vertical space, which in turns allows me to align vertically to the center the "No staking activity yet" component. TBH I find this a bit fragile as the code lacks any clear connection and therefore it's easy to break. Do you perhaps have some nicer solution on your mind @mrcnk ?

{activePage === Page.overview && <Overview />}
{activePage === Page.browsePools && <BrowsePools />}
{activePage === Page.activity && <Activity />}
Expand Down
3 changes: 3 additions & 0 deletions packages/staking/src/features/theme/colors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { darkColorScheme, laceGradient, lightColorScheme } from '@lace/ui';

export const colorsContract = {
$activityNoActivityTextColor: '',
$bannerBellIconColor: '',
$bannerInfoIconColor: '',
$delegationCardInfoLabelColor: '',
Expand Down Expand Up @@ -29,6 +30,7 @@ export const colorsContract = {
};

export const lightThemeColors: typeof colorsContract = {
$activityNoActivityTextColor: lightColorScheme.$primary_dark_grey,
$bannerBellIconColor: lightColorScheme.$primary_accent_purple,
$bannerInfoIconColor: lightColorScheme.$primary_accent_purple,
$delegationCardInfoLabelColor: lightColorScheme.$primary_dark_grey,
Expand Down Expand Up @@ -57,6 +59,7 @@ export const lightThemeColors: typeof colorsContract = {
};

export const darkThemeColors: typeof colorsContract = {
$activityNoActivityTextColor: darkColorScheme.$primary_light_grey,
$bannerBellIconColor: darkColorScheme.$primary_accent_purple,
$bannerInfoIconColor: darkColorScheme.$primary_accent_purple,
$delegationCardInfoLabelColor: darkColorScheme.$primary_light_grey,
Expand Down