diff --git a/src/custom/components/Settings/SettingsMod.tsx b/src/custom/components/Settings/SettingsMod.tsx index 314abcbea..a912a7e05 100644 --- a/src/custom/components/Settings/SettingsMod.tsx +++ b/src/custom/components/Settings/SettingsMod.tsx @@ -10,8 +10,8 @@ import { Text } from 'rebass' import styled, { ThemeContext } from 'styled-components/macro' import { useOnClickOutside } from 'hooks/useOnClickOutside' import { useModalOpen, useToggleSettingsMenu } from 'state/application/hooks' +import { useExpertModeManager, useRecipientToggleManager } from 'state/user/hooks' import { ApplicationModal } from 'state/application/reducer' -import { /* useClientSideRouter, */ useExpertModeManager } from 'state/user/hooks' import { TYPE } from 'theme' import { ButtonError } from 'components/Button' import { AutoColumn } from 'components/Column' @@ -127,6 +127,7 @@ export default function SettingsTab({ className, placeholderSlippage, SettingsBu const theme = useContext(ThemeContext) const [expertMode, toggleExpertMode] = useExpertModeManager() + const [recipientToggleVisible, toggleRecipientVisibility] = useRecipientToggleManager() // const [clientSideRouter, setClientSideRouter] = useClientSideRouter() @@ -244,15 +245,38 @@ export default function SettingsTab({ className, placeholderSlippage, SettingsBu expertMode ? () => { toggleExpertMode() + toggleRecipientVisibility(false) setShowConfirmation(false) } : () => { toggle() + toggleRecipientVisibility(true) setShowConfirmation(true) } } /> + + + + + Toggle Recipient + + Allows you to choose a destination address for the swap other than the connected one. + } + /> + + (expertMode ? null : toggleRecipientVisibility())} + className={expertMode ? 'disabled' : ''} + /> + )} diff --git a/src/custom/components/Toggle/index.tsx b/src/custom/components/Toggle/index.tsx index 5028727c7..a0f790a43 100644 --- a/src/custom/components/Toggle/index.tsx +++ b/src/custom/components/Toggle/index.tsx @@ -16,9 +16,17 @@ const WrappedToggle = styled(ToggleUni)` border: 2px solid ${({ theme }) => theme.text1}; } } - .disabled { - background: ${({ theme }) => theme.primary1}; - color: ${({ theme }) => theme.text2}; + + &.disabled { + cursor: default; + + ${ToggleElement} { + opacity: 0.5; + + &:hover { + border: 2px solid transparent; + } + } } ` diff --git a/src/custom/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx b/src/custom/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx index 69ce8f653..c12049e01 100644 --- a/src/custom/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx +++ b/src/custom/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx @@ -280,8 +280,8 @@ SwapModalHeaderProps) { )} {recipient !== null ? ( - - + + Output will be sent to{' '} {isAddress(recipient) ? shortenAddress(recipient) : recipient} diff --git a/src/custom/pages/Swap/SwapMod.tsx b/src/custom/pages/Swap/SwapMod.tsx index d82775052..618fbd71e 100644 --- a/src/custom/pages/Swap/SwapMod.tsx +++ b/src/custom/pages/Swap/SwapMod.tsx @@ -63,7 +63,7 @@ import { useHighFeeWarning, useUnknownImpactWarning, } from 'state/swap/hooks' -import { useExpertModeManager } from 'state/user/hooks' +import { useExpertModeManager, useRecipientToggleManager } from 'state/user/hooks' import { /* HideSmall, */ LinkStyledButton, TYPE, ButtonSize } from 'theme' // import { computeFiatValuePriceImpact } from 'utils/computeFiatValuePriceImpact' // import { getTradeVersion } from 'utils/getTradeVersion' @@ -169,6 +169,8 @@ export default function Swap({ // for expert mode const [isExpertMode] = useExpertModeManager() + const [recipientToggleVisible] = useRecipientToggleManager() + // get version from the url // const toggledVersion = useToggledVersion() @@ -527,7 +529,7 @@ export default function Swap({ - + */} {/* GP ARROW SWITCHER */} - + - {recipient === null && !showWrap && isExpertMode ? ( + {recipient === null && !showWrap && (isExpertMode || recipientToggleVisible) ? ( onChangeRecipient('')}> + Add a send (optional) diff --git a/src/state/user/actions.ts b/src/state/user/actions.ts index 9cb92e0dc..44a4a513a 100644 --- a/src/state/user/actions.ts +++ b/src/state/user/actions.ts @@ -23,6 +23,8 @@ export const updateOptimismAlphaAcknowledged = createAction<{ optimismAlphaAckno ) export const updateUserDarkMode = createAction<{ userDarkMode: boolean }>('user/updateUserDarkMode') export const updateUserExpertMode = createAction<{ userExpertMode: boolean }>('user/updateUserExpertMode') +export const updateRecipientToggleVisible = + createAction<{ recipientToggleVisible: boolean }>('user/recipientToggleVisible') export const updateUserLocale = createAction<{ userLocale: SupportedLocale }>('user/updateUserLocale') export const updateUserClientSideRouter = createAction<{ userClientSideRouter: boolean }>( 'user/updateUserClientSideRouter' diff --git a/src/state/user/hooks.tsx b/src/state/user/hooks.tsx index 15c44fc04..d9a3d0089 100644 --- a/src/state/user/hooks.tsx +++ b/src/state/user/hooks.tsx @@ -21,6 +21,7 @@ import { SerializedToken, updateArbitrumAlphaAcknowledged, updateHideClosedPositions, + updateRecipientToggleVisible, updateOptimismAlphaAcknowledged, updateUserClientSideRouter, updateUserDarkMode, @@ -29,6 +30,7 @@ import { updateUserLocale, updateUserSlippageTolerance, } from './actions' +import { useSwapActionHandlers } from '../swap/hooks' export function serializeToken(token: Token): SerializedToken { return { @@ -106,6 +108,29 @@ export function useExpertModeManager(): [boolean, () => void] { return [expertMode, toggleSetExpertMode] } +export function useIsRecipientToggleVisible(): boolean { + return useAppSelector((state) => state.user.recipientToggleVisible) +} + +export function useRecipientToggleManager(): [boolean, (value?: boolean) => void] { + const dispatch = useAppDispatch() + const recipientToggleVisible = useIsRecipientToggleVisible() + const { onChangeRecipient } = useSwapActionHandlers() + + const toggleRecipientVisibility = useCallback( + (value?: boolean) => { + const newRecipientToggleVisibilityValue = value ?? !recipientToggleVisible + dispatch(updateRecipientToggleVisible({ recipientToggleVisible: newRecipientToggleVisibilityValue })) + if (!newRecipientToggleVisibilityValue) { + onChangeRecipient(null) + } + }, + [recipientToggleVisible, dispatch, onChangeRecipient] + ) + + return [recipientToggleVisible, toggleRecipientVisibility] +} + export function useClientSideRouter(): [boolean, (userClientSideRouter: boolean) => void] { const dispatch = useAppDispatch() diff --git a/src/state/user/reducer.ts b/src/state/user/reducer.ts index 0dcd00fbc..d327b7c50 100644 --- a/src/state/user/reducer.ts +++ b/src/state/user/reducer.ts @@ -10,17 +10,18 @@ import { removeSerializedToken, SerializedPair, SerializedToken, - updateArbitrumAlphaAcknowledged, - updateHideClosedPositions, updateMatchesDarkMode, updateOptimismAlphaAcknowledged, updateUserClientSideRouter, updateUserDarkMode, updateUserDeadline, updateUserExpertMode, - updateUserLocale, updateUserSlippageTolerance, toggleURLWarning, + updateHideClosedPositions, + updateUserLocale, + updateArbitrumAlphaAcknowledged, + updateRecipientToggleVisible, } from './actions' const currentTimestamp = () => new Date().getTime() @@ -40,6 +41,8 @@ export interface UserState { userExpertMode: boolean + recipientToggleVisible: boolean + userClientSideRouter: boolean // whether routes should be calculated with the client side router only // hides closed (inactive) positions across the app @@ -79,6 +82,7 @@ export const initialState: UserState = { optimismAlphaAcknowledged: false, userDarkMode: null, userExpertMode: false, + recipientToggleVisible: false, userLocale: null, userClientSideRouter: false, userHideClosedPositions: false, @@ -144,6 +148,10 @@ export default createReducer(initialState, (builder) => state.userExpertMode = action.payload.userExpertMode state.timestamp = currentTimestamp() }) + .addCase(updateRecipientToggleVisible, (state, action) => { + state.recipientToggleVisible = action.payload.recipientToggleVisible + state.timestamp = currentTimestamp() + }) .addCase(updateUserLocale, (state, action) => { state.userLocale = action.payload.userLocale state.timestamp = currentTimestamp()