mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-07-03 05:29:50 +00:00
271 lines
12 KiB
QML
271 lines
12 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
|
|
import Logos.Theme
|
|
import Logos.Controls
|
|
|
|
import "../components/pool"
|
|
|
|
// Two-column pool-creation flow (Uniswap-style): a vertical step rail on the
|
|
// left and the active step's panel on the right. Step 1 selects the token pair;
|
|
// step 2 enters deposit amounts. Both panels stay alive so the entered values
|
|
// persist when navigating between steps via the rail.
|
|
Item {
|
|
id: root
|
|
|
|
readonly property int pageMargin: 24
|
|
// Breathing room below the navbar. The Trade page fully centers its card
|
|
// (gap = leftover space / 2); this uses a quarter of the leftover so it sits
|
|
// roughly half as far down, scaling with the window, with a sensible floor.
|
|
readonly property int topMargin: Math.max(48, Math.round((scroll.height - content.implicitHeight) / 4))
|
|
readonly property int contentWidth: 760
|
|
|
|
// 0x123456…cdef style truncation for showing token addresses compactly.
|
|
function truncated(addr) {
|
|
const a = (addr || "").trim()
|
|
return a.length > 13 ? (a.substring(0, 6) + "…" + a.substring(a.length - 4)) : a
|
|
}
|
|
|
|
// Numbers only (digits + a single decimal point) for the deposit amounts.
|
|
RegularExpressionValidator {
|
|
id: amountValidator
|
|
regularExpression: /^[0-9]*\.?[0-9]*$/
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
color: Theme.palette.background
|
|
}
|
|
|
|
Flickable {
|
|
id: scroll
|
|
anchors.fill: parent
|
|
clip: true
|
|
contentWidth: width
|
|
contentHeight: Math.max(height, content.implicitHeight + root.topMargin + root.pageMargin)
|
|
flickableDirection: Flickable.VerticalFlick
|
|
|
|
RowLayout {
|
|
id: content
|
|
x: Math.max(root.pageMargin, (scroll.width - width) / 2)
|
|
y: root.topMargin
|
|
width: Math.min(scroll.width - root.pageMargin * 2, root.contentWidth)
|
|
spacing: Theme.spacing.xxlarge
|
|
|
|
PoolStepRail {
|
|
id: rail
|
|
currentStep: 0
|
|
Layout.preferredWidth: 240
|
|
Layout.alignment: Qt.AlignTop
|
|
// Jump back to an already-reached step (e.g. step 1 to re-pick
|
|
// tokens). Selections persist because both panels stay alive.
|
|
onStepClicked: (index) => { rail.currentStep = index }
|
|
}
|
|
|
|
// ── Right: active step's panel (both kept alive to preserve state) ──
|
|
Item {
|
|
id: rightPane
|
|
Layout.fillWidth: true
|
|
Layout.alignment: Qt.AlignTop
|
|
Layout.preferredHeight: rail.currentStep === 0
|
|
? selectCard.implicitHeight
|
|
: depositCard.implicitHeight
|
|
|
|
// ── Step 1: select pair ──────────────────────────────────
|
|
Rectangle {
|
|
id: selectCard
|
|
width: parent.width
|
|
visible: rail.currentStep === 0
|
|
implicitHeight: selectCol.implicitHeight + Theme.spacing.large * 2
|
|
radius: Theme.spacing.radiusLarge
|
|
color: Theme.palette.backgroundSecondary
|
|
border.width: 1
|
|
border.color: Theme.palette.borderSecondary
|
|
|
|
ColumnLayout {
|
|
id: selectCol
|
|
anchors.fill: parent
|
|
anchors.margins: Theme.spacing.large
|
|
spacing: Theme.spacing.medium
|
|
|
|
LogosText {
|
|
text: qsTr("Select pair")
|
|
font.pixelSize: Theme.typography.panelTitleText
|
|
font.weight: Theme.typography.weightBold
|
|
color: Theme.palette.text
|
|
}
|
|
LogosText {
|
|
Layout.fillWidth: true
|
|
text: qsTr("Choose the two tokens for your pool by entering each token's address.")
|
|
wrapMode: Text.WordWrap
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.textSecondary
|
|
}
|
|
|
|
LogosText {
|
|
Layout.topMargin: Theme.spacing.small
|
|
text: qsTr("Token A address")
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.textSecondary
|
|
}
|
|
LogosTextField {
|
|
id: tokenAField
|
|
Layout.fillWidth: true
|
|
placeholderText: "0x…"
|
|
}
|
|
|
|
LogosText {
|
|
Layout.topMargin: Theme.spacing.small
|
|
text: qsTr("Token B address")
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.textSecondary
|
|
}
|
|
LogosTextField {
|
|
id: tokenBField
|
|
Layout.fillWidth: true
|
|
placeholderText: "0x…"
|
|
}
|
|
|
|
LogosButton {
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: Theme.spacing.medium
|
|
height: 44
|
|
text: qsTr("Continue")
|
|
enabled: tokenAField.text.trim().length > 0
|
|
&& tokenBField.text.trim().length > 0
|
|
&& tokenAField.text.trim() !== tokenBField.text.trim()
|
|
onClicked: rail.currentStep = 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// ── Step 2: deposit amounts ──────────────────────────────
|
|
Rectangle {
|
|
id: depositCard
|
|
width: parent.width
|
|
visible: rail.currentStep === 1
|
|
implicitHeight: depositCol.implicitHeight + Theme.spacing.large * 2
|
|
radius: Theme.spacing.radiusLarge
|
|
color: Theme.palette.backgroundSecondary
|
|
border.width: 1
|
|
border.color: Theme.palette.borderSecondary
|
|
|
|
ColumnLayout {
|
|
id: depositCol
|
|
anchors.fill: parent
|
|
anchors.margins: Theme.spacing.large
|
|
spacing: Theme.spacing.medium
|
|
|
|
LogosText {
|
|
text: qsTr("Deposit amounts")
|
|
font.pixelSize: Theme.typography.panelTitleText
|
|
font.weight: Theme.typography.weightBold
|
|
color: Theme.palette.text
|
|
}
|
|
LogosText {
|
|
Layout.fillWidth: true
|
|
text: qsTr("Set the initial liquidity for the pool.")
|
|
wrapMode: Text.WordWrap
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.textSecondary
|
|
}
|
|
|
|
// Token pair carried over from step 1.
|
|
Rectangle {
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: Theme.spacing.small
|
|
implicitHeight: pairCol.implicitHeight + Theme.spacing.medium * 2
|
|
radius: Theme.spacing.radiusLarge
|
|
color: Theme.palette.backgroundTertiary
|
|
border.width: 1
|
|
border.color: Theme.palette.borderSecondary
|
|
|
|
ColumnLayout {
|
|
id: pairCol
|
|
anchors.fill: parent
|
|
anchors.margins: Theme.spacing.medium
|
|
spacing: Theme.spacing.small
|
|
|
|
LogosText {
|
|
text: qsTr("Selected pair")
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.textSecondary
|
|
}
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
LogosText {
|
|
text: qsTr("Token A")
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.textSecondary
|
|
}
|
|
Item { Layout.fillWidth: true }
|
|
LogosText {
|
|
text: root.truncated(tokenAField.text)
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.text
|
|
}
|
|
}
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
LogosText {
|
|
text: qsTr("Token B")
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.textSecondary
|
|
}
|
|
Item { Layout.fillWidth: true }
|
|
LogosText {
|
|
text: root.truncated(tokenBField.text)
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.text
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Amount inputs, one per token.
|
|
LogosText {
|
|
Layout.topMargin: Theme.spacing.small
|
|
text: qsTr("Token A amount")
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.textSecondary
|
|
}
|
|
LogosTextField {
|
|
id: amountAField
|
|
Layout.fillWidth: true
|
|
placeholderText: "0.0"
|
|
Component.onCompleted: textInput.validator = amountValidator
|
|
}
|
|
|
|
LogosText {
|
|
Layout.topMargin: Theme.spacing.small
|
|
text: qsTr("Token B amount")
|
|
font.pixelSize: Theme.typography.secondaryText
|
|
color: Theme.palette.textSecondary
|
|
}
|
|
LogosTextField {
|
|
id: amountBField
|
|
Layout.fillWidth: true
|
|
placeholderText: "0.0"
|
|
Component.onCompleted: textInput.validator = amountValidator
|
|
}
|
|
|
|
LogosButton {
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: Theme.spacing.medium
|
|
height: 44
|
|
text: qsTr("Create pool")
|
|
enabled: parseFloat(amountAField.text) > 0
|
|
&& parseFloat(amountBField.text) > 0
|
|
// Wiring to the AMM new_definition instruction is a follow-up.
|
|
onClicked: console.log("create pool",
|
|
tokenAField.text, amountAField.text,
|
|
tokenBField.text, amountBField.text)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|