Commit a1b37766 authored by Jordan Frankfurt's avatar Jordan Frankfurt Committed by GitHub

feat: vertical LP (#7000)

* Re-organize add liquidity page

* fix title alignment

* Update styles

* Update logic for disable/enable input on creation

* lint and clean up a couple small things

* lint and clean up a couple small things

* Tweak UI

* clean up code

* add back range selector

* remove inline styles

---------
Co-authored-by: default avatarCallil Capuozzo <callil@uniswap.org>
parent dc2225a2
This diff is collapsed.
...@@ -25,9 +25,7 @@ const pulse = (color: string) => keyframes` ...@@ -25,9 +25,7 @@ const pulse = (color: string) => keyframes`
` `
const InputRow = styled.div` const InputRow = styled.div`
display: grid; display: flex;
grid-template-columns: 30px 1fr 30px;
` `
const SmallButton = styled(ButtonGray)` const SmallButton = styled(ButtonGray)`
...@@ -43,18 +41,17 @@ const FocusedOutlineCard = styled(OutlineCard)<{ active?: boolean; pulsing?: boo ...@@ -43,18 +41,17 @@ const FocusedOutlineCard = styled(OutlineCard)<{ active?: boolean; pulsing?: boo
const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>` const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>`
background-color: transparent; background-color: transparent;
text-align: center;
width: 100%;
font-weight: 500; font-weight: 500;
padding: 0 10px; text-align: left;
width: 100%;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToSmall` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToSmall`
font-size: 16px; font-size: 16px;
`}; `};
`
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToExtraSmall` const InputColumn = styled(AutoColumn)`
font-size: 12px; width: 100%;
`};
` `
const InputTitle = styled(ThemedText.DeprecatedSmall)` const InputTitle = styled(ThemedText.DeprecatedSmall)`
...@@ -142,20 +139,11 @@ const StepCounter = ({ ...@@ -142,20 +139,11 @@ const StepCounter = ({
return ( return (
<FocusedOutlineCard pulsing={pulsing} active={active} onFocus={handleOnFocus} onBlur={handleOnBlur} width={width}> <FocusedOutlineCard pulsing={pulsing} active={active} onFocus={handleOnFocus} onBlur={handleOnBlur} width={width}>
<AutoColumn gap="6px"> <InputRow>
<InputTitle fontSize={12} textAlign="center"> <InputColumn justify="flex-start">
{title} <InputTitle fontSize={12} textAlign="center">
</InputTitle> {title}
</InputTitle>
<InputRow>
{!locked && (
<SmallButton data-testid="decrement-price-range" onClick={handleDecrement} disabled={decrementDisabled}>
<ButtonLabel disabled={decrementDisabled} fontSize="12px">
<Minus size={18} />
</ButtonLabel>
</SmallButton>
)}
<StyledInput <StyledInput
className="rate-input-0" className="rate-input-0"
value={localValue} value={localValue}
...@@ -165,7 +153,14 @@ const StepCounter = ({ ...@@ -165,7 +153,14 @@ const StepCounter = ({
setLocalValue(val) setLocalValue(val)
}} }}
/> />
<InputTitle fontSize={12} textAlign="left">
<Trans>
{tokenB} per {tokenA}
</Trans>
</InputTitle>
</InputColumn>
<AutoColumn gap="8px">
{!locked && ( {!locked && (
<SmallButton data-testid="increment-price-range" onClick={handleIncrement} disabled={incrementDisabled}> <SmallButton data-testid="increment-price-range" onClick={handleIncrement} disabled={incrementDisabled}>
<ButtonLabel disabled={incrementDisabled} fontSize="12px"> <ButtonLabel disabled={incrementDisabled} fontSize="12px">
...@@ -173,14 +168,15 @@ const StepCounter = ({ ...@@ -173,14 +168,15 @@ const StepCounter = ({
</ButtonLabel> </ButtonLabel>
</SmallButton> </SmallButton>
)} )}
</InputRow> {!locked && (
<SmallButton data-testid="decrement-price-range" onClick={handleDecrement} disabled={decrementDisabled}>
<InputTitle fontSize={12} textAlign="center"> <ButtonLabel disabled={decrementDisabled} fontSize="12px">
<Trans> <Minus size={18} />
{tokenB} per {tokenA} </ButtonLabel>
</Trans> </SmallButton>
</InputTitle> )}
</AutoColumn> </AutoColumn>
</InputRow>
</FocusedOutlineCard> </FocusedOutlineCard>
) )
} }
......
...@@ -12,7 +12,7 @@ const Wrapper = styled.div<{ count: number }>` ...@@ -12,7 +12,7 @@ const Wrapper = styled.div<{ count: number }>`
grid-gap: 6px; grid-gap: 6px;
position: absolute; position: absolute;
top: -75px; top: -32px;
right: 0; right: 0;
` `
......
...@@ -6,7 +6,7 @@ import Loader from 'components/Icons/LoadingSpinner' ...@@ -6,7 +6,7 @@ import Loader from 'components/Icons/LoadingSpinner'
import { format } from 'd3' import { format } from 'd3'
import { useColor } from 'hooks/useColor' import { useColor } from 'hooks/useColor'
import { saturate } from 'polished' import { saturate } from 'polished'
import React, { ReactNode, useCallback, useMemo } from 'react' import { ReactNode, useCallback, useMemo } from 'react'
import { BarChart2, CloudOff, Inbox } from 'react-feather' import { BarChart2, CloudOff, Inbox } from 'react-feather'
import { batch } from 'react-redux' import { batch } from 'react-redux'
import { Bound } from 'state/mint/v3/actions' import { Bound } from 'state/mint/v3/actions'
...@@ -46,7 +46,8 @@ const ZOOM_LEVELS: Record<FeeAmount, ZoomLevels> = { ...@@ -46,7 +46,8 @@ const ZOOM_LEVELS: Record<FeeAmount, ZoomLevels> = {
const ChartWrapper = styled.div` const ChartWrapper = styled.div`
position: relative; position: relative;
width: 100%;
max-height: 200px;
justify-content: center; justify-content: center;
align-content: center; align-content: center;
` `
...@@ -180,7 +181,7 @@ export default function LiquidityChartRangeInput({ ...@@ -180,7 +181,7 @@ export default function LiquidityChartRangeInput({
<ChartWrapper> <ChartWrapper>
<Chart <Chart
data={{ series: formattedData, current: price }} data={{ series: formattedData, current: price }}
dimensions={{ width: 400, height: 200 }} dimensions={{ width: 560, height: 200 }}
margins={{ top: 10, right: 2, bottom: 20, left: 0 }} margins={{ top: 10, right: 2, bottom: 20, left: 0 }}
styles={{ styles={{
area: { area: {
......
...@@ -3,7 +3,7 @@ import { Percent } from '@uniswap/sdk-core' ...@@ -3,7 +3,7 @@ import { Percent } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { ArrowLeft } from 'react-feather' import { ArrowLeft } from 'react-feather'
import { Link as HistoryLink, useLocation } from 'react-router-dom' import { Link, useLocation } from 'react-router-dom'
import { Box } from 'rebass' import { Box } from 'rebass'
import { useAppDispatch } from 'state/hooks' import { useAppDispatch } from 'state/hooks'
import { resetMintState } from 'state/mint/actions' import { resetMintState } from 'state/mint/actions'
...@@ -12,7 +12,7 @@ import styled, { useTheme } from 'styled-components/macro' ...@@ -12,7 +12,7 @@ import styled, { useTheme } from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
import { flexRowNoWrap } from 'theme/styles' import { flexRowNoWrap } from 'theme/styles'
import Row, { RowBetween } from '../Row' import { RowBetween } from '../Row'
import SettingsTab from '../Settings' import SettingsTab from '../Settings'
const Tabs = styled.div` const Tabs = styled.div`
...@@ -22,7 +22,7 @@ const Tabs = styled.div` ...@@ -22,7 +22,7 @@ const Tabs = styled.div`
justify-content: space-evenly; justify-content: space-evenly;
` `
const StyledHistoryLink = styled(HistoryLink)<{ flex?: string }>` const StyledLink = styled(Link)<{ flex?: string }>`
flex: ${({ flex }) => flex ?? 'none'}; flex: ${({ flex }) => flex ?? 'none'};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
...@@ -31,9 +31,10 @@ const StyledHistoryLink = styled(HistoryLink)<{ flex?: string }>` ...@@ -31,9 +31,10 @@ const StyledHistoryLink = styled(HistoryLink)<{ flex?: string }>`
`}; `};
` `
const ActiveText = styled.div` const FindPoolTabsText = styled(ThemedText.SubHeaderLarge)`
font-weight: 500; position: absolute;
font-size: 20px; left: 50%;
transform: translateX(-50%);
` `
const StyledArrowLeft = styled(ArrowLeft)` const StyledArrowLeft = styled(ArrowLeft)`
...@@ -44,17 +45,22 @@ export function FindPoolTabs({ origin }: { origin: string }) { ...@@ -44,17 +45,22 @@ export function FindPoolTabs({ origin }: { origin: string }) {
return ( return (
<Tabs> <Tabs>
<RowBetween style={{ padding: '1rem 1rem 0 1rem', position: 'relative' }}> <RowBetween style={{ padding: '1rem 1rem 0 1rem', position: 'relative' }}>
<HistoryLink to={origin}> <Link to={origin}>
<StyledArrowLeft /> <StyledArrowLeft />
</HistoryLink> </Link>
<ActiveText style={{ position: 'absolute', left: '50%', transform: 'translateX(-50%)' }}> <FindPoolTabsText>
<Trans>Import V2 Pool</Trans> <Trans>Import V2 Pool</Trans>
</ActiveText> </FindPoolTabsText>
</RowBetween> </RowBetween>
</Tabs> </Tabs>
) )
} }
const AddRemoveTitleText = styled(ThemedText.SubHeaderLarge)`
flex: 1;
margin: auto;
`
export function AddRemoveTabs({ export function AddRemoveTabs({
adding, adding,
creating, creating,
...@@ -83,7 +89,7 @@ export function AddRemoveTabs({ ...@@ -83,7 +89,7 @@ export function AddRemoveTabs({
return ( return (
<Tabs> <Tabs>
<RowBetween style={{ padding: '1rem 1rem 0 1rem' }}> <RowBetween style={{ padding: '1rem 1rem 0 1rem' }}>
<StyledHistoryLink <StyledLink
to={poolLink} to={poolLink}
onClick={() => { onClick={() => {
if (adding) { if (adding) {
...@@ -95,12 +101,8 @@ export function AddRemoveTabs({ ...@@ -95,12 +101,8 @@ export function AddRemoveTabs({
flex={children ? '1' : undefined} flex={children ? '1' : undefined}
> >
<StyledArrowLeft stroke={theme.textSecondary} /> <StyledArrowLeft stroke={theme.textSecondary} />
</StyledHistoryLink> </StyledLink>
<ThemedText.DeprecatedMediumHeader <AddRemoveTitleText textAlign={children ? 'start' : 'center'}>
fontWeight={500}
fontSize={20}
style={{ flex: '1', margin: 'auto', textAlign: children ? 'start' : 'center' }}
>
{creating ? ( {creating ? (
<Trans>Create a pair</Trans> <Trans>Create a pair</Trans>
) : adding ? ( ) : adding ? (
...@@ -108,23 +110,10 @@ export function AddRemoveTabs({ ...@@ -108,23 +110,10 @@ export function AddRemoveTabs({
) : ( ) : (
<Trans>Remove Liquidity</Trans> <Trans>Remove Liquidity</Trans>
)} )}
</ThemedText.DeprecatedMediumHeader> </AddRemoveTitleText>
<Box style={{ marginRight: '.5rem' }}>{children}</Box> {children && <Box style={{ marginRight: '.5rem' }}>{children}</Box>}
<SettingsTab autoSlippage={autoSlippage} chainId={chainId} /> <SettingsTab autoSlippage={autoSlippage} chainId={chainId} />
</RowBetween> </RowBetween>
</Tabs> </Tabs>
) )
} }
export function CreateProposalTabs() {
return (
<Tabs>
<Row style={{ padding: '1rem 1rem 0 1rem' }}>
<HistoryLink to="/vote">
<StyledArrowLeft />
</HistoryLink>
<ActiveText style={{ marginLeft: 'auto', marginRight: 'auto' }}>Create Proposal</ActiveText>
</Row>
</Tabs>
)
}
...@@ -5,7 +5,7 @@ import styled from 'styled-components/macro' ...@@ -5,7 +5,7 @@ import styled from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
const Button = styled(ButtonOutlined).attrs(() => ({ const Button = styled(ButtonOutlined).attrs(() => ({
padding: '8px', padding: '6px',
$borderRadius: '8px', $borderRadius: '8px',
}))` }))`
color: ${({ theme }) => theme.textPrimary}; color: ${({ theme }) => theme.textPrimary};
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, Price, Token } from '@uniswap/sdk-core' import { Currency, Price, Token } from '@uniswap/sdk-core'
import { AutoColumn } from 'components/Column'
import StepCounter from 'components/InputStepCounter/InputStepCounter' import StepCounter from 'components/InputStepCounter/InputStepCounter'
import { RowBetween } from 'components/Row' import { AutoRow } from 'components/Row'
import { Bound } from 'state/mint/v3/actions' import { Bound } from 'state/mint/v3/actions'
// currencyA is the base token // currencyA is the base token
...@@ -41,37 +40,33 @@ export default function RangeSelector({ ...@@ -41,37 +40,33 @@ export default function RangeSelector({
const rightPrice = isSorted ? priceUpper : priceLower?.invert() const rightPrice = isSorted ? priceUpper : priceLower?.invert()
return ( return (
<AutoColumn gap="md"> <AutoRow gap="md">
<RowBetween> <StepCounter
<StepCounter value={ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER] ? '0' : leftPrice?.toSignificant(8) ?? ''}
value={ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER] ? '0' : leftPrice?.toSignificant(5) ?? ''} onUserInput={onLeftRangeInput}
onUserInput={onLeftRangeInput} decrement={isSorted ? getDecrementLower : getIncrementUpper}
width="48%" increment={isSorted ? getIncrementLower : getDecrementUpper}
decrement={isSorted ? getDecrementLower : getIncrementUpper} decrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]}
increment={isSorted ? getIncrementLower : getDecrementUpper} incrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]}
decrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]} feeAmount={feeAmount}
incrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]} label={leftPrice ? `${currencyB?.symbol}` : '-'}
feeAmount={feeAmount} title={<Trans>Low price</Trans>}
label={leftPrice ? `${currencyB?.symbol}` : '-'} tokenA={currencyA?.symbol}
title={<Trans>Min Price</Trans>} tokenB={currencyB?.symbol}
tokenA={currencyA?.symbol} />
tokenB={currencyB?.symbol} <StepCounter
/> value={ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER] ? '' : rightPrice?.toSignificant(8) ?? ''}
<StepCounter onUserInput={onRightRangeInput}
value={ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER] ? '' : rightPrice?.toSignificant(5) ?? ''} decrement={isSorted ? getDecrementUpper : getIncrementLower}
onUserInput={onRightRangeInput} increment={isSorted ? getIncrementUpper : getDecrementLower}
width="48%" incrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]}
decrement={isSorted ? getDecrementUpper : getIncrementLower} decrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]}
increment={isSorted ? getIncrementUpper : getDecrementLower} feeAmount={feeAmount}
incrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]} label={rightPrice ? `${currencyB?.symbol}` : '-'}
decrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]} tokenA={currencyA?.symbol}
feeAmount={feeAmount} tokenB={currencyB?.symbol}
label={rightPrice ? `${currencyB?.symbol}` : '-'} title={<Trans>High price</Trans>}
tokenA={currencyA?.symbol} />
tokenB={currencyB?.symbol} </AutoRow>
title={<Trans>Max Price</Trans>}
/>
</RowBetween>
</AutoColumn>
) )
} }
This diff is collapsed.
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import CurrencyInputPanel from 'components/CurrencyInputPanel' import CurrencyInputPanel from 'components/CurrencyInputPanel'
import Input from 'components/NumericalInput' import Input from 'components/NumericalInput'
import { BodyWrapper } from 'pages/AppBody'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
export const PageWrapper = styled(BodyWrapper)<{ wide: boolean }>`
max-width: ${({ wide }) => (wide ? '880px' : '480px')};
width: 100%;
padding: ${({ wide }) => (wide ? '10px' : '0')};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
max-width: 480px;
`};
`
export const Wrapper = styled.div` export const Wrapper = styled.div`
position: relative; position: relative;
padding: 26px 16px; padding: 26px 16px;
min-width: 480px;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
min-width: 400px;
`};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToExtraSmall`
min-width: 340px;
`};
` `
export const ScrollablePage = styled.div` export const ScrollablePage = styled.div`
padding: 68px 8px 0px; padding: 20px 8px 0px;
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
max-width: 480px;
margin: 0 auto; margin: 0 auto;
`}; `};
...@@ -67,56 +45,19 @@ export const StyledInput = styled(Input)` ...@@ -67,56 +45,19 @@ export const StyledInput = styled(Input)`
/* two-column layout where DepositAmount is moved at the very end on mobile. */ /* two-column layout where DepositAmount is moved at the very end on mobile. */
export const ResponsiveTwoColumns = styled.div<{ wide: boolean }>` export const ResponsiveTwoColumns = styled.div<{ wide: boolean }>`
display: grid; display: flex;
grid-column-gap: 50px; flex-direction: column;
grid-row-gap: 15px; gap: 20px;
grid-template-columns: ${({ wide }) => (wide ? '1fr 1fr' : '1fr')};
grid-template-rows: max-content;
grid-auto-flow: row;
padding-top: 20px; padding-top: 20px;
border-top: 1px solid ${({ theme }) => theme.backgroundInteractive}; border-top: 1px solid ${({ theme }) => theme.backgroundInteractive};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
grid-template-columns: 1fr;
margin-top: 0; margin-top: 0;
`}; `};
` `
export const RightContainer = styled(AutoColumn)`
grid-row: 1 / 3;
grid-column: 2;
height: fit-content;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
grid-row: 2 / 3;
grid-column: 1;
`};
`
export const StackedContainer = styled.div`
display: grid;
`
export const StackedItem = styled.div<{ zIndex?: number }>`
grid-column: 1;
grid-row: 1;
height: 100%;
z-index: ${({ zIndex }) => zIndex};
`
export const MediumOnly = styled.div` export const MediumOnly = styled.div`
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
display: none; display: none;
`}; `};
` `
export const HideMedium = styled.div`
display: none;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
display: block;
`};
`
import React, { PropsWithChildren } from 'react' import { PropsWithChildren } from 'react'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { Z_INDEX } from 'theme/zIndex' import { Z_INDEX } from 'theme/zIndex'
......
...@@ -12,6 +12,8 @@ import JSBI from 'jsbi' ...@@ -12,6 +12,8 @@ import JSBI from 'jsbi'
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { Wrapper } from 'pages/Pool/styleds' import { Wrapper } from 'pages/Pool/styleds'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import { ArrowLeft } from 'react-feather'
import { Link } from 'react-router-dom'
import { import {
CreateProposalData, CreateProposalData,
ProposalState, ProposalState,
...@@ -24,7 +26,6 @@ import { ...@@ -24,7 +26,6 @@ import {
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ExternalLink, ThemedText } from 'theme' import { ExternalLink, ThemedText } from 'theme'
import { CreateProposalTabs } from '../../components/NavigationTabs'
import { LATEST_GOVERNOR_INDEX } from '../../constants/governance' import { LATEST_GOVERNOR_INDEX } from '../../constants/governance'
import { UNI } from '../../constants/tokens' import { UNI } from '../../constants/tokens'
import AppBody from '../AppBody' import AppBody from '../AppBody'
...@@ -45,6 +46,19 @@ const PageWrapper = styled(AutoColumn)` ...@@ -45,6 +46,19 @@ const PageWrapper = styled(AutoColumn)`
} }
` `
const BackArrow = styled(ArrowLeft)`
cursor: pointer;
color: ${({ theme }) => theme.textPrimary};
`
const Nav = styled(Link)`
align-items: center;
display: flex;
flex-direction: row;
justify-content: flex-start;
margin: 1em 0 0 1em;
text-decoration: none;
`
const CreateProposalButton = ({ const CreateProposalButton = ({
proposalThreshold, proposalThreshold,
hasActiveOrPendingProposal, hasActiveOrPendingProposal,
...@@ -242,7 +256,10 @@ ${bodyValue} ...@@ -242,7 +256,10 @@ ${bodyValue}
<Trace page={InterfacePageName.VOTE_PAGE} shouldLogImpression> <Trace page={InterfacePageName.VOTE_PAGE} shouldLogImpression>
<PageWrapper> <PageWrapper>
<AppBody $maxWidth="800px"> <AppBody $maxWidth="800px">
<CreateProposalTabs /> <Nav to="/vote">
<BackArrow />
<ThemedText.SubHeaderLarge>Create Proposal</ThemedText.SubHeaderLarge>
</Nav>
<CreateProposalWrapper> <CreateProposalWrapper>
<BlueCard> <BlueCard>
<AutoColumn gap="10px"> <AutoColumn gap="10px">
......
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