Keep open positions carousel stable
This commit is contained in:
@@ -10,7 +10,7 @@ android {
|
||||
applicationId = "xyz.kusoft.tradebotmonitor"
|
||||
minSdk = 26
|
||||
targetSdk = 36
|
||||
versionCode = 16
|
||||
versionName = "0.2.13"
|
||||
versionCode = 17
|
||||
versionName = "0.2.14"
|
||||
}
|
||||
}
|
||||
|
||||
+60
-6
@@ -62,10 +62,12 @@ class MainActivity : Activity() {
|
||||
var positionsScroller: HorizontalScrollView? = null,
|
||||
var positionsList: LinearLayout? = null,
|
||||
var closedTradesContainer: LinearLayout? = null,
|
||||
val positionOrder: MutableList<String> = mutableListOf(),
|
||||
val positions: MutableMap<String, PositionBinding> = linkedMapOf(),
|
||||
)
|
||||
|
||||
private data class PositionBinding(
|
||||
var index: TextView? = null,
|
||||
var value: TextView? = null,
|
||||
var quantity: TextView? = null,
|
||||
var entryPrice: TextView? = null,
|
||||
@@ -165,7 +167,7 @@ class MainActivity : Activity() {
|
||||
trainingStatusSignature = newTrainingStatusSignature
|
||||
lastError = ""
|
||||
ensureSelectedSymbol()
|
||||
if (silent && hadSnapshot && !hadError && updateVisibleScreen(data)) {
|
||||
if (silent && hadSnapshot && updateVisibleScreen(data)) {
|
||||
return@post
|
||||
}
|
||||
if (shouldRenderAfterRefresh(silent, hadSnapshot, hadError, trainingChanged)) {
|
||||
@@ -178,6 +180,9 @@ class MainActivity : Activity() {
|
||||
val hadError = lastError.isNotBlank()
|
||||
lastError = error.message ?: "ошибка подключения"
|
||||
if (!silent) toast(lastError)
|
||||
if (silent && hadSnapshot) {
|
||||
return@post
|
||||
}
|
||||
if (shouldRenderAfterRefresh(silent, hadSnapshot, hadError, trainingChanged = false)) {
|
||||
render()
|
||||
}
|
||||
@@ -258,10 +263,8 @@ class MainActivity : Activity() {
|
||||
val binding = assetsBindings ?: return false
|
||||
val positionSignature = positionsSignature(data.positions)
|
||||
if (binding.positionSignature != positionSignature) {
|
||||
binding.positionsContainer?.let { container ->
|
||||
rebuildPositionsContent(container, data.positions, binding.positionsScroller?.scrollX ?: 0)
|
||||
binding.positionSignature = positionSignature
|
||||
} ?: return false
|
||||
if (!syncPositionsList(binding, data.positions)) return false
|
||||
binding.positionSignature = positionSignature
|
||||
}
|
||||
val closedSignature = closedTradesSignature(data.closedTrades, data.closedTradesSummary)
|
||||
if (binding.closedTradesSignature != closedSignature) {
|
||||
@@ -837,6 +840,7 @@ class MainActivity : Activity() {
|
||||
private fun rebuildPositionsContent(container: LinearLayout, positions: List<PositionData>, preserveScrollX: Int = 0) {
|
||||
container.removeAllViews()
|
||||
assetsBindings?.positions?.clear()
|
||||
assetsBindings?.positionOrder?.clear()
|
||||
assetsBindings?.positionsScroller = null
|
||||
assetsBindings?.positionsList = null
|
||||
if (positions.isEmpty()) {
|
||||
@@ -868,13 +872,61 @@ class MainActivity : Activity() {
|
||||
cardWidth: Int = (resources.displayMetrics.widthPixels - dp(64)).coerceAtLeast(dp(260)),
|
||||
) {
|
||||
list.removeAllViews()
|
||||
assetsBindings?.positionOrder?.clear()
|
||||
positions.forEachIndexed { index, position ->
|
||||
assetsBindings?.positionOrder?.add(positionKey(position))
|
||||
list.addView(positionCard(position, index + 1, positions.size), LinearLayout.LayoutParams(cardWidth, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
|
||||
if (index < positions.lastIndex) setMargins(0, 0, dp(12), 0)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun syncPositionsList(binding: AssetsBindings, positions: List<PositionData>): Boolean {
|
||||
val container = binding.positionsContainer ?: return false
|
||||
val list = binding.positionsList
|
||||
if (list == null || positions.isEmpty() || binding.positionOrder.isEmpty()) {
|
||||
rebuildPositionsContent(container, positions, binding.positionsScroller?.scrollX ?: 0)
|
||||
return true
|
||||
}
|
||||
|
||||
val byKey = positions.associateBy(::positionKey)
|
||||
var index = 0
|
||||
while (index < binding.positionOrder.size) {
|
||||
val key = binding.positionOrder[index]
|
||||
if (!byKey.containsKey(key)) {
|
||||
binding.positionOrder.removeAt(index)
|
||||
binding.positions.remove(key)
|
||||
list.removeViewAt(index)
|
||||
} else {
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
||||
val cardWidth = (resources.displayMetrics.widthPixels - dp(64)).coerceAtLeast(dp(260))
|
||||
positions.forEach { position ->
|
||||
val key = positionKey(position)
|
||||
if (!binding.positionOrder.contains(key)) {
|
||||
binding.positionOrder.add(key)
|
||||
list.addView(positionCard(position, binding.positionOrder.size, positions.size), LinearLayout.LayoutParams(cardWidth, ViewGroup.LayoutParams.WRAP_CONTENT))
|
||||
}
|
||||
}
|
||||
updatePositionCardChrome(binding)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun updatePositionCardChrome(binding: AssetsBindings) {
|
||||
val total = binding.positionOrder.size
|
||||
binding.positionOrder.forEachIndexed { index, key ->
|
||||
setText(binding.positions[key]?.index, "${index + 1}/$total")
|
||||
}
|
||||
val list = binding.positionsList ?: return
|
||||
for (i in 0 until list.childCount) {
|
||||
val params = (list.getChildAt(i).layoutParams as? LinearLayout.LayoutParams) ?: continue
|
||||
params.setMargins(0, 0, if (i < list.childCount - 1) dp(12) else 0, 0)
|
||||
list.getChildAt(i).layoutParams = params
|
||||
}
|
||||
}
|
||||
|
||||
private fun positionCard(position: PositionData, index: Int, total: Int): View =
|
||||
LinearLayout(this).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
@@ -884,7 +936,9 @@ class MainActivity : Activity() {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
addView(text(position.symbol, 20f, Typeface.BOLD), LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f))
|
||||
addView(text("$index/$total", 12f, Typeface.BOLD, palette.muted))
|
||||
val indexText = text("$index/$total", 12f, Typeface.BOLD, palette.muted)
|
||||
assetsBindings?.positions?.getOrPut(positionKey(position)) { PositionBinding() }?.index = indexText
|
||||
addView(indexText)
|
||||
})
|
||||
val valueText = text("${money(position.marketValue)} · ${signedPercent(position.unrealizedPnlPercent, 2)}", 15f, Typeface.BOLD, colorForSigned(position.unrealizedPnlPercent))
|
||||
addView(valueText.top(dp(8)))
|
||||
|
||||
Reference in New Issue
Block a user