Skip to content

Commit

Permalink
MOB-356 MOB-358 Margin mode screen
Browse files Browse the repository at this point in the history
  • Loading branch information
johnqh committed Apr 3, 2024
1 parent 9015bcf commit 8ebe53d
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import exchange.dydx.trading.common.navigation.DydxRouter
import exchange.dydx.trading.common.navigation.TradeRoutes
import exchange.dydx.trading.common.navigation.dydxComposable
import exchange.dydx.trading.feature.trade.closeposition.DydxClosePositionInputView
import exchange.dydx.trading.feature.trade.tradeinput.DydxTradeInputMarketTypeView
import exchange.dydx.trading.feature.trade.tradeinput.DydxTradeInputMarginModeView
import exchange.dydx.trading.feature.trade.tradeinput.DydxTradeInputTargetLeverageView
import exchange.dydx.trading.feature.trade.tradestatus.DydxTradeStatusView
import timber.log.Timber
Expand Down Expand Up @@ -46,7 +46,7 @@ fun NavGraphBuilder.tradeGraph(
route = TradeRoutes.market_type,
deepLinks = appRouter.deeplinks(TradeRoutes.status),
) { navBackStackEntry ->
DydxTradeInputMarketTypeView.Content(Modifier)
DydxTradeInputMarginModeView.Content(Modifier)
}

dydxComposable(
Expand All @@ -56,5 +56,4 @@ fun NavGraphBuilder.tradeGraph(
) { navBackStackEntry ->
DydxTradeInputTargetLeverageView.Content(Modifier)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
package exchange.dydx.trading.feature.trade.tradeinput

import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import exchange.dydx.platformui.components.PlatformInfoScaffold
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
import exchange.dydx.platformui.designSystem.theme.color
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.feature.shared.views.HeaderViewCloseBotton

@Preview
@Composable
fun Preview_DydxTradeInputMarginModeView() {
DydxThemedPreviewSurface {
DydxTradeInputMarginModeView.Content(
Modifier,
DydxTradeInputMarginModeView.ViewState.preview,
)
}
}

object DydxTradeInputMarginModeView : DydxComponent {
data class MarginTypeSelection(
val title: String,
val text: String,
val selected: Boolean,
val action: () -> Unit,
)

data class ViewState(
val title: String,
val asset: String,
val crossMargin: MarginTypeSelection,
val isolatedMargin: MarginTypeSelection,
val errorText: String?,
val closeAction: (() -> Unit)? = null,
) {
companion object {
val preview = ViewState(
title = "Margin Mode",
asset = "for ETH-USD",
crossMargin = MarginTypeSelection(
title = "Cross Margin",
text = "This is the description text for cross margin",
selected = true,
action = {},
),
isolatedMargin = MarginTypeSelection(
title = "Isolated Margin",
text = "This is the description text for isolated margin",
selected = false,
action = {},
),
errorText = "Error",
)
}
}

@Composable
override fun Content(modifier: Modifier) {
val viewModel: DydxTradeInputMarginModeViewModel = hiltViewModel()

val state = viewModel.state.collectAsStateWithLifecycle(initialValue = null).value
PlatformInfoScaffold(modifier = modifier, platformInfo = viewModel.platformInfo) {
Content(modifier, state)
}
}

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

Column(
modifier = modifier
.animateContentSize()
.fillMaxSize()
.themeColor(ThemeColor.SemanticColor.layer_3),
) {
MarginModeViewHeader(state)
PlatformDivider()
Selection(state.crossMargin)
Spacer(modifier = Modifier.height(8.dp))
Selection(state.isolatedMargin)
}
}

@Composable
fun MarginModeViewHeader(
state: ViewState,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
) {
Spacer(modifier = Modifier.width(16.dp))
Text(
modifier = Modifier.padding(horizontal = 0.dp),
style = TextStyle.dydxDefault
.themeFont(
fontSize = ThemeFont.FontSize.large,
fontType = ThemeFont.FontType.plus,
)
.themeColor(ThemeColor.SemanticColor.text_primary),
text = state.title,
)
Spacer(modifier = Modifier.width(4.dp))
Text(
modifier = Modifier.padding(horizontal = 4.dp),
style = TextStyle.dydxDefault
.themeFont(
fontSize = ThemeFont.FontSize.large,
fontType = ThemeFont.FontType.plus,
)
.themeColor(ThemeColor.SemanticColor.text_secondary),
text = state.asset,
)
Spacer(modifier = Modifier.weight(1f))
HeaderViewCloseBotton(
closeAction = state.closeAction,
)
}
}

@Composable
fun Selection(marginModeState: MarginTypeSelection) {
val shape = RoundedCornerShape(10.dp)
Row(
modifier = Modifier
.padding(
horizontal = ThemeShapes.HorizontalPadding,
vertical = ThemeShapes.VerticalPadding,
)
.fillMaxWidth()
.background(
color = if (marginModeState.selected) {
ThemeColor.SemanticColor.layer_1.color
} else {
ThemeColor.SemanticColor.layer_4.color
},
shape = shape,
)
.border(
width = 1.dp,
color = if (marginModeState.selected) {
ThemeColor.SemanticColor.color_purple.color
} else {
ThemeColor.SemanticColor.layer_7.color
},
shape = shape,
)
.clip(shape)
.padding(
horizontal = ThemeShapes.HorizontalPadding,
vertical = 16.dp,
)
.clickable { marginModeState.action() },
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 0.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(
modifier = Modifier
.padding(horizontal = 0.dp),
style = TextStyle.dydxDefault
.themeFont(
fontSize = ThemeFont.FontSize.medium,
fontType = ThemeFont.FontType.book,
)
.themeColor(ThemeColor.SemanticColor.text_primary),
text = marginModeState.title,
)

Text(
modifier = Modifier
.padding(horizontal = 0.dp),
style = TextStyle.dydxDefault
.themeFont(
fontSize = ThemeFont.FontSize.small,
fontType = ThemeFont.FontType.book,
)
.themeColor(ThemeColor.SemanticColor.text_tertiary),
text = marginModeState.text,
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package exchange.dydx.trading.feature.trade.tradeinput

import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import exchange.dydx.abacus.output.input.MarginMode
import exchange.dydx.abacus.output.input.TradeInput
import exchange.dydx.abacus.protocols.LocalizerProtocol
import exchange.dydx.dydxstatemanager.AbacusStateManagerProtocol
import exchange.dydx.platformui.components.PlatformInfo
import exchange.dydx.trading.common.DydxViewModel
import exchange.dydx.trading.common.formatter.DydxFormatter
import exchange.dydx.trading.common.navigation.DydxRouter
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import javax.inject.Inject

@HiltViewModel
class DydxTradeInputMarginModeViewModel @Inject constructor(
private val localizer: LocalizerProtocol,
private val router: DydxRouter,
private val abacusStateManager: AbacusStateManagerProtocol,
private val formatter: DydxFormatter,
val platformInfo: PlatformInfo,
) : ViewModel(), DydxViewModel {

val state: Flow<DydxTradeInputMarginModeView.ViewState?> =
abacusStateManager.state.tradeInput
.map {
createViewState(it)
}
.distinctUntilChanged()

private fun createViewState(tradeInput: TradeInput?): DydxTradeInputMarginModeView.ViewState {
return DydxTradeInputMarginModeView.ViewState(
localizer.localize("APP.GENERAL.MARGIN_MODE"),
tradeInput?.marketId ?: "",
DydxTradeInputMarginModeView.MarginTypeSelection(
localizer.localize("APP.GENERAL.CROSS_MARGIN"),
localizer.localize("APP.GENERAL.CROSS_MARGIN_DESCRIPTION"),
tradeInput?.marginMode == MarginMode.cross,
{
},
),
DydxTradeInputMarginModeView.MarginTypeSelection(
localizer.localize("APP.GENERAL.ISOLATED_MARGIN"),
localizer.localize("APP.GENERAL.ISOLATED_MARGIN_DESCRIPTION"),
tradeInput?.marginMode == MarginMode.isolated,
{
},
),
null,
{
},
)
}
}
Loading

0 comments on commit 8ebe53d

Please sign in to comment.