auto width printReceiptScreen dot

This commit is contained in:
moon 2026-08-25 21:37:47 +06:30
parent 81920acc8c
commit 7ccf393793
2 changed files with 94 additions and 27 deletions

View File

@ -37,4 +37,7 @@ Pick the edge-case-correct option when two stdlib approaches are the same size,
Mark intentional simplifications with a ponytail: comment. If the shortcut has a known ceiling (global lock, O(n²) scan, naive heuristic), the comment names the ceiling and the upgrade path.
Not lazy about: understanding the problem (read it fully and trace the real flow before picking a rung, a small diff you don't understand is just laziness dressed up as efficiency), input validation at trust boundaries, error handling that prevents data loss, security, accessibility, the calibration real hardware needs (the platform is never the spec ideal, a clock drifts, a sensor reads off), anything explicitly requested. Lazy code without its check is unfinished: non-trivial logic leaves ONE runnable check behind, the smallest thing that fails if the logic breaks (an assert-based demo/self-check or one small test file; no frameworks, no fixtures). Trivial one-liners need no test.
(Yes, this file also applies to agents working on the ponytail repo itself. Especially to them.)
(Yes, this file also applies to agents working on the ponytail repo itself. Especially to them.)
### Don't Do This
- don't run ./grdlew

View File

@ -3,6 +3,7 @@ package com.mob.utsmyanmar.ui.print_receipt
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
@ -32,18 +33,24 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.mob.utsmyanmar.ui.components.appbar.AppBar
import com.mob.utsmyanmar.ui.history_functions.displayTransactionStatus
import com.mob.utsmyanmar.ui.history_functions.displayTransactionTitle
import com.mob.utsmyanmar.ui.preview.P2Preview
import com.mob.utsmyanmar.ui.preview.P3Preview
import com.mob.utsmyanmar.ui.theme.Color
import com.mob.utsmyanmar.ui.theme.MOBPOSTheme
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultState
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultViewModel
import com.mob.utsmyanmar.viewmodel.SharedViewModel
import com.utsmyanmar.paylibs.model.PayDetail
import com.utsmyanmar.paylibs.utils.POSUtil
import com.utsmyanmar.paylibs.utils.PrintStatus
import kotlinx.coroutines.launch
@ -59,9 +66,32 @@ fun PrintReceiptScreen(
sharedViewModel: SharedViewModel,
onPrint: () -> Unit,
onDone: () -> Unit,
onPrintFinished : () -> Unit,
onPrintFinished: () -> Unit,
) {
val state by transactionResultViewModel.state.collectAsStateWithLifecycle()
val isReprint = sharedViewModel.isReprint.value ?: false
PrintReceiptContent(
state = state,
isReprint = isReprint,
onPrint = onPrint,
onDone = onDone,
onPrintFinished = onPrintFinished,
onSetPrintStatus = { sharedViewModel.setPrintStatus(it) },
onResetReprint = { sharedViewModel.isReprint.value = false },
)
}
@Composable
fun PrintReceiptContent(
state: TransactionResultState,
isReprint: Boolean,
onPrint: () -> Unit,
onDone: () -> Unit,
onPrintFinished: () -> Unit,
onSetPrintStatus: (PrintStatus) -> Unit,
onResetReprint: () -> Unit
) {
val scope = rememberCoroutineScope()
val receiptOffsetY = remember { Animatable(0f) }
val merchant_copy_autoprint = true
@ -82,14 +112,11 @@ fun PrintReceiptScreen(
)
}
fun isReprintMode() = sharedViewModel.isReprint.value == true
fun doPrint(copy: ReceiptCopy, onFinished: (printFinished: ReceiptCopy) -> Unit) {
val reprint = isReprintMode()
val actualCopy = if (reprint && copy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else copy
val actualCopy = if (isReprint && copy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER else copy
currentCopy = actualCopy
sharedViewModel.setPrintStatus(
onSetPrintStatus(
if (actualCopy == ReceiptCopy.MERCHANT)
PrintStatus.FIRST_PRINT
else
@ -100,7 +127,7 @@ fun PrintReceiptScreen(
isPrinting = true
animatePrint()
isPrinting = false
val upcomingCopy = if (reprint) ReceiptCopy.CUSTOMER
val upcomingCopy = if (isReprint) ReceiptCopy.CUSTOMER
else if (actualCopy == ReceiptCopy.MERCHANT) ReceiptCopy.CUSTOMER
else ReceiptCopy.CUSTOMER
@ -112,14 +139,13 @@ fun PrintReceiptScreen(
}
LaunchedEffect(Unit) {
val reprint = isReprintMode()
if (reprint) {
if (isReprint) {
currentCopy = ReceiptCopy.CUSTOMER
nextCopy = ReceiptCopy.CUSTOMER
}
sharedViewModel.isReprint.value = false
onResetReprint()
when {
merchant_copy_autoprint && !reprint -> doPrint(ReceiptCopy.MERCHANT) { }
merchant_copy_autoprint && !isReprint -> doPrint(ReceiptCopy.MERCHANT) { }
customer_copy_autoprint -> doPrint(ReceiptCopy.CUSTOMER) { }
}
}
@ -209,6 +235,7 @@ fun ReceiptPreview(
copyLabel: String,
modifier: Modifier = Modifier
) {
val isPreview = LocalInspectionMode.current
Column(
modifier = modifier
.fillMaxWidth()
@ -246,7 +273,7 @@ fun ReceiptPreview(
ReceiptRow("Amount", POSUtil.getInstance().getDecimalAmountSeparatorFormat(state.payDetail?.amount?:0))
ReceiptRow("Card Type", state.payDetail?.accountType.toString())
ReceiptRow("Card No", state.payDetail?.cardNo.toString())
ReceiptRow("Status", state.payDetail?.let(::displayTransactionStatus).orEmpty())
ReceiptRow("Status", if (isPreview) "SUCCESS" else state.payDetail?.let(::displayTransactionStatus).orEmpty())
ReceiptRow("Date", state.payDetail?.transDate.toString() )
ReceiptRow("Time", state.payDetail?.transTime.toString())
ReceiptRow("Ref No", state.payDetail?.referNo.toString())
@ -292,25 +319,62 @@ fun ReceiptRow(
@Composable
fun ReceiptDivider() {
Text(
Canvas(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
text = "--------------------------------",
color = Color.Gray
)
.padding(vertical = 10.dp)
.height(2.dp)
) {
// Convert dp to pixels so it scales perfectly on all screen sizes
val dotRadius = 1.5.dp.toPx()
val dotSpacing = 6.dp.toPx()
val totalWidth = size.width
var currentX = 0f
// Loop across the width of the screen and draw individual circles
while (currentX < totalWidth) {
drawCircle(
color = Color.Gray,
radius = dotRadius,
center = Offset(x = currentX, y = size.height / 2)
)
// Move X forward by the size of the dot + the space we want
currentX += (dotRadius * 2) + dotSpacing
}
}
}
@Preview(showBackground = true, showSystemUi = true)
@P2Preview
@P3Preview
@Composable
fun PreviewPrintReceiptScreen() {
MaterialTheme {
PrintReceiptScreen(
sharedViewModel = hiltViewModel(),
transactionResultViewModel = hiltViewModel(),
private fun PrintReceiptScreenPreview() {
val samplePayDetail = PayDetail().apply {
merchantName = "Sample Merchant"
terminalNo = "12345678"
voucherNo = "000001"
amount = 100000
cardNo = "1234********5678"
transDate = "2023-10-27"
transTime = "10:30:00"
referNo = "123456789012"
transType = "SALE"
tradeAnswerCode = "00"
}
val sampleState = TransactionResultState(
payDetail = samplePayDetail
)
MOBPOSTheme {
PrintReceiptContent(
state = sampleState,
isReprint = false,
onPrint = {},
onDone = {},
onPrintFinished = {}
onPrintFinished = {},
onSetPrintStatus = {},
onResetReprint = {}
)
}
}