Skip to content

Commit

Permalink
MOB-441 add TP/SL display to market screen
Browse files Browse the repository at this point in the history
  • Loading branch information
ruixhuang committed Apr 4, 2024
1 parent 711e4e7 commit fac15ec
Show file tree
Hide file tree
Showing 17 changed files with 960 additions and 28 deletions.
2 changes: 1 addition & 1 deletion v4/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ ext {
compileSdkVersion = 34

// App dependencies
abacusVersion = '1.6.26'
abacusVersion = '1.6.30'
carteraVersion = '0.1.13'
kollectionsVersion = '2.0.16'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.Easing
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.runtime.Composable
import androidx.navigation.NavBackStackEntry
import kotlinx.serialization.json.JsonNull.content
Expand Down Expand Up @@ -144,4 +146,17 @@ object DydxAnimation {
content = content,
)
}

@Composable
fun AnimateExpandInOut(
visible: Boolean,
content: @Composable AnimatedVisibilityScope.() -> Unit
) {
AnimatedVisibility(
visible = visible,
enter = expandVertically(),
exit = shrinkVertically(),
content = content,
)
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package exchange.dydx.trading.feature.market.marketinfo.components.paging

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.AnimatedVisibilityScope
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -88,17 +84,4 @@ object DydxMarketInfoPagingView : DydxComponent {
DydxMarketFundingRateView.Content(modifier)
}
}

@Composable
private fun AnimateFadeInOut(
visible: Boolean,
content: @Composable AnimatedVisibilityScope.() -> Unit
) {
AnimatedVisibility(
visible = visible,
enter = fadeIn(),
exit = fadeOut(),
content = content,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import exchange.dydx.abacus.protocols.LocalizerProtocol
import exchange.dydx.platformui.components.dividers.PlatformDivider
import exchange.dydx.platformui.designSystem.theme.ThemeColor
import exchange.dydx.platformui.designSystem.theme.ThemeFont
import exchange.dydx.platformui.designSystem.theme.ThemeShapes
Expand All @@ -29,9 +30,16 @@ import exchange.dydx.trading.common.component.DydxComponent
import exchange.dydx.trading.common.compose.collectAsStateWithLifecycle
import exchange.dydx.trading.common.theme.DydxThemedPreviewSurface
import exchange.dydx.trading.common.theme.MockLocalizer
import exchange.dydx.trading.feature.shared.views.HeaderView
import exchange.dydx.trading.feature.shared.views.HeaderViewCloseBotton
import exchange.dydx.trading.feature.trade.trigger.components.DydxTriggerOrderCtaButtonView
import exchange.dydx.trading.feature.trade.trigger.components.DydxTriggerOrderReceiptView
import exchange.dydx.trading.feature.trade.trigger.components.inputfields.DydxTriggerOrderInputType
import exchange.dydx.trading.feature.trade.trigger.components.inputfields.DydxTriggerOrderPriceInputType
import exchange.dydx.trading.feature.trade.trigger.components.inputfields.gainloss.DydxTriggerOrderGainLossView
import exchange.dydx.trading.feature.trade.trigger.components.inputfields.limitprice.DydxTriggerOrderLimitPriceSectionView
import exchange.dydx.trading.feature.trade.trigger.components.inputfields.price.DydxTriggerOrderPriceView
import exchange.dydx.trading.feature.trade.trigger.components.inputfields.size.DydxTriggerOrderSizeView

@Preview
@Composable
Expand Down Expand Up @@ -78,17 +86,45 @@ object DydxTriggerOrderInputView : DydxComponent {
focusManager.clearFocus()
})
},
verticalArrangement = Arrangement.spacedBy(12.dp),
) {
HeaderView(modifier = Modifier, state = state)

DydxTriggerOrderReceiptView.Content(
modifier = Modifier.padding(top = 16.dp),
modifier = Modifier,
)

TakeProfitSectionView(
modifier = Modifier,
state = state,
)

StopLossSectionView(
modifier = Modifier,
state = state,
)

AdvacedDividerView(
modifier = Modifier,
state = state,
)

DydxTriggerOrderSizeView.Content(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = ThemeShapes.HorizontalPadding),
)

