Commit 4ec95d09 authored by eddie's avatar eddie Committed by GitHub

fix: URL params for widget (#5943)

* fix: URL params for widget

* fix: remove output token from tokenDetails callsite

* fix: combine props, rename initial state values

* fix: better prop types

* fix: rename prop type
parent fba6cc9e
......@@ -2,7 +2,6 @@ import { Trans } from '@lingui/macro'
import { Trace } from '@uniswap/analytics'
import { InterfacePageName } from '@uniswap/analytics-events'
import { Currency } from '@uniswap/sdk-core'
import { Field } from '@uniswap/widgets'
import { useWeb3React } from '@web3-react/core'
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { AboutSection } from 'components/Tokens/TokenDetails/About'
......@@ -221,9 +220,10 @@ export default function TokenDetails({
<RightPanel onClick={() => isBlockedToken && setOpenTokenSafetyModal(true)}>
<div style={{ pointerEvents: isBlockedToken ? 'none' : 'auto' }}>
<Widget
token={token ?? undefined}
defaultField={Field.OUTPUT}
onTokenChange={navigateToWidgetSelectedToken}
defaultTokens={{
default: token ?? undefined,
}}
onDefaultTokenChange={navigateToWidgetSelectedToken}
onReviewSwapClick={onReviewSwapClick}
/>
</div>
......
......@@ -10,7 +10,6 @@ import { Currency, TradeType } from '@uniswap/sdk-core'
import {
AddEthereumChainParameter,
EMPTY_TOKEN_LIST,
Field,
OnReviewSwapClick,
SwapWidget,
SwapWidgetSkeleton,
......@@ -32,7 +31,7 @@ import { useIsDarkMode } from 'state/user/hooks'
import { computeRealizedPriceImpact } from 'utils/prices'
import { switchChain } from 'utils/switchChain'
import { useSyncWidgetInputs } from './inputs'
import { DefaultTokens, useSyncWidgetInputs } from './inputs'
import { useSyncWidgetSettings } from './settings'
import { DARK_THEME, LIGHT_THEME } from './theme'
import { useSyncWidgetTransactions } from './transactions'
......@@ -46,24 +45,25 @@ function useWidgetTheme() {
}
interface WidgetProps {
token?: Currency
defaultTokens: DefaultTokens
width?: number | string
defaultField: Field
onTokenChange?: (token: Currency) => void
onDefaultTokenChange?: (token: Currency) => void
onReviewSwapClick?: OnReviewSwapClick
}
export default function Widget({
token,
defaultTokens,
width = DEFAULT_WIDGET_WIDTH,
defaultField,
onTokenChange,
onDefaultTokenChange,
onReviewSwapClick,
}: WidgetProps) {
const { connector, provider } = useWeb3React()
const locale = useActiveLocale()
const theme = useWidgetTheme()
const { inputs, tokenSelector } = useSyncWidgetInputs({ token, onTokenChange, defaultField })
const { inputs, tokenSelector } = useSyncWidgetInputs({
defaultTokens,
onDefaultTokenChange,
})
const { settings } = useSyncWidgetSettings()
const { transactions } = useSyncWidgetTransactions()
......@@ -189,7 +189,7 @@ export default function Widget({
)
}
export function WidgetSkeleton() {
export function WidgetSkeleton({ width = DEFAULT_WIDGET_WIDTH }: { width?: number | string }) {
const theme = useWidgetTheme()
return <SwapWidgetSkeleton theme={theme} width={DEFAULT_WIDGET_WIDTH} />
return <SwapWidgetSkeleton theme={theme} width={width} />
}
......@@ -8,10 +8,11 @@ const EMPTY_AMOUNT = ''
type SwapValue = Required<SwapController>['value']
type SwapTokens = Pick<SwapValue, Field.INPUT | Field.OUTPUT> & { default?: Currency }
export type DefaultTokens = Partial<SwapTokens>
function includesDefaultToken(tokens: SwapTokens) {
if (!tokens.default) return true
return tokens[Field.INPUT]?.equals(tokens.default) || tokens[Field.OUTPUT]?.equals(tokens.default)
function missingDefaultToken(tokens: SwapTokens) {
if (!tokens.default) return false
return !tokens[Field.INPUT]?.equals(tokens.default) && !tokens[Field.OUTPUT]?.equals(tokens.default)
}
/**
......@@ -20,30 +21,31 @@ function includesDefaultToken(tokens: SwapTokens) {
* Enforces that token is a part of the returned value.
*/
export function useSyncWidgetInputs({
token,
defaultField,
onTokenChange,
defaultTokens,
onDefaultTokenChange,
}: {
token?: Currency
defaultField: Field
onTokenChange?: (token: Currency) => void
defaultTokens: DefaultTokens
onDefaultTokenChange?: (token: Currency) => void
}) {
const trace = useTrace({ section: InterfaceSectionName.WIDGET })
const [type, setType] = useState<SwapValue['type']>(TradeType.EXACT_INPUT)
const [amount, setAmount] = useState<SwapValue['amount']>(EMPTY_AMOUNT)
const [tokens, setTokens] = useState<SwapTokens>({ [defaultField]: token, default: token })
const [tokens, setTokens] = useState<SwapTokens>(defaultTokens)
useEffect(() => {
setTokens((tokens) => {
const update = { ...tokens, default: token }
if (!includesDefaultToken(update)) {
return { [defaultField]: update.default, default: update.default }
}
return update
})
}, [defaultField, token])
if (!tokens[Field.INPUT] && !tokens[Field.OUTPUT]) {
setTokens((tokens) => {
const update = {
...tokens,
[Field.INPUT]: defaultTokens[Field.INPUT] ?? tokens[Field.INPUT],
[Field.OUTPUT]: defaultTokens[Field.OUTPUT] ?? tokens[Field.OUTPUT] ?? defaultTokens.default,
default: defaultTokens.default,
}
return update
})
}
}, [defaultTokens, tokens])
const onAmountChange = useCallback(
(field: Field, amount: string, origin?: 'max') => {
......@@ -99,12 +101,12 @@ export function useSyncWidgetInputs({
return type
})
if (!includesDefaultToken(update)) {
onTokenChange?.(update[Field.OUTPUT] || selectingToken)
if (missingDefaultToken(update)) {
onDefaultTokenChange?.(update[Field.OUTPUT] ?? selectingToken)
}
setTokens(update)
},
[onTokenChange, selectingField, tokens]
[onDefaultTokenChange, selectingField, tokens]
)
const tokenSelector = (
<CurrencySearchModal
......@@ -120,11 +122,11 @@ export function useSyncWidgetInputs({
() => ({
type,
amount,
// If the default has not yet been handled, preemptively disable the widget by passing no tokens. Effectively,
// If the initial state has not yet been set, preemptively disable the widget by passing no tokens. Effectively,
// this resets the widget - avoiding rendering stale state - because with no tokens the skeleton will be rendered.
...(token && tokens.default?.equals(token) ? tokens : undefined),
...(tokens[Field.INPUT] || tokens[Field.OUTPUT] ? tokens : undefined),
}),
[amount, token, tokens, type]
[amount, tokens, type]
)
const valueHandlers: SwapEventHandlers = useMemo(
() => ({ onAmountChange, onSwitchTokens, onTokenSelectorClick }),
......
......@@ -563,7 +563,13 @@ export default function Swap({ className }: { className?: string }) {
/>
<PageWrapper>
{swapWidgetEnabled ? (
<Widget token={loadedInputCurrency ?? undefined} width="100%" defaultField={Field.INPUT} />
<Widget
defaultTokens={{
[Field.INPUT]: loadedInputCurrency ?? undefined,
[Field.OUTPUT]: loadedOutputCurrency ?? undefined,
}}
width="100%"
/>
) : (
<SwapWrapper className={className} id="swap-page">
<SwapHeader allowedSlippage={allowedSlippage} />
......
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