signature fixed

This commit is contained in:
moon 2026-07-14 15:06:00 +06:30
parent e0baafb84d
commit 6f61532741
7 changed files with 34 additions and 164 deletions

View File

@ -125,4 +125,6 @@ dependencies {
implementation(project(":ecr"))
implementation(project(":xpay"))
implementation(project(":cmhl"))
implementation("se.warting.signature:signature-pad:0.2.0")
}

View File

@ -26,6 +26,7 @@ import com.mob.utsmyanmar.ui.device_info.DeviceInfoViewModel
import com.mob.utsmyanmar.ui.error.TransactionErrorScreen
import com.mob.utsmyanmar.ui.functions.FunctionsScreen
import com.mob.utsmyanmar.ui.history_functions.HistoryRoute
import com.mob.utsmyanmar.ui.history_functions.prepareReprintPayDetail
import com.mob.utsmyanmar.ui.input_amount.AmountRoute
import com.mob.utsmyanmar.ui.password_input.InputPassword
import com.mob.utsmyanmar.ui.password_input.PasswordType
@ -36,7 +37,6 @@ import com.mob.utsmyanmar.ui.processing_card.ProcessingCardRoute
import com.mob.utsmyanmar.ui.processing_card.ProcessingCardViewModel
import com.mob.utsmyanmar.ui.refund_rrn.InputRrnRoute
import com.mob.utsmyanmar.ui.refund_rrn.RRNViewModel
import com.mob.utsmyanmar.ui.history_functions.prepareReprintPayDetail
import com.mob.utsmyanmar.ui.sale_void.TranDetailPage
import com.mob.utsmyanmar.ui.sale_void.VoidTraceScreen
import com.mob.utsmyanmar.ui.sale_void.VoidViewModel
@ -92,7 +92,7 @@ fun AppNavGraph(
val sharedViewModel: SharedViewModel = hiltViewModel(activity)
SignaturePad(
onBack = { navController.popBackStack() },
onConfirm = { _, bitmap, signatureBlob ->
onConfirm = { bitmap, signatureBlob ->
sharedViewModel.signBitmap = bitmap
sharedViewModel.updateSignatureBlob(signatureBlob)
navController.navigate(Routes.TransactionResult.route) {
@ -179,7 +179,6 @@ fun AppNavGraph(
launchSingleTop = true
}
}
"Pre-Auth",
"Cash Adv" -> {
navController.navigate(Routes.Amount.createRoute(action)) {

View File

@ -1,15 +1,10 @@
package com.mob.utsmyanmar.ui.signature_pad
import android.graphics.Bitmap
import android.graphics.Paint
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
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
@ -24,82 +19,31 @@ import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.graphics.createBitmap
import com.mob.utsmyanmar.ui.components.appbar.AppBar
import com.mob.utsmyanmar.ui.theme.MOBPOSTheme
import se.warting.signaturepad.SignaturePadAdapter
import se.warting.signaturepad.SignaturePadView
import java.io.ByteArrayOutputStream
import android.graphics.Canvas as AndroidCanvas
import android.graphics.Path as AndroidPath
import com.mob.utsmyanmar.ui.theme.Color as AppColor
@Composable
fun SignaturePad(
modifier: Modifier = Modifier,
signatureColor: Color = Color.Black,
onBack: () -> Unit = {},
onConfirm: (SignatureMode, Bitmap?, signatureBlob: ByteArray?) -> Unit = { _, _, _ -> }
onConfirm: (Bitmap?, ByteArray?) -> Unit = { _, _ -> }
) {
val paths = remember { mutableStateListOf<List<Offset>>() }
val currentPath = remember { mutableStateListOf<Offset>() }
var selectedMode by remember { mutableStateOf(SignatureMode.Digital) }
var canvasSize by remember { mutableStateOf(Size.Zero) }
var strokeWidth = 6f
var signaturePadAdapter: SignaturePadAdapter? = null
fun clearSignature() {
paths.clear()
currentPath.clear()
}
val scaledWidth = 300
fun buildBitmap(): Bitmap? {
if (selectedMode == SignatureMode.Manual) return null
if (paths.isEmpty() && currentPath.isEmpty()) return null
if (canvasSize.width <= 0f || canvasSize.height <= 0f) return null
val bitmap =
createBitmap(canvasSize.width.toInt(), canvasSize.height.toInt(), Bitmap.Config.RGB_565)
val canvas = AndroidCanvas(bitmap)
canvas.drawColor(android.graphics.Color.WHITE)
val paint = Paint().apply {
color = android.graphics.Color.BLACK
style = Paint.Style.STROKE
isAntiAlias = true
strokeCap = Paint.Cap.ROUND
strokeJoin = Paint.Join.ROUND
strokeWidth = 10f
}
fun drawStroke(points: List<Offset>) {
if (points.size < 2) return
val path = AndroidPath().apply {
moveTo(points.first().x, points.first().y)
for (index in 1 until points.size) {
lineTo(points[index].x, points[index].y)
}
}
canvas.drawPath(path, paint)
}
paths.forEach(::drawStroke)
drawStroke(currentPath)
return bitmap
fun scaleBitmap(source: Bitmap): Bitmap {
val ratio = scaledWidth.toFloat() / source.width
val height = (source.height * ratio).toInt()
return Bitmap.createScaledBitmap(source, scaledWidth, height, true)
}
fun bitmapToBlob(bitmap: Bitmap): ByteArray {
@ -125,103 +69,20 @@ fun SignaturePad(
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth(0.85f)
.height(180.dp)
.align(Alignment.CenterHorizontally)
.background(
color = if (selectedMode == SignatureMode.Digital) {
Color.White
} else {
Color.White.copy(alpha = 0.55f)
},
shape = RoundedCornerShape(16.dp)
)
.padding(12.dp)
.onSizeChanged { size ->
canvasSize = Size(size.width.toFloat(), size.height.toFloat())
}
.pointerInput(selectedMode) {
if (selectedMode == SignatureMode.Manual) return@pointerInput
detectDragGestures(
onDragStart = { startOffset ->
currentPath.add(startOffset)
},
onDrag = { change, _ ->
change.consume()
currentPath.add(change.position)
},
onDragEnd = {
paths.add(currentPath.toList())
currentPath.clear()
}
)
}
) {
Canvas(modifier = Modifier.fillMaxSize()) {
paths.forEach { points ->
if (points.size > 1) {
val path = Path().apply {
moveTo(points.first().x, points.first().y)
for (i in 1 until points.size) {
lineTo(points[i].x, points[i].y)
}
}
drawPath(
path = path,
color = signatureColor,
style = Stroke(width = strokeWidth)
)
}
}
if (currentPath.size > 1) {
val path = Path().apply {
moveTo(currentPath.first().x, currentPath.first().y)
for (i in 1 until currentPath.size) {
lineTo(currentPath[i].x, currentPath[i].y)
}
}
drawPath(
path = path,
color = signatureColor,
style = Stroke(width = strokeWidth)
)
}
}
}
Column(
SignaturePadView(
onReady = { signaturePadAdapter = it },
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
) {
SignatureModeOption(
title = "Manual Sign",
subtitle = "Signature on Paper",
selected = selectedMode == SignatureMode.Manual,
onClick = { selectedMode = SignatureMode.Manual },
modifier = Modifier.fillMaxWidth()
.height(200.dp)
.border(width = 1.dp, color = AppColor.LegacyRed)
)
Spacer(Modifier.height(12.dp))
SignatureModeOption(
title = "Digital Sign",
subtitle = "Draw on pad",
selected = selectedMode == SignatureMode.Digital,
onClick = { selectedMode = SignatureMode.Digital },
modifier = Modifier.fillMaxWidth()
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
OutlinedButton(
onClick = { clearSignature() },
onClick = { signaturePadAdapter?.clear() },
modifier = Modifier
.weight(1f)
.height(50.dp)
@ -231,9 +92,10 @@ fun SignaturePad(
Button(
onClick = {
val bitmap = buildBitmap()
val rawBitmap = signaturePadAdapter?.getSignatureBitmap()
val bitmap = rawBitmap?.let { scaleBitmap(it) }
val signatureBlob = bitmap?.let { bitmapToBlob(it) }
onConfirm(selectedMode, bitmap, signatureBlob)
onConfirm(bitmap, signatureBlob)
},
modifier = Modifier
.weight(1f)

View File

@ -1189,10 +1189,11 @@ public class PrintReceipt {
private void printSignature(Bitmap signatureBitmap) {
try {
sunmiPrinterService.setAlignment(1, null);
if (signatureBitmap.getWidth() > 130) {
double size = 1.0 * signatureBitmap.getHeight() * 130 / signatureBitmap.getWidth();
int newHeight = (int) size;
signatureBitmap = BitmapUtils.scale(signatureBitmap, 130, newHeight);
int targetHeight = 200;
if (signatureBitmap.getHeight() > targetHeight) {
double ratio = 1.0 * targetHeight / signatureBitmap.getHeight();
int newWidth = (int) (signatureBitmap.getWidth() * ratio);
signatureBitmap = BitmapUtils.scale(signatureBitmap, newWidth, targetHeight);
}
sunmiPrinterService.printBitmap(signatureBitmap, null);
sunmiPrinterService.printText("\n", null);

View File

@ -954,6 +954,12 @@ public abstract class BaseXPrint {
if (signatureBlob != null && signatureBlob.length > 0) {
Bitmap signatureBitmap = android.graphics.BitmapFactory.decodeByteArray(signatureBlob, 0, signatureBlob.length);
if (signatureBitmap != null) {
int targetHeight = 200;
if (signatureBitmap.getHeight() > targetHeight) {
double ratio = 1.0 * targetHeight / signatureBitmap.getHeight();
int newWidth = (int) (signatureBitmap.getWidth() * ratio);
signatureBitmap = BitmapUtils.scale(signatureBitmap, newWidth, targetHeight);
}
sunmiPrinterService.printBitmap(signatureBitmap, innerResultCallback);
}
}