DydxTriggerOrderLimitPriceSectionView.Content(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = ThemeShapes.HorizontalPadding),
)

Spacer(modifier = Modifier.weight(1f))

DydxTriggerOrderCtaButtonView.Content(
Modifier
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = ThemeShapes.HorizontalPadding)
.padding(bottom = ThemeShapes.VerticalPadding * 2),
Expand Down Expand Up @@ -131,4 +167,91 @@ object DydxTriggerOrderInputView : DydxComponent {
)
}
}

@Composable
private fun TakeProfitSectionView(modifier: Modifier, state: ViewState) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = ThemeShapes.HorizontalPadding),
) {
Text(
text = state.localizer.localize("TRADE.BRACKET_ORDER_TP.TITLE"),
style = TextStyle.dydxDefault
.themeFont(fontSize = ThemeFont.FontSize.base)
.themeColor(ThemeColor.SemanticColor.text_secondary),
)

Row(
modifier = modifier
.fillMaxWidth()
.padding(top = 8.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
DydxTriggerOrderPriceView.Content(
modifier = Modifier.weight(1f),
inputType = DydxTriggerOrderPriceInputType.TakeProfit,
)

DydxTriggerOrderGainLossView.Content(
modifier = Modifier.weight(1f),
inputType = DydxTriggerOrderInputType.TakeProfit,
)
}
}
}

@Composable
private fun StopLossSectionView(modifier: Modifier, state: ViewState) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = ThemeShapes.HorizontalPadding),
) {
Text(
text = state.localizer.localize("TRADE.BRACKET_ORDER_SL.TITLE"),
style = TextStyle.dydxDefault
.themeFont(fontSize = ThemeFont.FontSize.base)
.themeColor(ThemeColor.SemanticColor.text_secondary),
)

Row(
modifier = modifier
.fillMaxWidth()
.padding(top = 8.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
DydxTriggerOrderPriceView.Content(
modifier = Modifier.weight(1f),
inputType = DydxTriggerOrderPriceInputType.StopLoss,
)

DydxTriggerOrderGainLossView.Content(
modifier = Modifier.weight(1f),
inputType = DydxTriggerOrderInputType.StopLoss,
)
}
}
}

