Closed kataRebuy closed 10 months ago
Hi @kataRebuy, thank you for reaching out! Compatibility with Compose is indeed something we're looking into. However at the moment I'm afraid the only way to integrate with our drop-in and components is through an activity or fragment (technically a ViewModelStoreOwner
and a SavedStateRegistryOwner
).
Once we have any updates on that we'll post them here 🙂
Hi again @kataRebuy , can you try this code and let us know if it works?
val cardComponent = CardComponent.PROVIDER.get(
LocalSavedStateRegistryOwner.current,
LocalViewModelStoreOwner.current
paymentMethod,
cardConfiguration,
null,
)
@jreij Thank you, this seems to work I could get rid of the reference of the fragment. But I have to mention that I still use the compose view inside a fragment, I hope it will also work without it.
Good to hear it works! For the view, can you wrap it in an AndroidView
? Something like this:
@Composable
fun CardViewComposable(cardComponent: CardComponent){
val lifecycleOwner = LocalLifecycleOwner.current
return AndroidView(factory = {
CardView(it).apply {
attach(cardComponent, lifecycleOwner)
}
})
}
Yes this works, however, I tried to get rid of the fragment and use it inside a Dialog
and then this problem appears: https://github.com/Adyen/adyen-android/issues/656 that is why we started to wrap it around a fragment
Ah yes you will face this issue indeed. I don't think this can be solved in the current version but we will investigate how we can improve this for the next major release (v5) and hopefully we'll have a proper solution for Compose apps.
@jreij Until this is fixed would it be possible to have a workaround for this issue? Maybe having a function call like cardComponent.reset()
@OscarSpruit will your PR(https://github.com/Adyen/adyen-android/pull/1237/files) solve this issue?
Hi @kataRebuy! Yes, I believe it should resolve all the issues you have been running into and also integration with compose should be easier. However, this change is only for the next 5.x.x release. Meaning you would have to migrate to this new major version
hi @kataRebuy, we just released 5.0.0-alpha02 which improves support for Jetpack compose with 2 new modules: drop-in-compose
and components-compose
.
I just checked the release. I couldn't really find the documentation so I just tried working based on the code. I exchanged the provider from this:
CardComponent.PROVIDER.get( fragment, paymentMethod, cardConfiguration)
to the following:
val savedState = LocalSavedStateRegistryOwner.current
val storeOwner = LocalViewModelStoreOwner.current
val lifecycleOwner = LocalLifecycleOwner.current
val callback = remember {
object : ComponentCallback<CardComponentState> {
override fun onAdditionalDetails(actionComponentData: ActionComponentData) {
TODO("Not yet implemented")
}
override fun onError(componentError: ComponentError) {
TODO("Not yet implemented")
}
override fun onSubmit(state: CardComponentState) {
TODO("Not yet implemented")
}
}
}
CardComponent.PROVIDER.get(
savedState,
storeOwner!!,
lifecycleOwner,
paymentMethod,
cardConfiguration,
application,
callback,
null,
null
)
Is this correct?
I noticed that now you added a button to the component, is there a way to change the text on the button? Also, I would be happy to get a documentation on how can I customize the button and all the colors in the component. It would be really nice if it could be done through the compose view that you created and not with an XML.
BREAKING: In the end, I tested the case reported with this issue: https://github.com/Adyen/adyen-android/issues/656, and seems like this issue is still not solved which makes it impossible to use the view without a fragment. Would it be possible to reopen this issue or the original one(https://github.com/Adyen/adyen-android/issues/656) to keep track of the issue?
Hi again @kataRebuy, the lack of documentation doesn't help indeed, we wanted to get the compose modules out quickly so you can get the chance to try them out but we'll try to document them a bit more. The code you need is basically in these 2 files: drop-in and components.
Here's a code sample you can try out:
import com.adyen.checkout.components.compose.get
@Composable
private fun ComposableCardComponent() {
// keep a reference to this component in case you need to access it later
val cardComponent = CardComponent.PROVIDER.get(
paymentMethod = paymentMethod,
configuration = configuration,
componentCallback = callback,
// this key is necessary to ensure a new component gets created for each different screen/payment session
// generate a new value for this key every time you need to "reset" the component
key = "UNIQUE_KEY_PER_COMPONENT",
)
// this is your composable, a wrapper around our xml view
AdyenComponent(
component = cardComponent,
modifier = YOUR_MODIFIER,
)
}
As for customizing the button there are 2 ways:
Option 1: override our xml strings and styles in your own strings.xml
and styles.xml
:
strings.xml:
<string name="pay_button">Pay</string>
<string name="pay_button_with_value">Pay %s</string>
<string name="confirm_preauthorization">Confirm preauthorization</string>
styles.xml:
<style name="AdyenCheckout.Button.Colored" parent="AdyenCheckout.Button.Primary">
...
</style>
Option 2: hide our button completely and add your own button:
val cardConfiguration = CardConfiguration.Builder(...)
.setSubmitButtonVisible(false)
.build()
YOUR_BUTTON.setOnClickListener {
cardComponent.submit()
}
I hope I haven't missed anything, let me know if you have any more questions. And please let us know whether this works or not and if you think it's a nice way to integrate our components with compose. We're still in alpha and we have lots of room for feedback and improvement 😉
Thank you for the good explanation. I just tried it out the way you suggested and it works. It would be super nice if the AdyenComponent could use compose themes in the future. I am looking forward to the production release.
Great to hear that, thanks for the feedback!
Is your feature request related to a problem? Please describe. I want to fully migrate to compose and get rid of my fragments. Currently, it is not possible because of Adyen Components. The following line is preventing me from doing so:
val cardComponent = CardComponent.PROVIDER.get(this@YourActivity, paymentMethod, cardConfiguration)
Describe the solution you'd like Creating a fully compose component library
Describe alternatives you've considered Maybe it would be possible to just use the context instead of the activity.