-
Notifications
You must be signed in to change notification settings - Fork 102
Release / 5.21.0 #4492
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
base: production
Are you sure you want to change the base?
Release / 5.21.0 #4492
Changes from all commits
24028e4
6f890d1
ba54699
f2815c0
c4edb73
793677f
7a210e8
10512c9
9b66209
7caa948
7f0718f
2620ae5
8304c16
77dcdee
a3983d4
7c01b76
cda66c2
e4c8c86
98f2a2d
0521ec9
04ac972
93e8756
3bcc64b
c88a2ba
363fd1a
518d413
3e36e06
0f6f823
b6737b4
7be0a9f
6f1f128
f34bf8f
58521e3
903c036
c9589bf
06867ea
faff1fd
d8f8045
61cd91b
aa4e2d6
cc34a5a
c69f1ec
724577c
14d779c
3e89ccc
af40022
7f455f3
e06aa33
765602d
cc9fd6c
d336551
ba75dbe
5add0bc
06b241a
81ff5f1
870808b
8eb977d
532f485
dd2a9a5
e08b367
847f5e0
e4bb22a
91a1898
fd1b653
e54552e
bdc5696
32a3867
7c42963
9d1443d
6574bc0
dd5c321
633f11d
52f54e1
b6d8406
4de2b8e
cf55b30
ab958b2
568133c
23f5a99
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| import { Typography, Button, Grid, Stack, Link } from '@mui/material'; | ||
| import { styled } from '@mui/material/styles'; | ||
| import { useModal } from '../modals/ModalContext'; | ||
| import { useEffect } from 'react'; | ||
| import CardanoCardImage from './CardanoCardImage.png'; | ||
| import LocalStorageApi from '../../../api/localStorage/index'; | ||
| import { useStrings } from '../../common/hooks/useStrings'; | ||
| import { CARDANO_CARD_URL } from '../../common/constants'; | ||
| import { useYoroiRemoteConfig } from '../../common/hooks/useYoroiRemoteConfig'; | ||
|
|
||
| let hasProcessedThisSession = false; | ||
|
|
||
| export const CardanoCardDialog = () => { | ||
| const strings = useStrings(); | ||
| const { openModal, closeModal } = useModal(); | ||
| const { data } = useYoroiRemoteConfig(); | ||
|
|
||
| useEffect(() => { | ||
| const checkModalState = async () => { | ||
| const localStorage = new LocalStorageApi(); | ||
| const appOpenedCount = await localStorage.getAppOpenedCount(); | ||
|
|
||
| if (!data?.popups?.cardanoCardAnnouncement?.display || hasProcessedThisSession) return; | ||
|
|
||
| // Mark as processed to prevent re-execution on data refetches and component remounts | ||
| hasProcessedThisSession = true; | ||
| if (appOpenedCount === undefined || appOpenedCount === null) { | ||
| localStorage.setAppOpenedCount('1'); | ||
| } else { | ||
| localStorage.setAppOpenedCount(String(Number(appOpenedCount) + 1)); | ||
| } | ||
|
|
||
| if (!appOpenedCount || appOpenedCount === '4') { | ||
| openModal({ | ||
| title: strings.cardanoCardTitle, | ||
| height: '550px', | ||
| width: '612px', | ||
| content: ( | ||
| <CardanoCardContent | ||
| onClose={() => { | ||
| closeModal(); | ||
| }} | ||
| /> | ||
| ), | ||
| modalId: 'cardanoCard', | ||
| onClose: () => { | ||
| closeModal(); | ||
| }, | ||
| }); | ||
| } | ||
| }; | ||
|
|
||
| checkModalState(); | ||
| }, [data]); | ||
|
|
||
| return null; | ||
| }; | ||
|
|
||
| const CardanoCardContent = ({ onClose }) => { | ||
| const strings = useStrings(); | ||
| return ( | ||
| <Stack> | ||
| <Stack direction="column" alignItems="center" justifyContent="center" pb="24px"> | ||
| <Stack my={48}> | ||
| <img src={CardanoCardImage} alt="Cardano Card Illustration" /> | ||
| </Stack> | ||
|
|
||
| <Typography variant="h5" color="ds.text_gray_medium" fontWeight={500} mb="8px"> | ||
| {strings.cardanoCardSubtitle} | ||
| </Typography> | ||
| <Typography variant="body1" color="ds.text_gray_medium" textAlign="center" mx="24px" sx={{ whiteSpace: 'pre' }}> | ||
| {strings.cardanoCard} | ||
| </Typography> | ||
| </Stack> | ||
|
|
||
| <Grid justifyContent="space-between" direction="column" style={{ marginTop: 18 }}> | ||
| <Link href={CARDANO_CARD_URL} target="_blank" rel="noopener noreferrer" onClick={onClose}> | ||
| <CustomButton variant="contained" color="primary"> | ||
| {strings.cardanoCardGetTheCard} | ||
| </CustomButton> | ||
| </Link> | ||
| </Grid> | ||
| </Stack> | ||
| ); | ||
| }; | ||
|
|
||
| const CustomButton = styled(Button)(() => ({ | ||
| width: '100%', | ||
| fontSize: '16px', | ||
| lineHeight: '22px', | ||
| })); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -158,16 +158,17 @@ function formatDate(dateString: string, locale: string): string { | |
| } | ||
|
|
||
| function getCurrentThawIndex(schedule: Schedule): number { | ||
| const redeemableIndex = schedule.thaws.findIndex(thaw => thaw.status === 'redeemable'); | ||
| const redeemableIndex = schedule.thaws.findIndex(thaw => thaw.status === 'redeemable' || thaw.status === 'failed'); | ||
| if (redeemableIndex >= 0) return redeemableIndex; | ||
| const upcomingIndex = schedule.thaws.findIndex(thaw => thaw.status === 'upcoming'); | ||
| const upcomingIndex = schedule.thaws.findIndex(thaw => thaw.status === 'upcoming' || thaw.status === 'failed'); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant failed status check in getCurrentThawIndexLow Severity The |
||
| if (upcomingIndex >= 0) return upcomingIndex; | ||
| return 0; | ||
| } | ||
|
|
||
| type ThawStatus = 'redeemable' | 'confirmed' | 'upcoming'; | ||
| type ThawStatus = 'redeemable' | 'confirmed' | 'upcoming' | 'failed'; | ||
|
|
||
| function getThawStatusType(status: string): ThawStatus { | ||
| if (status === 'failed') return 'failed'; | ||
| if (status === 'redeemable') return 'redeemable'; | ||
| if (status === 'confirmed') return 'confirmed'; | ||
| return 'upcoming'; | ||
|
|
@@ -202,6 +203,8 @@ function getStatusMessage(status: ThawStatus, strings: ReturnType<typeof useStri | |
| return strings.redeemable; | ||
| case 'confirmed': | ||
| return strings.redeemed; | ||
| case 'failed': | ||
| return strings.failed; | ||
| default: | ||
| return strings.notAvailable; | ||
| } | ||
|
|
@@ -238,6 +241,7 @@ function ScheduleCard({ schedule }: { schedule: Schedule }) { | |
| const isCurrent = index === currentThawIndex; | ||
| const isPast = index < currentThawIndex; | ||
| const isLast = index === totalThaws - 1; | ||
| const isFailed = thaw.status === 'failed'; | ||
|
|
||
| return ( | ||
| <Box key={index} sx={{ flex: 1, position: 'relative' }}> | ||
|
|
@@ -251,15 +255,30 @@ function ScheduleCard({ schedule }: { schedule: Schedule }) { | |
| display: 'flex', | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| backgroundColor: isPast ? 'ds.primary_300' : isCurrent ? 'ds.primary_500' : 'ds.gray_200', | ||
| backgroundColor: isFailed | ||
| ? 'ds.gray_200' | ||
| : isPast | ||
| ? 'ds.primary_300' | ||
| : isCurrent | ||
| ? 'ds.primary_500' | ||
| : 'ds.gray_200', | ||
| color: isPast || isCurrent ? 'ds.white_static' : 'ds.text_gray_min', | ||
| fontSize: '12px', | ||
| fontWeight: 500, | ||
| zIndex: 1, | ||
| flexShrink: 0, | ||
| }} | ||
| > | ||
| {isPast ? ( | ||
| {isFailed ? ( | ||
| <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 16 16" fill="none"> | ||
| <path | ||
| fill-rule="evenodd" | ||
| clip-rule="evenodd" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistent SVG attribute naming conventionLow Severity The SVG path uses hyphenated attributes |
||
| d="M4.29289 4.29289C4.68342 3.90237 5.31658 3.90237 5.70711 4.29289L8 6.58579L10.2929 4.29289C10.6834 3.90237 11.3166 3.90237 11.7071 4.29289C12.0976 4.68342 12.0976 5.31658 11.7071 5.70711L9.41421 8L11.7071 10.2929C12.0976 10.6834 12.0976 11.3166 11.7071 11.7071C11.3166 12.0976 10.6834 12.0976 10.2929 11.7071L8 9.41421L5.70711 11.7071C5.31658 12.0976 4.68342 12.0976 4.29289 11.7071C3.90237 11.3166 3.90237 10.6834 4.29289 10.2929L6.58579 8L4.29289 5.70711C3.90237 5.31658 3.90237 4.68342 4.29289 4.29289Z" | ||
| fill="#FF0000" | ||
| /> | ||
| </svg> | ||
| ) : isPast ? ( | ||
| <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}> | ||
| <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 16 16" fill="none"> | ||
| <path | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| import Dialog from '../../../../components/widgets/Dialog'; | ||
| import { Typography, Box, Button } from '@mui/material'; | ||
| import { useEffect, useState, useRef } from 'react'; | ||
| import { getCollateralUtxos, getRedemptionTransaction } from '../../../../api/ada/midnight'; | ||
| import { getRedemptionUtxos, getRedemptionTransaction } from '../../../../api/ada/midnight'; | ||
| import { useStrings } from '../common/hooks/useStrings'; | ||
| import LoadingSpinner from '../../../../components/widgets/LoadingSpinner'; | ||
| import { formatNumberExactly } from '../../../../api/ada/midnightRedemption'; | ||
|
|
@@ -23,7 +23,7 @@ export default function Redeem(props: { | |
| const abort = useRef(false); | ||
|
|
||
| const updateCollateralUtxos = async (reorgTxId?: string) => { | ||
| const result = await getCollateralUtxos(props.wallet); | ||
| const result = await getRedemptionUtxos(props.wallet); | ||
| setGetCollateralUtxosResult(result); | ||
| if (result.state === 'exist') { | ||
| // we just submitted the re-org tx, wait for it to be confirmed | ||
|
|
@@ -44,8 +44,8 @@ export default function Redeem(props: { | |
| props.address, | ||
| props.endpoint, | ||
| result.fundingUtxoAddr, | ||
| result.collateralUtxos, | ||
| [result.fundingUtxo] | ||
| [], | ||
| result.fundingUtxos | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dead code after midnight API refactoringMedium Severity The Additional Locations (1) |
||
| ); | ||
| if (abort.current) { | ||
| return; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing cleanup for async operations in useEffect
Medium Severity
The
useEffectruns an async function that performs localStorage operations and potentially callsopenModal, but lacks a cleanup function to handle component unmount. If the component unmounts ordatachanges while the async operation is in progress, it will continue executing and attempt to callopenModaland update the module-levelhasProcessedThisSessionvariable after unmount, potentially causing memory leaks and unexpected modal behavior.