@Composable
private fun AdvacedDividerView(modifier: Modifier, state: ViewState) {
Row(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = ThemeShapes.HorizontalPadding),
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = state.localizer.localize("APP.GENERAL.ADVANCED"),
style = TextStyle.dydxDefault
.themeFont(fontSize = ThemeFont.FontSize.small)
.themeColor(ThemeColor.SemanticColor.text_tertiary),
)
PlatformDivider(
modifier = Modifier.weight(1f),
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import exchange.dydx.abacus.protocols.LocalizerProtocol
import exchange.dydx.abacus.state.model.TriggerOrdersInputField
import exchange.dydx.dydxstatemanager.AbacusStateManagerProtocol
import exchange.dydx.trading.common.DydxViewModel
import exchange.dydx.trading.common.formatter.DydxFormatter
Expand All @@ -30,6 +31,7 @@ class DydxTriggerOrderInputViewModel @Inject constructor(
router.navigateBack()
} else {
abacusStateManager.setMarket(marketId = marketId)
abacusStateManager.triggerOrders(input = marketId, type = TriggerOrdersInputField.marketId)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package exchange.dydx.trading.feature.trade.trigger.components.inputfields

enum class DydxTriggerOrderInputType {
TakeProfit,
StopLoss,
}
enum class DydxTriggerOrderPriceInputType {
TakeProfit,
StopLoss,
TakeProfitLimit,
StopLossLimit,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package exchange.dydx.trading.feature.trade.trigger.components.inputfields.gainloss

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import exchange.dydx.abacus.protocols.LocalizerProtocol
import exchange.dydx.platformui.components.buttons.PlatformAccessoryButton
import exchange.dydx.platformui.components.menus.PlatformDropdownMenu
import exchange.dydx.platformui.components.menus.PlatformMenuItem
import exchange.dydx.platformui.designSystem.theme.ThemeColor
import exchange.dydx.platformui.designSystem.theme.ThemeFont
import exchange.dydx.platformui.designSystem.theme.ThemeShapes
import exchange.dydx.platformui.designSystem.theme.dydxDefault
import exchange.dydx.platformui.designSystem.theme.themeColor
import exchange.dydx.platformui.designSystem.theme.themeFont
import exchange.dydx.trading.common.component.DydxComponent
import exchange.dydx.trading.common.compose.collectAsStateWithLifecycle
import exchange.dydx.trading.common.theme.DydxThemedPreviewSurface
import exchange.dydx.trading.common.theme.MockLocalizer
import exchange.dydx.trading.feature.shared.scarfolds.InputFieldScarfold
import exchange.dydx.trading.feature.shared.views.LabeledSelectionInput
import exchange.dydx.trading.feature.shared.views.LabeledTextInput
import exchange.dydx.trading.feature.trade.trigger.components.inputfields.DydxTriggerOrderInputType

@Preview
@Composable
fun Preview_DydxTriggerOrderGainLossView() {
DydxThemedPreviewSurface {
DydxTriggerOrderGainLossView.Content(
Modifier,
DydxTriggerOrderGainLossView.ViewState.preview,
)
}
}

object DydxTriggerOrderGainLossView : DydxComponent {
data class ViewState(
val localizer: LocalizerProtocol,
val labeledTextInput: LabeledTextInput.ViewState? = null,
val labeledSelectionInput: LabeledSelectionInput.ViewState? = null,
) {
companion object {
val preview = ViewState(
localizer = MockLocalizer(),
labeledTextInput = LabeledTextInput.ViewState.preview,
labeledSelectionInput = LabeledSelectionInput.ViewState.preview,
)
}
}

@Composable
override fun Content(modifier: Modifier) {
Content(modifier, DydxTriggerOrderInputType.TakeProfit)
}

@Composable
fun Content(modifier: Modifier, inputType: DydxTriggerOrderInputType) {
when (inputType) {
DydxTriggerOrderInputType.TakeProfit -> {
val viewModel: DydxTriggerOrderGainLossTakeProfitViewModel = hiltViewModel()
val state = viewModel.state.collectAsStateWithLifecycle(initialValue = null).value
Content(modifier, state)
}
DydxTriggerOrderInputType.StopLoss -> {
val viewModel: DydxTriggerOrderGainLossStopLossViewModel = hiltViewModel()
val state = viewModel.state.collectAsStateWithLifecycle(initialValue = null).value
Content(modifier, state)
}
}
}

@Composable
fun Content(modifier: Modifier, state: ViewState?) {
if (state == null) {
return
}

val expanded: MutableState<Boolean> = remember {
mutableStateOf(false)
}

InputFieldScarfold(modifier) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
LabeledTextInput.Content(
modifier = Modifier.weight(1f),
state = state.labeledTextInput,
)

Box {
PlatformAccessoryButton(
modifier = Modifier,
action = { expanded.value = !expanded.value },
) {
Text(
modifier = Modifier.padding(ThemeShapes.InputPaddingValues),
text = state.labeledSelectionInput?.options?.getOrNull(
state.labeledSelectionInput?.selectedIndex ?: 0,
) ?: "",
style = TextStyle.dydxDefault
.themeFont(fontSize = ThemeFont.FontSize.small)
.themeColor(ThemeColor.SemanticColor.text_primary),
)
}

PlatformDropdownMenu(
expanded = expanded,
items = state.labeledSelectionInput?.options?.mapIndexed { index, option ->
PlatformMenuItem(
text = option,
onClick = {
expanded.value = false
state.labeledSelectionInput?.onSelectionChanged?.invoke(index)
},
)
} ?: listOf(),
)
}
}
}
}
}
Loading

0 comments on commit fac15ec

Please sign in to comment.