From 871e8cae3085e0a7dd02f870ca5037fc3d6e82a3 Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Mon, 1 Dec 2025 15:47:00 +0200 Subject: [PATCH 01/10] Compose '2025.11.01' --- build.gradle | 2 +- .../sdk/ui/core/component/field/dropdown/PODropdownField.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 8b14bf8a4..95a67355d 100644 --- a/build.gradle +++ b/build.gradle @@ -68,7 +68,7 @@ ext { androidxBrowserVersion = '1.8.0' androidxCameraVersion = '1.4.2' - androidxComposeBOMVersion = '2025.04.00' + androidxComposeBOMVersion = '2025.11.01' composeGooglePayButtonVersion = '1.1.0' materialVersion = '1.12.0' diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/dropdown/PODropdownField.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/dropdown/PODropdownField.kt index 05dfb5559..c14400860 100644 --- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/dropdown/PODropdownField.kt +++ b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/dropdown/PODropdownField.kt @@ -140,7 +140,7 @@ fun PODropdownField( expanded = expanded, onDismissRequest = { expanded = false }, modifier = Modifier - .exposedDropdownSize(matchTextFieldWidth = menuMatchesTextFieldWidth) + .exposedDropdownSize(matchAnchorWidth = menuMatchesTextFieldWidth) .heightIn(max = maxMenuHeight) .border( width = menuStyle.border.width, From 8829f9be33c2cbe64ce4baaffe8e1c59434c00ce Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Mon, 1 Dec 2025 16:11:08 +0200 Subject: [PATCH 02/10] commonMarkVersion = '0.27.0' --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 95a67355d..9341c5a67 100644 --- a/build.gradle +++ b/build.gradle @@ -81,7 +81,7 @@ ext { okhttpVersion = '4.12.0' okioVersion = '3.10.2' coilVersion = '2.7.0' - commonMarkVersion = '0.25.1' + commonMarkVersion = '0.27.0' libphonenumberVersion = '9.0.12' zxingVersion = '3.5.3' jjwtVersion = '0.13.0' From 1cec4475b97dea36bcf70939cf85509a94119776 Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Mon, 1 Dec 2025 16:15:30 +0200 Subject: [PATCH 03/10] libphonenumberVersion = '9.0.19' --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9341c5a67..dd02d5e3e 100644 --- a/build.gradle +++ b/build.gradle @@ -82,7 +82,7 @@ ext { okioVersion = '3.10.2' coilVersion = '2.7.0' commonMarkVersion = '0.27.0' - libphonenumberVersion = '9.0.12' + libphonenumberVersion = '9.0.19' zxingVersion = '3.5.3' jjwtVersion = '0.13.0' bouncyCastleVersion = '1.79' From ebe634b6a0667002d04fcc07bca913bf0679d5ed Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Mon, 1 Dec 2025 16:26:46 +0200 Subject: [PATCH 04/10] zxingVersion = '3.5.4' --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index dd02d5e3e..5e070ea8f 100644 --- a/build.gradle +++ b/build.gradle @@ -83,7 +83,7 @@ ext { coilVersion = '2.7.0' commonMarkVersion = '0.27.0' libphonenumberVersion = '9.0.19' - zxingVersion = '3.5.3' + zxingVersion = '3.5.4' jjwtVersion = '0.13.0' bouncyCastleVersion = '1.79' slf4jVersion = '1.7.36' From de1ceb3bc740bbce6af0a9b60bff67909c1a9d14 Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Mon, 1 Dec 2025 18:01:58 +0200 Subject: [PATCH 05/10] Libs update, minor versions --- build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 5e070ea8f..49a4706a6 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { kotlinVersion = '2.1.20' kspVersion = '2.1.20-1.0.32' dokkaVersion = '1.9.20' - androidxNavigationVersion = '2.9.3' + androidxNavigationVersion = '2.9.6' secretsVaultPluginVersion = '0.1.3' nexusPublishPluginVersion = '2.0.0' } @@ -62,7 +62,7 @@ ext { androidxConstraintLayoutVersion = '2.2.1' androidxActivityVersion = '1.10.1' androidxFragmentVersion = '1.8.9' - androidxLifecycleVersion = '2.9.0' + androidxLifecycleVersion = '2.9.4' androidxRecyclerViewVersion = '1.4.0' androidxSwipeRefreshLayoutVersion = '1.1.0' androidxBrowserVersion = '1.8.0' @@ -92,15 +92,15 @@ ext { checkout3dsSdkVersion = '3.2.7' junitVersion = '4.13.2' - mockitoVersion = '5.19.0' + mockitoVersion = '5.20.0' mockitoInlineVersion = '5.2.0' - mockitoKotlinVersion = '6.0.0' - robolectricVersion = '4.15.1' + mockitoKotlinVersion = '6.1.0' + robolectricVersion = '4.16' androidxTestCoreVersion = '1.7.0' // Legacy volleyVersion = '1.2.1' - gsonVersion = '2.13.1' + gsonVersion = '2.13.2' } apply from: "${rootDir}/scripts/publish-root.gradle" From 7cb4ef36bd95ed6b233a153feae602301196a5ef Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Tue, 2 Dec 2025 15:16:33 +0200 Subject: [PATCH 06/10] ExposedDropdownMenuAnchorType --- .../sdk/ui/core/component/field/dropdown/PODropdownField.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/dropdown/PODropdownField.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/dropdown/PODropdownField.kt index c14400860..4f4de595e 100644 --- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/dropdown/PODropdownField.kt +++ b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/dropdown/PODropdownField.kt @@ -107,7 +107,7 @@ fun PODropdownField( onValueChange = {}, modifier = Modifier.fillMaxWidth(), textFieldModifier = textFieldModifier - .menuAnchor(MenuAnchorType.PrimaryNotEditable) + .menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable) .onFocusChanged { isFocused = it.isFocused }, From 6e6c0fa0fe7c9f695c00b1730a4312f5e1d907f9 Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Tue, 2 Dec 2025 17:47:12 +0200 Subject: [PATCH 07/10] Re-implement pasting of code field to new API, remove ProcessOutTextToolbar --- .../core/component/field/code/POCodeField.kt | 63 +++++++----- .../FloatingTextActionModeCallback.kt | 44 --------- .../PrimaryTextActionModeCallback.kt | 26 ----- .../texttoolbar/ProcessOutTextToolbar.kt | 71 ------------- .../texttoolbar/TextActionModeCallback.kt | 99 ------------------- 5 files changed, 37 insertions(+), 266 deletions(-) delete mode 100644 ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/FloatingTextActionModeCallback.kt delete mode 100644 ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/PrimaryTextActionModeCallback.kt delete mode 100644 ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/ProcessOutTextToolbar.kt delete mode 100644 ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/TextActionModeCallback.kt diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/code/POCodeField.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/code/POCodeField.kt index 0bf05bc39..0fa85b0dc 100644 --- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/code/POCodeField.kt +++ b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/code/POCodeField.kt @@ -6,6 +6,9 @@ import androidx.compose.foundation.focusGroup import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.text.contextmenu.builder.item +import androidx.compose.foundation.text.contextmenu.modifier.appendTextContextMenuComponents +import androidx.compose.foundation.text.contextmenu.modifier.filterTextContextMenuComponents import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -30,11 +33,11 @@ import com.processout.sdk.ui.core.component.PORequestFocus import com.processout.sdk.ui.core.component.POText import com.processout.sdk.ui.core.component.field.POField import com.processout.sdk.ui.core.component.field.POField.stateStyle +import com.processout.sdk.ui.core.component.field.code.POCodeField.ContextMenuPasteKey import com.processout.sdk.ui.core.component.field.code.POCodeField.align import com.processout.sdk.ui.core.component.field.code.POCodeField.rememberTextFieldWidth import com.processout.sdk.ui.core.component.field.code.POCodeField.validLength import com.processout.sdk.ui.core.component.field.text.POTextField -import com.processout.sdk.ui.core.component.texttoolbar.ProcessOutTextToolbar import com.processout.sdk.ui.core.state.POInputFilter import com.processout.sdk.ui.core.theme.ProcessOutTheme.colors import com.processout.sdk.ui.core.theme.ProcessOutTheme.spacing @@ -111,31 +114,7 @@ private fun Code( keyboardActions: KeyboardActions, modifier: Modifier = Modifier ) { - val validLength = remember(length) { validLength(length) } - var values by remember(validLength) { mutableStateOf(values(value.text, validLength, inputFilter)) } - var focusedIndex by remember(validLength) { mutableIntStateOf(values.focusedIndex()) } - val clipboardManager = LocalClipboardManager.current - CompositionLocalProvider( - LocalLayoutDirection provides LayoutDirection.Ltr, - LocalTextToolbar provides ProcessOutTextToolbar( - view = LocalView.current, - onPasteRequested = { - if (clipboardManager.hasText()) { - val pastedValues = values( - text = clipboardManager.getText()?.text ?: String(), - length = validLength, - inputFilter = inputFilter - ) - if (!pastedValues.all { it.text.isEmpty() }) { - values = pastedValues - focusedIndex = values.focusedIndex() - onValueChange(values.codeValue()) - } - } - }, - hideUnspecifiedActions = true - ) - ) { + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) { var rowWidthPx by remember { mutableIntStateOf(0) } val horizontalSpace = spacing.space8 Row( @@ -146,7 +125,14 @@ private fun Code( horizontalArrangement = Arrangement.spacedBy(horizontalSpace), verticalAlignment = Alignment.CenterVertically ) { + val context = LocalContext.current + val clipboardManager = LocalClipboardManager.current val focusManager = LocalFocusManager.current + + val validLength = remember(length) { validLength(length) } + var values by remember(validLength) { mutableStateOf(values(value.text, validLength, inputFilter)) } + var focusedIndex by remember(validLength) { mutableIntStateOf(values.focusedIndex()) } + for (textFieldIndex in values.indices) { val focusRequester = remember { FocusRequester() } POTextField( @@ -225,6 +211,29 @@ private fun Code( } false } + .appendTextContextMenuComponents { + item( + key = ContextMenuPasteKey, + label = context.getString(android.R.string.paste) + ) { + if (clipboardManager.hasText()) { + val pastedValues = values( + text = clipboardManager.getText()?.text ?: String(), + length = validLength, + inputFilter = inputFilter + ) + if (!pastedValues.all { it.text.isEmpty() }) { + values = pastedValues + focusedIndex = values.focusedIndex() + onValueChange(values.codeValue()) + } + } + close() + } + } + .filterTextContextMenuComponents { + it.key == ContextMenuPasteKey + } .focusRequester(focusRequester) .onFocusChanged { if (it.isFocused) { @@ -289,6 +298,8 @@ private fun List.codeValue() = TextFieldValue( @ProcessOutInternalApi object POCodeField { + data object ContextMenuPasteKey + val default: POField.Style @Composable get() = POField.default.let { val text = POText.Style( diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/FloatingTextActionModeCallback.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/FloatingTextActionModeCallback.kt deleted file mode 100644 index 107d25c7d..000000000 --- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/FloatingTextActionModeCallback.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.processout.sdk.ui.core.component.texttoolbar - -import android.graphics.Rect -import android.view.ActionMode -import android.view.Menu -import android.view.MenuItem -import android.view.View -import androidx.annotation.RequiresApi - -@RequiresApi(23) -internal class FloatingTextActionModeCallback( - private val callback: TextActionModeCallback -) : ActionMode.Callback2() { - - override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { - return callback.onCreateActionMode(mode, menu) - } - - override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { - return callback.onPrepareActionMode(mode, menu) - } - - override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { - return callback.onActionItemClicked(mode, item) - } - - override fun onDestroyActionMode(mode: ActionMode?) { - callback.onDestroyActionMode() - } - - override fun onGetContentRect( - mode: ActionMode?, - view: View?, - outRect: Rect? - ) { - val rect = callback.rect - outRect?.set( - rect.left.toInt(), - rect.top.toInt(), - rect.right.toInt(), - rect.bottom.toInt() - ) - } -} diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/PrimaryTextActionModeCallback.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/PrimaryTextActionModeCallback.kt deleted file mode 100644 index 5ed518f53..000000000 --- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/PrimaryTextActionModeCallback.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.processout.sdk.ui.core.component.texttoolbar - -import android.view.ActionMode -import android.view.Menu -import android.view.MenuItem - -internal class PrimaryTextActionModeCallback( - private val callback: TextActionModeCallback -) : ActionMode.Callback { - - override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { - return callback.onCreateActionMode(mode, menu) - } - - override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { - return callback.onPrepareActionMode(mode, menu) - } - - override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { - return callback.onActionItemClicked(mode, item) - } - - override fun onDestroyActionMode(mode: ActionMode?) { - callback.onDestroyActionMode() - } -} diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/ProcessOutTextToolbar.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/ProcessOutTextToolbar.kt deleted file mode 100644 index 529821f3b..000000000 --- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/ProcessOutTextToolbar.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.processout.sdk.ui.core.component.texttoolbar - -import android.os.Build -import android.view.ActionMode -import android.view.View -import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.platform.TextToolbar -import androidx.compose.ui.platform.TextToolbarStatus - -internal class ProcessOutTextToolbar( - private val view: View, - private val onCopyRequested: (() -> Unit)? = null, - private val onPasteRequested: (() -> Unit)? = null, - private val onCutRequested: (() -> Unit)? = null, - private val onSelectAllRequested: (() -> Unit)? = null, - private val hideUnspecifiedActions: Boolean = false -) : TextToolbar { - - private var actionMode: ActionMode? = null - - private val textActionModeCallback = TextActionModeCallback( - onActionModeDestroy = { - actionMode = null - } - ) - - override var status = TextToolbarStatus.Hidden - private set - - override fun showMenu( - rect: Rect, - onCopyRequested: (() -> Unit)?, - onPasteRequested: (() -> Unit)?, - onCutRequested: (() -> Unit)?, - onSelectAllRequested: (() -> Unit)? - ) { - textActionModeCallback.rect = rect - if (hideUnspecifiedActions) { - textActionModeCallback.onCopyRequested = this.onCopyRequested - textActionModeCallback.onPasteRequested = this.onPasteRequested - textActionModeCallback.onCutRequested = this.onCutRequested - textActionModeCallback.onSelectAllRequested = this.onSelectAllRequested - } else { - textActionModeCallback.onCopyRequested = this.onCopyRequested ?: onCopyRequested - textActionModeCallback.onPasteRequested = this.onPasteRequested ?: onPasteRequested - textActionModeCallback.onCutRequested = this.onCutRequested ?: onCutRequested - textActionModeCallback.onSelectAllRequested = this.onSelectAllRequested ?: onSelectAllRequested - } - if (actionMode == null) { - actionMode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - view.startActionMode( - FloatingTextActionModeCallback(textActionModeCallback), - ActionMode.TYPE_FLOATING - ) - } else { - view.startActionMode( - PrimaryTextActionModeCallback(textActionModeCallback) - ) - } - status = TextToolbarStatus.Shown - } else { - actionMode?.invalidate() - } - } - - override fun hide() { - actionMode?.finish() - actionMode = null - status = TextToolbarStatus.Hidden - } -} diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/TextActionModeCallback.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/TextActionModeCallback.kt deleted file mode 100644 index 8950acba5..000000000 --- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/texttoolbar/TextActionModeCallback.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.processout.sdk.ui.core.component.texttoolbar - -import android.view.ActionMode -import android.view.Menu -import android.view.MenuItem -import androidx.compose.ui.geometry.Rect - -internal class TextActionModeCallback( - var rect: Rect = Rect.Zero, - var onCopyRequested: (() -> Unit)? = null, - var onPasteRequested: (() -> Unit)? = null, - var onCutRequested: (() -> Unit)? = null, - var onSelectAllRequested: (() -> Unit)? = null, - val onActionModeDestroy: (() -> Unit)? = null -) { - - fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { - if (mode == null || menu == null) { - return false - } - onCopyRequested?.let { - addMenuItem(menu, MenuItemOption.Copy) - } - onPasteRequested?.let { - addMenuItem(menu, MenuItemOption.Paste) - } - onCutRequested?.let { - addMenuItem(menu, MenuItemOption.Cut) - } - onSelectAllRequested?.let { - addMenuItem(menu, MenuItemOption.SelectAll) - } - return true - } - - fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { - if (mode == null || menu == null) { - return false - } - updateMenuItems(menu) - return true - } - - fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { - when (item?.itemId) { - MenuItemOption.Copy.id -> onCopyRequested?.invoke() - MenuItemOption.Paste.id -> onPasteRequested?.invoke() - MenuItemOption.Cut.id -> onCutRequested?.invoke() - MenuItemOption.SelectAll.id -> onSelectAllRequested?.invoke() - else -> return false - } - mode?.finish() - return true - } - - fun onDestroyActionMode() { - onActionModeDestroy?.invoke() - } - - private fun updateMenuItems(menu: Menu) { - addOrRemoveMenuItem(menu, MenuItemOption.Copy, onCopyRequested) - addOrRemoveMenuItem(menu, MenuItemOption.Paste, onPasteRequested) - addOrRemoveMenuItem(menu, MenuItemOption.Cut, onCutRequested) - addOrRemoveMenuItem(menu, MenuItemOption.SelectAll, onSelectAllRequested) - } - - private fun addOrRemoveMenuItem( - menu: Menu, - item: MenuItemOption, - callback: (() -> Unit)? - ) { - when { - callback != null && menu.findItem(item.id) == null -> addMenuItem(menu, item) - callback == null && menu.findItem(item.id) != null -> menu.removeItem(item.id) - } - } - - private fun addMenuItem(menu: Menu, item: MenuItemOption) { - menu.add(0, item.id, item.order, item.titleResource) - .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM) - } -} - -private enum class MenuItemOption(val id: Int) { - Copy(0), - Paste(1), - Cut(2), - SelectAll(3); - - val titleResource: Int - get() = when (this) { - Copy -> android.R.string.copy - Paste -> android.R.string.paste - Cut -> android.R.string.cut - SelectAll -> android.R.string.selectAll - } - - val order = id -} From 11e64a1793423c0a3cf08a99f8f27c58309d6c27 Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Tue, 2 Dec 2025 19:21:11 +0200 Subject: [PATCH 08/10] Use new LocalClipboard API to paste in code field --- .../sdk/ui/core/component/field/code/POCodeField.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/code/POCodeField.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/code/POCodeField.kt index 0fa85b0dc..7c8e1203c 100644 --- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/code/POCodeField.kt +++ b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/field/code/POCodeField.kt @@ -42,6 +42,7 @@ import com.processout.sdk.ui.core.state.POInputFilter import com.processout.sdk.ui.core.theme.ProcessOutTheme.colors import com.processout.sdk.ui.core.theme.ProcessOutTheme.spacing import com.processout.sdk.ui.core.theme.ProcessOutTheme.typography +import kotlinx.coroutines.launch /** @suppress */ @ProcessOutInternalApi @@ -126,8 +127,9 @@ private fun Code( verticalAlignment = Alignment.CenterVertically ) { val context = LocalContext.current - val clipboardManager = LocalClipboardManager.current + val clipboard = LocalClipboard.current val focusManager = LocalFocusManager.current + val coroutineScope = rememberCoroutineScope() val validLength = remember(length) { validLength(length) } var values by remember(validLength) { mutableStateOf(values(value.text, validLength, inputFilter)) } @@ -216,9 +218,11 @@ private fun Code( key = ContextMenuPasteKey, label = context.getString(android.R.string.paste) ) { - if (clipboardManager.hasText()) { + coroutineScope.launch { + val pastedText = clipboard.getClipEntry()?.clipData + ?.getItemAt(0)?.text?.toString() ?: String() val pastedValues = values( - text = clipboardManager.getText()?.text ?: String(), + text = pastedText, length = validLength, inputFilter = inputFilter ) @@ -227,8 +231,8 @@ private fun Code( focusedIndex = values.focusedIndex() onValueChange(values.codeValue()) } + close() } - close() } } .filterTextContextMenuComponents { From b47b50b3d395f936a20a0f9733e00ec2bce1abd3 Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Tue, 2 Dec 2025 19:44:13 +0200 Subject: [PATCH 09/10] Use new LocalClipboard API to copy in POCopyButton --- .../sdk/ui/core/component/POCopyButton.kt | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POCopyButton.kt b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POCopyButton.kt index c02c9bd4b..9b604cfd5 100644 --- a/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POCopyButton.kt +++ b/ui-core/src/main/kotlin/com/processout/sdk/ui/core/component/POCopyButton.kt @@ -2,12 +2,13 @@ package com.processout.sdk.ui.core.component +import android.content.ClipData import androidx.compose.animation.* import androidx.compose.animation.core.tween import androidx.compose.runtime.* import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalClipboardManager -import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.platform.ClipEntry +import androidx.compose.ui.platform.LocalClipboard import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp import com.processout.sdk.ui.core.R @@ -36,7 +37,7 @@ fun POCopyButton( copiedIcon: PODrawableImage? = POCopyButton.CopiedIcon, iconSize: Dp = dimensions.iconSizeSmall ) { - val clipboardManager = LocalClipboardManager.current + val clipboard = LocalClipboard.current var isCopied by remember { mutableStateOf(false) } var timerJob by remember { mutableStateOf(null) } val coroutineScope = rememberCoroutineScope() @@ -55,12 +56,14 @@ fun POCopyButton( POButton( text = if (isCopiedAnimated) copiedText else copyText, onClick = { - clipboardManager.setText(AnnotatedString(textToCopy)) - isCopied = true - timerJob?.cancel() - timerJob = coroutineScope.launch { - delay(timeMillis = 2500) - isCopied = false + coroutineScope.launch { + clipboard.setClipEntry(ClipEntry(ClipData.newPlainText(textToCopy, textToCopy))) + isCopied = true + timerJob?.cancel() + timerJob = launch { + delay(timeMillis = 2500) + isCopied = false + } } }, modifier = modifier, From 873133b43e84f5c755182251b3f7f746e1d296ff Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Wed, 3 Dec 2025 14:30:11 +0200 Subject: [PATCH 10/10] Fix card scanner padding --- .../com/processout/sdk/ui/card/scanner/CardScannerScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/card/scanner/CardScannerScreen.kt b/ui/src/main/kotlin/com/processout/sdk/ui/card/scanner/CardScannerScreen.kt index 284d0426b..f41d5659c 100644 --- a/ui/src/main/kotlin/com/processout/sdk/ui/card/scanner/CardScannerScreen.kt +++ b/ui/src/main/kotlin/com/processout/sdk/ui/card/scanner/CardScannerScreen.kt @@ -89,7 +89,7 @@ internal fun CardScannerScreen( val contentHeight = it.size.height + verticalSpacingPx onContentHeightChanged(contentHeight) } - .padding(scaffoldPadding) + .padding(bottom = scaffoldPadding.calculateBottomPadding()) ) { POButtonToggle( checked = state.torchAction.checked,