ci(release): publish latest release

parent d76a660e
IPFS hash of the deployment: IPFS hash of the deployment:
- CIDv0: `QmSy9dnGZafmGNzzJgdfu97LH9P9HsAZNUTtnfMfAJctRr` - CIDv0: `QmR4otTaGReggG5cf37xRt4wh3XkeKPZT5jqT7YbuvQFRQ`
- CIDv1: `bafybeicezboop6s2zwdnk7izhxdkemytiecd3vub4x4564xc2gmio4e3ou` - CIDv1: `bafybeibiqqsv6nojor2kdirpukl4h6f44erjheo2r7fzbq2wvpg5akvd44`
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org). The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org).
...@@ -10,15 +10,15 @@ You can also access the Uniswap Interface from an IPFS gateway. ...@@ -10,15 +10,15 @@ You can also access the Uniswap Interface from an IPFS gateway.
Your Uniswap settings are never remembered across different URLs. Your Uniswap settings are never remembered across different URLs.
IPFS gateways: IPFS gateways:
- https://bafybeicezboop6s2zwdnk7izhxdkemytiecd3vub4x4564xc2gmio4e3ou.ipfs.dweb.link/ - https://bafybeibiqqsv6nojor2kdirpukl4h6f44erjheo2r7fzbq2wvpg5akvd44.ipfs.dweb.link/
- https://bafybeicezboop6s2zwdnk7izhxdkemytiecd3vub4x4564xc2gmio4e3ou.ipfs.cf-ipfs.com/ - https://bafybeibiqqsv6nojor2kdirpukl4h6f44erjheo2r7fzbq2wvpg5akvd44.ipfs.cf-ipfs.com/
- [ipfs://QmSy9dnGZafmGNzzJgdfu97LH9P9HsAZNUTtnfMfAJctRr/](ipfs://QmSy9dnGZafmGNzzJgdfu97LH9P9HsAZNUTtnfMfAJctRr/) - [ipfs://QmR4otTaGReggG5cf37xRt4wh3XkeKPZT5jqT7YbuvQFRQ/](ipfs://QmR4otTaGReggG5cf37xRt4wh3XkeKPZT5jqT7YbuvQFRQ/)
### 5.27.8 (2024-05-16) ## 5.28.0 (2024-05-21)
### Bug Fixes ### Features
* **web:** window.ethereum fallback on mobile [prod] (#8260) 929c164 * **web:** unicon v2 education label (#8339) e861024
web/5.27.8 web/5.28.0
\ No newline at end of file \ No newline at end of file
...@@ -8,21 +8,47 @@ import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' ...@@ -8,21 +8,47 @@ import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks' import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks'
import ENSAvatarIcon from './ENSAvatarIcon' import ENSAvatarIcon from './ENSAvatarIcon'
export default function Identicon({ account, size }: { account?: string; size: number }) { export enum IdenticonType {
LOADING = 'loading',
UNITAG_PROFILE_PICTURE = 'unitagProfilePicture',
ENS_AVATAR = 'ensAvatar',
UNICON = 'unicon',
UNICON_V2 = 'uniconV2',
}
export function useIdenticonType(account?: string) {
const { unitag, loading: unitagLoading } = useUnitagByAddress(account) const { unitag, loading: unitagLoading } = useUnitagByAddress(account)
const { avatar, loading: ensAvatarLoading } = useENSAvatar(account) const { avatar, loading: ensAvatarLoading } = useENSAvatar(account)
const uniconV2Enabled = useFeatureFlag(FeatureFlags.UniconsV2) const uniconV2Enabled = useFeatureFlag(FeatureFlags.UniconsV2)
if (!account) return null if (!account) return undefined
if (unitagLoading || ensAvatarLoading) { if (unitagLoading || ensAvatarLoading) {
return <Loader data-testid="IdenticonLoader" size={size + 'px'} /> return IdenticonType.LOADING
} } else if (unitag?.metadata?.avatar) {
return IdenticonType.UNITAG_PROFILE_PICTURE
if (unitag?.metadata?.avatar) {
return <UniTagProfilePicture account={account} size={size} />
} else if (avatar) { } else if (avatar) {
return <ENSAvatarIcon account={account} size={size} /> return IdenticonType.ENS_AVATAR
} else { } else {
return uniconV2Enabled ? <UniconV2 address={account} size={size} /> : <Unicon address={account} size={size} /> return uniconV2Enabled ? IdenticonType.UNICON_V2 : IdenticonType.UNICON
}
}
export default function Identicon({ account, size }: { account?: string; size: number }) {
const identiconType = useIdenticonType(account)
if (!account) return null
switch (identiconType) {
case IdenticonType.LOADING:
return <Loader data-testid="IdenticonLoader" size={size + 'px'} />
case IdenticonType.UNITAG_PROFILE_PICTURE:
return <UniTagProfilePicture account={account} size={size} />
case IdenticonType.ENS_AVATAR:
return <ENSAvatarIcon account={account} size={size} />
case IdenticonType.UNICON_V2:
return <UniconV2 address={account} size={size} />
case IdenticonType.UNICON:
return <Unicon address={account} size={size} />
default:
return null
} }
} }
...@@ -33,7 +33,7 @@ const StyledClose = styled(X)<{ $padding: number }>` ...@@ -33,7 +33,7 @@ const StyledClose = styled(X)<{ $padding: number }>`
cursor: pointer; cursor: pointer;
} }
` `
const PopupContainer = styled.div<{ padded?: boolean }>` export const PopupContainer = styled.div<{ padded?: boolean }>`
display: inline-block; display: inline-block;
width: 100%; width: 100%;
background-color: ${({ theme }) => theme.surface1}; background-color: ${({ theme }) => theme.surface1};
......
import Column from 'components/Column'
import Identicon, { IdenticonType, useIdenticonType } from 'components/Identicon'
import { PopupContainer } from 'components/Popups/PopupContent'
import Row from 'components/Row'
import { Trans } from 'i18n'
import { useAtom } from 'jotai'
import { atomWithStorage } from 'jotai/utils'
import { X } from 'react-feather'
import styled from 'styled-components'
import { ClickableStyle, ThemedText } from 'theme/components'
import { useAccount } from 'wagmi'
const StyledColumn = styled(Column)`
width: 242px;
`
const StyledClose = styled(X)`
right: 10px;
top: 10px;
stroke: ${({ theme }) => theme.neutral2};
${ClickableStyle}
`
export const showUniconV2InfoPopupAtom = atomWithStorage('showUniconV2InfoPopup', true)
export default function UniconV2InfoPopup() {
const account = useAccount()
const isUniconV2 = useIdenticonType(account.address) === IdenticonType.UNICON_V2
const [showUniconV2InfoPopup, setShowUniconV2InfoPopup] = useAtom(showUniconV2InfoPopupAtom)
return isUniconV2 && account.isConnected && showUniconV2InfoPopup ? (
<PopupContainer>
<Row align="flex-start" justify="space-between" padding="12px" gap="md">
<Identicon account={account.address} size={40} />
<StyledColumn>
<ThemedText.BodyPrimary>
<Trans>Your Unicon got a new look</Trans>
</ThemedText.BodyPrimary>
<ThemedText.BodySecondary>
<Trans>We gave your wallet&apos;s unique Unicon a makeover.</Trans>
</ThemedText.BodySecondary>
</StyledColumn>
<StyledClose onClick={() => setShowUniconV2InfoPopup(false)} />
</Row>
</PopupContainer>
) : null
}
...@@ -3,6 +3,8 @@ import { useActivePopups } from 'state/application/hooks' ...@@ -3,6 +3,8 @@ import { useActivePopups } from 'state/application/hooks'
import styled from 'styled-components' import styled from 'styled-components'
import { Z_INDEX } from 'theme/zIndex' import { Z_INDEX } from 'theme/zIndex'
import UniconV2InfoPopup, { showUniconV2InfoPopupAtom } from 'components/Popups/UniconV2InfoPopup'
import { useAtomValue } from 'jotai/utils'
import { AutoColumn } from '../Column' import { AutoColumn } from '../Column'
import ClaimPopup from './ClaimPopup' import ClaimPopup from './ClaimPopup'
import PopupItem from './PopupItem' import PopupItem from './PopupItem'
...@@ -35,9 +37,16 @@ const MobilePopupInner = styled.div` ...@@ -35,9 +37,16 @@ const MobilePopupInner = styled.div`
const FixedPopupColumn = styled(AutoColumn)<{ const FixedPopupColumn = styled(AutoColumn)<{
drawerOpen: boolean drawerOpen: boolean
showUniconV2InfoPopup: boolean
}>` }>`
position: fixed; position: fixed;
top: ${({ drawerOpen }) => `${64 + (drawerOpen ? -50 : 0)}px`}; top: ${({ drawerOpen, showUniconV2InfoPopup }) => {
if (showUniconV2InfoPopup) {
return drawerOpen ? '80px' : '64px'
} else {
return drawerOpen ? '14px' : '64px'
}
}};
right: 1rem; right: 1rem;
max-width: 348px !important; max-width: 348px !important;
width: 100%; width: 100%;
...@@ -54,18 +63,28 @@ export default function Popups() { ...@@ -54,18 +63,28 @@ export default function Popups() {
// get all popups // get all popups
const activePopups = useActivePopups() const activePopups = useActivePopups()
const showUniconV2InfoPopup = useAtomValue(showUniconV2InfoPopupAtom)
const hasPopups = showUniconV2InfoPopup || activePopups?.length > 0
return ( return (
<> <>
<FixedPopupColumn gap="20px" drawerOpen={isAccountDrawerOpen} data-testid="popups"> <FixedPopupColumn
gap="20px"
drawerOpen={isAccountDrawerOpen}
showUniconV2InfoPopup={showUniconV2InfoPopup}
data-testid="popups"
>
<ClaimPopup /> <ClaimPopup />
<UniconV2InfoPopup />
{activePopups.map((item) => ( {activePopups.map((item) => (
<PopupItem key={item.key} content={item.content} popKey={item.key} removeAfterMs={item.removeAfterMs} /> <PopupItem key={item.key} content={item.content} popKey={item.key} removeAfterMs={item.removeAfterMs} />
))} ))}
</FixedPopupColumn> </FixedPopupColumn>
{activePopups?.length > 0 && ( {hasPopups && (
<MobilePopupWrapper data-testid="popups"> <MobilePopupWrapper data-testid="popups">
<MobilePopupInner> <MobilePopupInner>
<UniconV2InfoPopup />
{activePopups // reverse so new items up front {activePopups // reverse so new items up front
.slice(0) .slice(0)
.reverse() .reverse()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment