Skip to content

Commit

Permalink
MOB-480 MOB-484: Order-lines formatting, localization, rendering clea…
Browse files Browse the repository at this point in the history
…n-up. (#96)
  • Loading branch information
prashanDYDX authored May 10, 2024
1 parent f9b3530 commit 3d2e002
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package exchange.dydx.trading.feature.market.marketinfo.components.prices

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.Typeface
import android.view.ViewGroup
import androidx.annotation.ColorInt
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
Expand Down Expand Up @@ -37,6 +37,7 @@ import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.data.CandleEntry
import com.github.mikephil.charting.data.Entry
import exchange.dydx.abacus.output.input.OrderSide
import exchange.dydx.abacus.output.input.OrderType
import exchange.dydx.abacus.protocols.LocalizerProtocol
import exchange.dydx.platformui.components.buttons.PlatformPillItem
import exchange.dydx.platformui.components.charts.config.CombinedChartConfig
Expand All @@ -54,6 +55,8 @@ import exchange.dydx.platformui.designSystem.theme.color
import exchange.dydx.platformui.designSystem.theme.dydxDefault
import exchange.dydx.platformui.designSystem.theme.negativeColor
import exchange.dydx.platformui.designSystem.theme.positiveColor
import exchange.dydx.platformui.designSystem.theme.textOnNegativeColor
import exchange.dydx.platformui.designSystem.theme.textOnPositiveColor
import exchange.dydx.platformui.designSystem.theme.themeColor
import exchange.dydx.platformui.designSystem.theme.themeFont
import exchange.dydx.trading.common.component.DydxComponent
Expand Down Expand Up @@ -127,7 +130,7 @@ object DydxMarketPricesView : DydxComponent {
"funding",
),
listOf(
OrderData(1.0, OrderSide.buy, 1.0),
OrderData(1.0, OrderSide.buy, 1.0, "$1.0", OrderType.limit),
),
typeOptions = SelectionOptions(
titles = listOf("Candles", "Lines"),
Expand Down Expand Up @@ -362,7 +365,7 @@ object DydxMarketPricesView : DydxComponent {
) {
AndroidView(
factory = { context ->
CombinedChartWithOrderLines(context).apply {
CombinedChartWithOrderLines(context, state.localizer).apply {
config(state.config)
}
},
Expand Down Expand Up @@ -394,10 +397,20 @@ object DydxMarketPricesView : DydxComponent {
}
}

internal class CombinedChartWithOrderLines(context: Context) : CombinedChart(context) {
internal class CombinedChartWithOrderLines(
context: Context,
private val localizer: LocalizerProtocol,
) : CombinedChart(context) {

// Compose AndroidView by default does not clip children, let's turn it on.
override fun onAttachedToWindow() {
super.onAttachedToWindow()
(parent as ViewGroup).clipChildren = true
}

var orderLines: List<OrderData> = emptyList()
set(value) {
if (field == value) return
field = value
axisLeft.removeAllLimitLines()
value.forEach { (price, side) ->
Expand Down Expand Up @@ -430,24 +443,24 @@ internal class CombinedChartWithOrderLines(context: Context) : CombinedChart(con
return drawTextView(
xPos = 0f,
yPos = yPos,
text = "\$${orderLine.price}",
text = orderLine.formattedPrice,
backgroundColor = orderLine.side.orderLineColor,
textColor = orderLine.side.orderLineTextColor,
)
}

private fun Canvas.drawOrderLabelAndSize(xPos: Float, yPos: Float, orderLine: OrderData) {
val orderLabelRight = drawOrderLabel(xPos, yPos)
val orderLabelRight = drawOrderLabel(xPos, yPos, orderLine)
drawOrderSize(orderLabelRight, yPos, orderLine)
}

private fun Canvas.drawOrderLabel(xPos: Float, yPos: Float): Float {
private fun Canvas.drawOrderLabel(xPos: Float, yPos: Float, orderLine: OrderData): Float {
return drawTextView(
xPos = xPos,
yPos = yPos,
text = "Limit Order",
backgroundColor = Color.parseColor("#18181B"),
textColor = Color.parseColor("#807E98"),
text = localizer.localize(orderLine.orderType.labelKey),
backgroundColor = ThemeColor.SemanticColor.layer_1.color.toArgb(),
textColor = ThemeColor.SemanticColor.text_tertiary.color.toArgb(),
)
}

Expand Down Expand Up @@ -509,6 +522,16 @@ private val OrderSide.orderLineColor: Int

private val OrderSide.orderLineTextColor: Int
get() = when (this) {
OrderSide.buy -> ThemeColor.SemanticColor.color_black.color.toArgb()
OrderSide.sell -> ThemeColor.SemanticColor.color_white.color.toArgb()
OrderSide.buy -> ThemeColor.SemanticColor.textOnPositiveColor.color.toArgb()
OrderSide.sell -> ThemeColor.SemanticColor.textOnNegativeColor.color.toArgb()
}

private val OrderType.labelKey: String
get() = when (this) {
OrderType.takeProfitMarket -> "APP.TRADE.TAKE_PROFIT_MARKET"
OrderType.takeProfitLimit -> "APP.TRADE.TAKE_PROFIT_LIMIT"
OrderType.limit -> "APP.TRADE.LIMIT_ORDER"
OrderType.stopLimit -> "APP.TRADE.STOP_LIMIT"
OrderType.stopMarket -> "APP.TRADE.STOP_MARKET"
else -> error("$this is not supported by orderlines")
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import exchange.dydx.abacus.output.MarketCandle
import exchange.dydx.abacus.output.PerpetualMarket
import exchange.dydx.abacus.output.input.OrderSide
import exchange.dydx.abacus.output.input.OrderStatus
import exchange.dydx.abacus.output.input.OrderType
import exchange.dydx.abacus.protocols.LocalizerProtocol
import exchange.dydx.dydxstatemanager.AbacusStateManagerProtocol
import exchange.dydx.platformui.components.charts.config.AxisConfig
Expand Down Expand Up @@ -45,6 +46,7 @@ import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import timber.log.Timber
import java.time.Instant
import java.time.temporal.ChronoUnit
import javax.inject.Inject
Expand Down Expand Up @@ -110,21 +112,41 @@ class DydxMarketPricesViewModel @Inject constructor(
typeIndex,
resolutionIndex,
) { market, allPrices, ordersForMarket, selectedPrice, typeIndex, resolutionIndex ->
val candlesPeriod = candlesPeriods[resolutionIndex]
val prices = allPrices?.candles?.get(candlesPeriod)
val orderData = ordersForMarket?.run {
filter { it.status in listOf(OrderStatus.open, OrderStatus.untriggered, OrderStatus.partiallyFilled) }
.map { OrderData(it.price, it.side, it.remainingSize ?: it.size) }
}.orEmpty()
createViewState(
prices = prices,
market = market,
orderData = orderData,
candlesPeriod = candlesPeriod,
selectedPrice = selectedPrice,
typeIndex = typeIndex,
resolutionIndex = resolutionIndex,
)
market.configs?.let { configs ->
val candlesPeriod = candlesPeriods[resolutionIndex]
val prices = allPrices.candles?.get(candlesPeriod)
val orderData = ordersForMarket?.let { orders ->
orders
.filter {
it.status in setOf(OrderStatus.open, OrderStatus.untriggered, OrderStatus.partiallyFilled) &&
it.type in setOf(OrderType.limit, OrderType.stopLimit, OrderType.stopMarket, OrderType.takeProfitLimit, OrderType.takeProfitMarket)
}
.map {
OrderData(
price = it.price,
side = it.side,
size = it.remainingSize ?: it.size,
formattedPrice = formatter.dollar(it.price, configs.tickSizeDecimals)
?: run {
Timber.tag("DydxMarketPricesViewModel")
.e("Failed to format orderline price.")
""
},
orderType = it.type,
)
}
}.orEmpty()

createViewState(
prices = prices,
market = market,
orderData = orderData,
candlesPeriod = candlesPeriod,
selectedPrice = selectedPrice,
typeIndex = typeIndex,
resolutionIndex = resolutionIndex,
)
}
}
.distinctUntilChanged()
.stateIn(viewModelScope, SharingStarted.Lazily, null)
Expand Down Expand Up @@ -210,6 +232,44 @@ class DydxMarketPricesViewModel @Inject constructor(
}
}

val orderData = listOf(
OrderData(
price = 3100.0,
side = OrderSide.sell,
formattedPrice = "$3100.00",
orderType = OrderType.takeProfitLimit,
size = 10.0,
),
OrderData(
price = 3300.0,
side = OrderSide.sell,
formattedPrice = "$3300.00",
orderType = OrderType.takeProfitMarket,
size = 10.0,
),
OrderData(
price = 3500.0,
side = OrderSide.sell,
formattedPrice = "$3500.00",
orderType = OrderType.limit,
size = 10.0,
),
OrderData(
price = 2900.0,
side = OrderSide.buy,
formattedPrice = "$2900.00",
orderType = OrderType.stopMarket,
size = 10.0,
),
OrderData(
price = 2700.0,
side = OrderSide.buy,
formattedPrice = "$2700.00",
orderType = OrderType.stopLimit,
size = 10.0,
),
)

return DydxMarketPricesView.ViewState(
localizer = localizer,
config = config(market, candlesPeriod),
Expand Down Expand Up @@ -368,4 +428,6 @@ data class OrderData(
val price: Double,
val side: OrderSide,
val size: Double,
val formattedPrice: String,
val orderType: OrderType,
)
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ import kotlinx.serialization.Serializable

class ThemeSettings(
private val context: Context,
val sharedPreferences: SharedPreferencesStore?,
private val sharedPreferences: SharedPreferencesStore?,
val themeConfig: MutableStateFlow<ThemeConfig?> = MutableStateFlow(ThemeConfig.sampleThemeConfig(context)),
val styleConfig: MutableStateFlow<StyleConfig?> = MutableStateFlow(StyleConfig.sampleStyleConfig(context)),
) {

val greenIsUp: Boolean
get() = (
sharedPreferences?.read("direction_color_preference")
?: "green_is_up"
) == "green_is_up"
companion object {
lateinit var shared: ThemeSettings

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,27 +128,33 @@ private fun family(
}

val ThemeColor.SemanticColor.Companion.positiveColor: ThemeColor.SemanticColor
get() = if ((
ThemeSettings.shared.sharedPreferences?.read("direction_color_preference")
?: "green_is_up"
) == "green_is_up"
) {
get() = if (ThemeSettings.shared.greenIsUp) {
ThemeColor.SemanticColor.color_green
} else {
ThemeColor.SemanticColor.color_red
}

val ThemeColor.SemanticColor.Companion.negativeColor: ThemeColor.SemanticColor
get() = if ((
ThemeSettings.shared.sharedPreferences?.read("direction_color_preference")
?: "green_is_up"
) == "green_is_up"
) {
get() = if (ThemeSettings.shared.greenIsUp) {
ThemeColor.SemanticColor.color_red
} else {
ThemeColor.SemanticColor.color_green
}

val ThemeColor.SemanticColor.Companion.textOnPositiveColor: ThemeColor.SemanticColor
get() = if (ThemeSettings.shared.greenIsUp) {
ThemeColor.SemanticColor.color_black
} else {
ThemeColor.SemanticColor.color_white
}

val ThemeColor.SemanticColor.Companion.textOnNegativeColor: ThemeColor.SemanticColor
get() = if (ThemeSettings.shared.greenIsUp) {
ThemeColor.SemanticColor.color_white
} else {
ThemeColor.SemanticColor.color_black
}

val ThemeColor.SemanticColor.positiveGradient: Brush
get() {
val colorStops = arrayOf(
Expand Down

0 comments on commit 3d2e002

Please sign in to comment.