Skip to content

Conversation

@descorp
Copy link
Contributor

@descorp descorp commented Dec 29, 2025

Changes

  • Improve pre-commit hooks
  • Modular structure - cleaner code organization
  • MessageBus improvement - organize event communication
  • Standalone Session Events - decoupled session communication
  • Improved example app - tabbed navigation with multiple checkout flows
  • Embedded CardView - first embeddable payment component

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @descorp, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a major architectural overhaul to the Adyen React Native SDK, focusing on enhancing modularity and developer experience. Key changes include the implementation of an embedded CardView component, a new MessageBus pattern for decoupled event communication, and a more structured approach to native module wrappers. The accompanying example application has been updated to demonstrate these new capabilities through a tabbed navigation interface, providing clear examples of various checkout flows and component integrations.

Highlights

  • Embedded CardView Component: Introduced the first embeddable payment component, the CardView, allowing developers to integrate card input forms directly into their React Native UI. This is supported on both iOS and Android.
  • MessageBus Pattern for Event Communication: Implemented a new MessageBus pattern to decouple event communication between native modules and the React Native layer. This centralizes event dispatching and handling, replacing previous direct listener implementations.
  • Modular Architecture Refinement: Significant refactoring to achieve a cleaner, more modular code organization across TypeScript, iOS (Swift), and Android (Kotlin). This includes new base wrapper classes and a comprehensive Architecture.md document detailing the layered design.
  • Enhanced Session Handling: Improved session management with standalone session events and a more streamlined approach to session creation and lifecycle within the native modules.
  • Updated Example Application: The example application has been revamped with tabbed navigation, showcasing multiple checkout flows (Sessions Drop-in, Sessions Components, Advanced, Partial Payment, Custom Card, Stored Cards) and demonstrating the new embedded components.
  • Pre-commit Hook Improvements: Added ktlint to Android pre-commit hooks and modified existing hooks to ensure they run silently and allow subsequent checks to proceed even if one fails.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant architectural improvements, primarily by adding an embedded CardView component and a MessageBus for decoupled event communication. The changes lead to a more modular and cleaner code structure, which is a great step forward. The new Architecture.md file is also an excellent addition for documenting these changes. My review includes a few suggestions to enhance code quality and fix a potential issue with error handling.

Comment on lines 143 to 145
.catch((error) => {
onError(
{
message: String(error),
errorCode: 'sessionError',
},
SessionHelper
);
console.error(error);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The error from SessionHelper.createSession is only logged to the console and not propagated to the onError prop. This is a regression from previous behavior and means that the application developer will not be notified of session creation failures. The onError prop should be called to allow for proper error handling in the app.

        .catch((error) => {
          console.error(error);
          onError?.(
            {
              message: String(error),
              errorCode: 'sessionError',
            },
            SessionHelper
          );
        });

Comment on lines +1 to +5
yarn test > /dev/null 2>&1 || yarn test
yarn lint > /dev/null 2>&1 || yarn lint
yarn typecheck > /dev/null 2>&1 || yarn typecheck
swiftformat --lint ios > /dev/null 2>&1 || swiftformat --lint ios
ktlint "!**node_modules**" > /dev/null 2>&1 || ktlint "!**node_modules**"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current approach of running commands twice on failure (e.g., yarn test > /dev/null 2>&1 || yarn test) can be inefficient for long-running tasks like tests. A more efficient pattern would be to capture the command's output and only print it if the command fails, thus avoiding a second execution. For example:

if ! output=$(yarn test 2>&1); then
  echo "$output"
  exit 1
fi

This would improve the developer experience by speeding up the pre-commit hook when failures occur.

companion object {
public val messageBus: MessageBus
get() {
return _messageBus ?: throw Exception("AdyenCheckout MessageBus is not initialized")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Throwing a generic java.lang.Exception is not ideal. It's better to use a more specific exception, like IllegalStateException, to indicate that a component is being used in an invalid state. This provides more clarity to developers using the SDK and allows for more specific catch blocks.

Suggested change
return _messageBus ?: throw Exception("AdyenCheckout MessageBus is not initialized")
return _messageBus ?: throw IllegalStateException("AdyenCheckout MessageBus is not initialized")

Comment on lines +34 to +36
let addressModels: [LookupAddressModel] = results
.compactMap { $0 as? NSDictionary }
.compactMap { try? $0.decode() }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of try? for decoding the address models will cause any decoding errors to be silently ignored. An address that fails to parse will simply be missing from the addressModels array. It would be better to handle potential decoding errors explicitly, for example by logging them, to aid in debugging issues with address data.

        let addressModels: [LookupAddressModel] = results.compactMap { 
            guard let dict = $0 as? NSDictionary else { return nil }
            do {
                return try dict.decode()
            } catch {
                adyenPrint("Failed to decode LookupAddressModel: \(error)")
                return nil
            }
        }

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
1.5% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant