animation added

This commit is contained in:
moon 2026-05-16 21:35:58 +06:30
parent ff2858d484
commit f4fc2fa730
8 changed files with 180 additions and 29 deletions

1
.gitignore vendored
View File

@ -14,3 +14,4 @@
.cxx .cxx
local.properties local.properties
/.idea /.idea
/.idea

View File

@ -57,5 +57,6 @@
<option name="composableFile" value="true" /> <option name="composableFile" value="true" />
<option name="previewFile" value="true" /> <option name="previewFile" value="true" />
</inspection_tool> </inspection_tool>
<inspection_tool class="UsePropertyAccessSyntax" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
</profile> </profile>
</component> </component>

View File

@ -19,6 +19,7 @@ import com.mob.utsmyanmar.ui.pinpad.PinPadRoute
import com.mob.utsmyanmar.ui.processing_card.ProcessingCardRoute import com.mob.utsmyanmar.ui.processing_card.ProcessingCardRoute
import com.mob.utsmyanmar.ui.processing_card.ProcessingCardViewModel import com.mob.utsmyanmar.ui.processing_card.ProcessingCardViewModel
import com.mob.utsmyanmar.ui.print_receipt.PrintReceiptScreen import com.mob.utsmyanmar.ui.print_receipt.PrintReceiptScreen
import com.mob.utsmyanmar.ui.sending_to_host.SendingToHostRoute
import com.mob.utsmyanmar.ui.transaction_result.TransactionResultRoute import com.mob.utsmyanmar.ui.transaction_result.TransactionResultRoute
import com.mob.utsmyanmar.viewmodel.CardReaderViewModel import com.mob.utsmyanmar.viewmodel.CardReaderViewModel
import com.mob.utsmyanmar.viewmodel.EmvTransactionProcessViewModel import com.mob.utsmyanmar.viewmodel.EmvTransactionProcessViewModel
@ -153,8 +154,8 @@ fun AppNavGraph(
pinPadViewModel = pinPadViewModel, pinPadViewModel = pinPadViewModel,
sharedViewModel = sharedViewModel, sharedViewModel = sharedViewModel,
transProcessViewModel = transProcessViewModel, transProcessViewModel = transProcessViewModel,
onNavigateTransactionResult = { onNavigateSendingToHost = {
navController.navigate(Routes.TransactionResult.route) { navController.navigate(Routes.SendingToHost.route) {
popUpTo(Routes.PinPad.route) { popUpTo(Routes.PinPad.route) {
inclusive = true inclusive = true
} }
@ -165,6 +166,19 @@ fun AppNavGraph(
) )
} }
composable(Routes.SendingToHost.route) {
SendingToHostRoute(
onNavigateTransactionResult = {
navController.navigate(Routes.TransactionResult.route) {
popUpTo(Routes.SendingToHost.route) {
inclusive = true
}
launchSingleTop = true
}
}
)
}
composable(Routes.TransactionResult.route) { composable(Routes.TransactionResult.route) {
val sharedViewModel: SharedViewModel = hiltViewModel(activity) val sharedViewModel: SharedViewModel = hiltViewModel(activity)

View File

@ -8,6 +8,7 @@ sealed class Routes(val route: String) {
data object CardWaiting : Routes("card_waiting") data object CardWaiting : Routes("card_waiting")
data object ProcessingCard : Routes("processing_card") data object ProcessingCard : Routes("processing_card")
data object PinPad : Routes("pin_pad") data object PinPad : Routes("pin_pad")
data object SendingToHost : Routes("sending_to_host")
data object TransactionResult : Routes("transaction_result") data object TransactionResult : Routes("transaction_result")
data object PrintReceipt : Routes("print_receipt") data object PrintReceipt : Routes("print_receipt")
} }

View File

@ -17,7 +17,7 @@ fun PinPadRoute(
pinPadViewModel: PinPadViewModel, pinPadViewModel: PinPadViewModel,
sharedViewModel: SharedViewModel, sharedViewModel: SharedViewModel,
transProcessViewModel: TransProcessViewModel, transProcessViewModel: TransProcessViewModel,
onNavigateTransactionResult: () -> Unit, onNavigateSendingToHost: () -> Unit,
onBack: () -> Unit onBack: () -> Unit
) { ) {
val pinText by pinPadViewModel.pinText.collectAsStateWithLifecycle() val pinText by pinPadViewModel.pinText.collectAsStateWithLifecycle()
@ -37,7 +37,7 @@ fun PinPadRoute(
payDetail?.tradeAnswerCode = Constant.ANSWER_CODE_APPROVED payDetail?.tradeAnswerCode = Constant.ANSWER_CODE_APPROVED
sharedViewModel.payDetail.value = payDetail sharedViewModel.payDetail.value = payDetail
transProcessViewModel.resetTransactionStatus() transProcessViewModel.resetTransactionStatus()
onNavigateTransactionResult() onNavigateSendingToHost()
} }
PinPadStatus.ON_CANCEL, PinPadStatus.ON_CANCEL,

View File

@ -2,6 +2,9 @@ package com.mob.utsmyanmar.ui.print_receipt
import android.util.Log import android.util.Log
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@ -15,40 +18,47 @@ import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.mob.utsmyanmar.ui.components.appbar.AppBar import com.mob.utsmyanmar.ui.components.appbar.AppBar
import com.mob.utsmyanmar.ui.theme.Primary import com.mob.utsmyanmar.ui.theme.Color
import com.mob.utsmyanmar.ui.theme.White import com.utsmyanmar.paylibs.print.PrintReceipt
import com.utsmyanmar.paylibs.print.NewPrintReceipt
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@Composable @Composable
fun PrintReceiptScreen( fun PrintReceiptScreen(
onPrint: () -> Unit, onPrint: () -> Unit,
onDone: () -> Unit onDone: () -> Unit
) { ) {
BackHandler {
onDone() val scope = rememberCoroutineScope();
val receiptOffsetY = remember {
Animatable(0f);
} }
val animationDuration = 3000;
Scaffold( Scaffold(
topBar = { topBar = {
AppBar(title = "Receipt") AppBar(title = "Receipt")
} },
containerColor = Color.IvoryBeige
) { paddingValues -> ) { paddingValues ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(paddingValues) .padding(paddingValues)
.fillMaxSize() .fillMaxSize()
.background(Color(0xFFF5F5F5))
.padding(16.dp), .padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
@ -57,6 +67,9 @@ fun PrintReceiptScreen(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.graphicsLayer{
translationY = receiptOffsetY.value
}
) )
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
@ -87,18 +100,41 @@ fun PrintReceiptScreen(
.weight(1f) .weight(1f)
.height(50.dp), .height(50.dp),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = Primary, containerColor = Color.LegacyRed,
contentColor = White, contentColor = Color.White,
disabledContainerColor = Primary, disabledContainerColor = Color.LegacyRed.copy(alpha = 0.5f),
disabledContentColor = White, disabledContentColor = Color.White.copy(alpha = 0.5f),
), ),
shape = RoundedCornerShape(12.dp), shape = RoundedCornerShape(12.dp),
onClick = { onClick = {
onPrint() // onPrint()
try { try {
NewPrintReceipt.getInstance().testPrint() PrintReceipt.getInstance().printNow()
scope.launch {
launch {
receiptOffsetY.animateTo(
targetValue = -1500f,
animationSpec = tween(
durationMillis = animationDuration,
easing = FastOutSlowInEasing
)
)
}
delay(5000)
launch {
receiptOffsetY.animateTo(
targetValue = 0f,
animationSpec = tween(
durationMillis = 0,
easing = FastOutSlowInEasing
)
)
}
}
} catch (e: Exception) { } catch (e: Exception) {
Log.d("PrintReceipt", "error with $e") Log.d("PrintReceipt", "error with $e")
} }
} }
) { ) {
@ -116,6 +152,7 @@ fun PrintReceiptScreen(
} }
} }
@Composable @Composable
fun ReceiptPreview( fun ReceiptPreview(
modifier: Modifier = Modifier modifier: Modifier = Modifier
@ -127,32 +164,26 @@ fun ReceiptPreview(
.background(Color.White) .background(Color.White)
.border( .border(
width = 1.dp, width = 1.dp,
color = Color.LightGray, color = Color.Gray,
shape = RoundedCornerShape(12.dp) shape = RoundedCornerShape(12.dp)
) )
.padding(20.dp), .padding(20.dp),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
Text( Text(
text = "MOB POS", text = "MOB POS",
fontSize = 24.sp, fontSize = 24.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontFamily = FontFamily.Monospace fontFamily = FontFamily.Monospace
) )
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
Text( Text(
text = "Transaction Receipt", text = "Transaction Receipt",
fontSize = 14.sp, fontSize = 14.sp,
fontFamily = FontFamily.Monospace fontFamily = FontFamily.Monospace
) )
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
ReceiptDivider() ReceiptDivider()
ReceiptRow("Merchant", "MOB UTS Myanmar") ReceiptRow("Merchant", "MOB UTS Myanmar")
ReceiptRow("Terminal ID", "POS001") ReceiptRow("Terminal ID", "POS001")
ReceiptRow("Transaction", "SALE") ReceiptRow("Transaction", "SALE")
@ -163,11 +194,8 @@ fun ReceiptPreview(
ReceiptRow("Date", "13/05/2026") ReceiptRow("Date", "13/05/2026")
ReceiptRow("Time", "14:30:22") ReceiptRow("Time", "14:30:22")
ReceiptRow("Ref No", "REF123456789") ReceiptRow("Ref No", "REF123456789")
ReceiptDivider() ReceiptDivider()
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
Text( Text(
text = "Thank You", text = "Thank You",
fontSize = 16.sp, fontSize = 16.sp,
@ -200,7 +228,7 @@ fun ReceiptRow(
text = label, text = label,
fontSize = 13.sp, fontSize = 13.sp,
fontFamily = FontFamily.Monospace, fontFamily = FontFamily.Monospace,
color = Color.DarkGray color = Color.Gray
) )
Text( Text(

View File

@ -0,0 +1,19 @@
package com.mob.utsmyanmar.ui.sending_to_host
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import kotlinx.coroutines.delay
private const val MOCK_HOST_DELAY_MS = 2000L
@Composable
fun SendingToHostRoute(
onNavigateTransactionResult: () -> Unit
) {
LaunchedEffect(Unit) {
delay(MOCK_HOST_DELAY_MS)
onNavigateTransactionResult()
}
SendingToHostScreen()
}

View File

@ -0,0 +1,87 @@
package com.mob.utsmyanmar.ui.sending_to_host
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
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.shape.RoundedCornerShape
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.mob.utsmyanmar.ui.theme.Black
import com.mob.utsmyanmar.ui.theme.Primary
import com.mob.utsmyanmar.ui.theme.White
@Composable
fun SendingToHostScreen() {
Scaffold(
containerColor = White
) { paddingValues ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.background(White)
.padding(horizontal = 24.dp, vertical = 32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Box(
modifier = Modifier
.fillMaxWidth()
.background(
color = Primary,
shape = RoundedCornerShape(24.dp)
)
.padding(horizontal = 24.dp, vertical = 32.dp),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
CircularProgressIndicator(color = White)
Spacer(modifier = Modifier.height(20.dp))
Text(
text = "Sending Data",
color = White,
fontSize = 24.sp,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(10.dp))
Text(
text = "Please wait while we send transaction data to host.",
color = White,
fontSize = 15.sp,
textAlign = TextAlign.Center
)
}
}
Spacer(modifier = Modifier.height(24.dp))
Text(
text = "Mock host communication in progress.",
color = Black,
fontSize = 14.sp,
textAlign = TextAlign.Center
)
}
}
}