From be50fa8297088395e59aeb590960e17e89c59420 Mon Sep 17 00:00:00 2001 From: viktor Date: Thu, 26 Mar 2026 20:55:49 +0200 Subject: [PATCH 1/2] MS-503: Add properties to the SDK theme --- .../api/model/branding_options_request.dart | 73 ++++ .../api/model/branding_options_request.g.dart | 79 ++++ .../api/model/create_transaction_request.dart | 5 + .../model/create_transaction_request.g.dart | 6 + Sample/lib/api/model/pg_codes.dart | 7 +- .../lib/feature/home/home_screen_cubit.dart | 98 +++++ .../theme/theme_customization_screen.dart | 152 ++++++- Sample/pubspec.yaml | 7 +- .../com/ottu/flutter/checkout/CheckoutView.kt | 11 +- .../ottu/flutter/checkout/CustomerTheme.kt | 6 +- .../ottu/flutter/checkout/ext/Extensions.kt | 45 +- .../CheckoutPlatformView.swift | 6 + .../CheckoutViewFactory.swift | 29 +- .../ottu_flutter_checkout/CustomerTheme.swift | 6 +- .../Sources/ottu_flutter_checkout/ext.swift | 25 +- lib/src/checkout_arguments.g.dart | 6 +- lib/src/checkout_theme.dart | 45 +- lib/src/checkout_theme.g.dart | 394 ++++++++++-------- lib/src/pay_button_text.g.dart | 10 +- .../payment_options_display_settings.g.dart | 24 +- pubspec.yaml | 6 +- 21 files changed, 789 insertions(+), 251 deletions(-) create mode 100644 Sample/lib/api/model/branding_options_request.dart create mode 100644 Sample/lib/api/model/branding_options_request.g.dart diff --git a/Sample/lib/api/model/branding_options_request.dart b/Sample/lib/api/model/branding_options_request.dart new file mode 100644 index 0000000..b8fc3e2 --- /dev/null +++ b/Sample/lib/api/model/branding_options_request.dart @@ -0,0 +1,73 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'branding_options_request.g.dart'; + +@JsonSerializable() +class BrandingOptionsRequest { + @JsonKey(name: "payment_methods") + final BrandingPaymentMethods paymentMethods; + + BrandingOptionsRequest({required this.paymentMethods}); + + factory BrandingOptionsRequest.fromJson(Map json) => + _$BrandingOptionsRequestFromJson(json); + + Map toJson() => _$BrandingOptionsRequestToJson(this); +} + +@JsonSerializable() +class BrandingPaymentMethods { + @JsonKey(name: "knet-staging", includeIfNull: false) + BrandingOption? knetStaging; + @JsonKey(includeIfNull: false) + BrandingOption? tabby; + @JsonKey(includeIfNull: false) + BrandingOption? tamara; + @JsonKey(includeIfNull: false) + BrandingOption? cod; + @JsonKey(name: "mpgs-testing", includeIfNull: false) + BrandingOption? mpgs; + @JsonKey(name: "stc_pay", includeIfNull: false) + BrandingOption? stcPay; + @JsonKey(includeIfNull: false) + BrandingOption? cs; + @JsonKey(includeIfNull: false) + BrandingOption? jamiawallet; + @JsonKey(name: "nbk-mpgs", includeIfNull: false) + BrandingOption? nbkMpgs; + @JsonKey(name: "tap_pg", includeIfNull: false) + BrandingOption? tapPg; + @JsonKey(name: "ottu_sdk", includeIfNull: false) + BrandingOption? ottuSdk; + + BrandingPaymentMethods({ + this.knetStaging, + this.tabby, + this.cod, + this.mpgs, + this.stcPay, + this.cs, + this.nbkMpgs, + this.tapPg, + this.ottuSdk, + }); + + factory BrandingPaymentMethods.fromJson(Map json) => + _$BrandingPaymentMethodsFromJson(json); + + Map toJson() => _$BrandingPaymentMethodsToJson(this); +} + +@JsonSerializable() +class BrandingOption { + final String text; + final String color; + @JsonKey(name: "font_weight") + final int fontWeight; + + BrandingOption({required this.text, required this.color, required this.fontWeight}); + + factory BrandingOption.fromJson(Map json) => _$BrandingOptionFromJson(json); + + Map toJson() => _$BrandingOptionToJson(this); +} diff --git a/Sample/lib/api/model/branding_options_request.g.dart b/Sample/lib/api/model/branding_options_request.g.dart new file mode 100644 index 0000000..1779350 --- /dev/null +++ b/Sample/lib/api/model/branding_options_request.g.dart @@ -0,0 +1,79 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'branding_options_request.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BrandingOptionsRequest _$BrandingOptionsRequestFromJson( + Map json, +) => BrandingOptionsRequest( + paymentMethods: BrandingPaymentMethods.fromJson( + json['payment_methods'] as Map, + ), +); + +Map _$BrandingOptionsRequestToJson( + BrandingOptionsRequest instance, +) => {'payment_methods': instance.paymentMethods}; + +BrandingPaymentMethods _$BrandingPaymentMethodsFromJson( + Map json, +) => BrandingPaymentMethods( + knetStaging: json['knet-staging'] == null + ? null + : BrandingOption.fromJson(json['knet-staging'] as Map), + tabby: json['tabby'] == null + ? null + : BrandingOption.fromJson(json['tabby'] as Map), + cod: json['cod'] == null + ? null + : BrandingOption.fromJson(json['cod'] as Map), + mpgs: json['mpgs-testing'] == null + ? null + : BrandingOption.fromJson(json['mpgs-testing'] as Map), + stcPay: json['stc_pay'] == null + ? null + : BrandingOption.fromJson(json['stc_pay'] as Map), + cs: json['cs'] == null + ? null + : BrandingOption.fromJson(json['cs'] as Map), + nbkMpgs: json['nbk-mpgs'] == null + ? null + : BrandingOption.fromJson(json['nbk-mpgs'] as Map), + tapPg: json['tap_pg'] == null + ? null + : BrandingOption.fromJson(json['tap_pg'] as Map), + ottuSdk: json['ottu_sdk'] == null + ? null + : BrandingOption.fromJson(json['ottu_sdk'] as Map), +); + +Map _$BrandingPaymentMethodsToJson( + BrandingPaymentMethods instance, +) => { + 'knet-staging': ?instance.knetStaging, + 'tabby': ?instance.tabby, + 'cod': ?instance.cod, + 'mpgs-testing': ?instance.mpgs, + 'stc_pay': ?instance.stcPay, + 'cs': ?instance.cs, + 'nbk-mpgs': ?instance.nbkMpgs, + 'tap_pg': ?instance.tapPg, + 'ottu_sdk': ?instance.ottuSdk, +}; + +BrandingOption _$BrandingOptionFromJson(Map json) => + BrandingOption( + text: json['text'] as String, + color: json['color'] as String, + fontWeight: (json['font_weight'] as num).toInt(), + ); + +Map _$BrandingOptionToJson(BrandingOption instance) => + { + 'text': instance.text, + 'color': instance.color, + 'font_weight': instance.fontWeight, + }; diff --git a/Sample/lib/api/model/create_transaction_request.dart b/Sample/lib/api/model/create_transaction_request.dart index 33db3cf..51b8d9d 100644 --- a/Sample/lib/api/model/create_transaction_request.dart +++ b/Sample/lib/api/model/create_transaction_request.dart @@ -3,6 +3,8 @@ import 'package:ottu_flutter_checkout_sample/api/model/billing_address.dart'; import 'package:ottu_flutter_checkout_sample/api/model/transaction_agreement.dart'; import 'package:ottu_flutter_checkout_sample/api/model/transaction_payment_type.dart'; +import 'branding_options_request.dart'; + part 'create_transaction_request.g.dart'; @JsonSerializable() @@ -32,6 +34,8 @@ class CreateTransactionRequest { final TransactionPaymentType? paymentType; @JsonKey(includeIfNull: false) final TransactionAgreement? agreement; + @JsonKey(name: "branding_options", includeIfNull: false) + final BrandingOptionsRequest? brandingOptions; CreateTransactionRequest({ required this.amount, @@ -49,6 +53,7 @@ class CreateTransactionRequest { this.cardAcceptanceCriteria, this.paymentType, this.agreement, + this.brandingOptions, }); @JsonKey(name: "card_acceptance_criteria", includeIfNull: false) diff --git a/Sample/lib/api/model/create_transaction_request.g.dart b/Sample/lib/api/model/create_transaction_request.g.dart index d875ad4..228adc2 100644 --- a/Sample/lib/api/model/create_transaction_request.g.dart +++ b/Sample/lib/api/model/create_transaction_request.g.dart @@ -39,6 +39,11 @@ CreateTransactionRequest _$CreateTransactionRequestFromJson( : TransactionAgreement.fromJson( json['agreement'] as Map, ), + brandingOptions: json['branding_options'] == null + ? null + : BrandingOptionsRequest.fromJson( + json['branding_options'] as Map, + ), ); Map _$CreateTransactionRequestToJson( @@ -58,6 +63,7 @@ Map _$CreateTransactionRequestToJson( 'language': instance.language, 'payment_type': ?_$TransactionPaymentTypeEnumMap[instance.paymentType], 'agreement': ?instance.agreement, + 'branding_options': ?instance.brandingOptions, 'card_acceptance_criteria': ?instance.cardAcceptanceCriteria, }; diff --git a/Sample/lib/api/model/pg_codes.dart b/Sample/lib/api/model/pg_codes.dart index be0929b..9c5e49b 100644 --- a/Sample/lib/api/model/pg_codes.dart +++ b/Sample/lib/api/model/pg_codes.dart @@ -8,12 +8,13 @@ enum PGCode { //urpay(code: "urpay", name: "Ur Pay"), tamara(code: "tamara", name: "Tamara"), tabby(code: "tabby", name: "Tabby"), + cod(code: "cod", name: "cod"), + jamiawallet(code: "jamiawallet", name: "jamiawallet"), + cs(code: "cs", name: "cs"), apple_pay(code: "apple-pay", name: "Apple Pay"), tap_pg(code: "tap_pg", name: "Tag PG"), - ottu_sdk(code: "ottu_sdk", name: "Ottu Sdk"), - cod(code: "cod", name: "cod"), - jamiawallet(code: "jamiawallet", name: "jamiawallet"); + ottu_sdk(code: "ottu_sdk", name: "Ottu Sdk"); const PGCode({required this.code, required this.name, this.inverselyRelated}); diff --git a/Sample/lib/feature/home/home_screen_cubit.dart b/Sample/lib/feature/home/home_screen_cubit.dart index 8b1b949..a14dabf 100644 --- a/Sample/lib/feature/home/home_screen_cubit.dart +++ b/Sample/lib/feature/home/home_screen_cubit.dart @@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart'; import 'package:logger/logger.dart'; import 'package:ottu_flutter_checkout/ottu_flutter_checkout.dart'; import 'package:ottu_flutter_checkout_sample/api/model/billing_address.dart'; +import 'package:ottu_flutter_checkout_sample/api/model/branding_options_request.dart'; import 'package:ottu_flutter_checkout_sample/api/model/create_transaction_request.dart'; import 'package:ottu_flutter_checkout_sample/api/model/pg_codes.dart'; import 'package:ottu_flutter_checkout_sample/api/model/transaction_agreement.dart'; @@ -78,6 +79,7 @@ class HomeScreenCubit extends Cubit { PGCode.tabby: true, PGCode.cod: true, PGCode.jamiawallet: true, + PGCode.cs: true, }), ), ) { @@ -124,6 +126,7 @@ class HomeScreenCubit extends Cubit { : null, paymentType: state.isAutoDebit == true ? TransactionPaymentType.autoDebit : null, agreement: state.isAutoDebit == true ? TransactionAgreement.defaultAgreement() : null, + brandingOptions: _brandingOptions(), ); final result = await _api.getSessionId( @@ -308,4 +311,99 @@ class HomeScreenCubit extends Cubit { return false; } } + + BrandingOptionsRequest? _brandingOptions() { + if (state.pgCodesChecked == null || state.pgCodesChecked?.isEmpty == true) { + return null; + } + + final brandingOptionsRequest = BrandingOptionsRequest(paymentMethods: BrandingPaymentMethods()); + state.pgCodesChecked?.forEach((code, isSelected) { + if(isSelected) { + switch (code) { + case PGCode.knet: + brandingOptionsRequest.paymentMethods.knetStaging = BrandingOption( + text: "Branding text for KNet", + color: "#009DCC", + fontWeight: 700, + ); + case PGCode.mpgs: + brandingOptionsRequest.paymentMethods.mpgs = BrandingOption( + text: "Branding text for MPGS", + color: "#92CC00", + fontWeight: 400, + ); + case PGCode.benefit: + /* brandingOptionsRequest.paymentMethods.benefit = BrandingOption( + text: "Branding text for Benefit", + color: "#006400", + fontWeight: 900, + );*/ + case PGCode.benefitpay: + /* brandingOptionsRequest.paymentMethods.benefitpay = BrandingOption( + text: "Branding text for BenefitPay", + color: "#48D1CC", + fontWeight: 900, + );*/ + case PGCode.stc_pay: + brandingOptionsRequest.paymentMethods.stcPay = BrandingOption( + text: "Branding text for STC", + color: "#FF00FF", + fontWeight: 600, + ); + case PGCode.nbk_mpgs: + brandingOptionsRequest.paymentMethods.nbkMpgs = BrandingOption( + text: "Branding text for NBK", + color: "#FFFF00", + fontWeight: 600, + ); + case PGCode.tamara: + brandingOptionsRequest.paymentMethods.tamara = BrandingOption( + text: "Branding text for Tamara", + color: "#A52A2A", + fontWeight: 600, + ); + case PGCode.tabby: + brandingOptionsRequest.paymentMethods.tabby = BrandingOption( + text: "Branding text for Tabby", + color: "#6A5ACD", + fontWeight: 600, + ); + case PGCode.cod: + brandingOptionsRequest.paymentMethods.cod = BrandingOption( + text: "Branding text for cod", + color: "#92CC00", + fontWeight: 400, + ); + case PGCode.jamiawallet: + brandingOptionsRequest.paymentMethods.jamiawallet = BrandingOption( + text: "Branding text for jamia", + color: "#708090", + fontWeight: 700, + ); + case PGCode.cs: + brandingOptionsRequest.paymentMethods.cs = BrandingOption( + text: "Branding text for cs", + color: "#D2691E", + fontWeight: 300, + ); + case PGCode.apple_pay: + case PGCode.tap_pg: + brandingOptionsRequest.paymentMethods.tapPg = BrandingOption( + text: "Branding text for Tap", + color: "#808000", + fontWeight: 500, + ); + case PGCode.ottu_sdk: + brandingOptionsRequest.paymentMethods.ottuSdk = BrandingOption( + text: "Branding text for Ottu", + color: "#2F4F4F", + fontWeight: 300, + ); + } + } + }); + + return brandingOptionsRequest; + } } diff --git a/Sample/lib/feature/theme/theme_customization_screen.dart b/Sample/lib/feature/theme/theme_customization_screen.dart index 09daec3..71b49c3 100644 --- a/Sample/lib/feature/theme/theme_customization_screen.dart +++ b/Sample/lib/feature/theme/theme_customization_screen.dart @@ -3,12 +3,15 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; +import 'package:logger/logger.dart'; import 'package:ottu_flutter_checkout/ottu_flutter_checkout.dart' as ch; import 'package:ottu_flutter_checkout_sample/feature/theme/android_fonts.dart'; import 'package:ottu_flutter_checkout_sample/feature/theme/ios_fonts.dart'; import 'package:ottu_flutter_checkout_sample/feature/theme/theme_customization_screen_cubit.dart'; import 'package:ottu_flutter_checkout_sample/feature/theme/theme_customization_state.dart'; +const _fontFamilies = ["Almarai Bold", "Almarai ExtraBold", "Almarai Light", "Almarai Regular"]; + class ThemeCustomizationScreen extends StatefulWidget { const ThemeCustomizationScreen({super.key}); @@ -16,12 +19,11 @@ class ThemeCustomizationScreen extends StatefulWidget { State createState() => _ThemeCustomizationScreenState(); } -const dividerPadding = 2.0; +const dividerPadding = 4.0; class _ThemeCustomizationScreenState extends State with TickerProviderStateMixin { - final amountEditingController = TextEditingController(); - + final _logger = Logger(); final uiModeController = TextEditingController(); @override @@ -290,6 +292,18 @@ class _ThemeCustomizationScreenState extends State context.read().onThemeChanged(newTheme); }, ), + divider(), + const SizedBox(height: dividerPadding), + _colorOptionItem( + state.theme?.paymentItemDescriptionTextColor?.color, + "Select Payment Description Color", + (color) { + final newTheme = (state.theme ?? ch.CheckoutTheme()).copyWith( + paymentItemDescriptionTextColor: ch.ColorState(color: color), + ); + context.read().onThemeChanged(newTheme); + }, + ), ], ); }, @@ -513,6 +527,45 @@ class _ThemeCustomizationScreenState extends State ), const SizedBox(height: dividerPadding), subDivider(), + ValueListenableBuilder( + valueListenable: btn, + builder: (context, btnValue, __) => + _colorOptionItem(btnValue?.borderColor?.color, "Button Border Color", (color) { + final button = (btnValue ?? ch.ButtonComponent()); + btn.value = button.copyWith( + borderColor: (button.borderColor ?? ch.ColorState()).copyWith(color: color), + ); + }), + ), + const SizedBox(height: dividerPadding), + subDivider(), + const SizedBox(height: dividerPadding), + _numberModifier("Button Border Width", button?.borderWidth, (number) { + final component = btn.value ?? ch.ButtonComponent(); + btn.value = component.copyWith(borderWidth: number); + }), + const SizedBox(height: dividerPadding), + subDivider(), + const SizedBox(height: dividerPadding), + _numberModifier("Button Corner Radius", button?.cornerRadius, (number) { + final component = btn.value ?? ch.ButtonComponent(); + btn.value = component.copyWith(cornerRadius: number); + }), + const SizedBox(height: dividerPadding), + subDivider(), + const SizedBox(height: dividerPadding), + _dropDownModifier( + "Button Font Name", + _fontFamilies, + "Button Font Family", + btn.value?.fontFamily, + (selection) { + final component = btn.value ?? ch.ButtonComponent(); + btn.value = component.copyWith(fontFamily: selection); + }, + ), + const SizedBox(height: dividerPadding), + subDivider(), const SizedBox(height: dividerPadding), ValueListenableBuilder( valueListenable: btn, @@ -799,6 +852,52 @@ class _ThemeCustomizationScreenState extends State ); } + Widget _numberModifier(String title, double? number, Function(double number) onChange) { + final controller = TextEditingController(text: number?.toString() ?? ""); + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible(child: Text(title)), + _numberInput(controller, (newNumber) { + final nd = double.tryParse(newNumber); + if (nd != null) { + onChange(nd); + _logger.d(nd); + } + }), + ], + ); + } + + SizedBox _numberInput( + TextEditingController controller, + Function(String newNumber) onTextChanged, + ) { + return SizedBox( + width: 64, + child: TextFormField( + maxLength: 4, + textAlign: TextAlign.center, + controller: controller, + decoration: InputDecoration( + counterText: "", + isDense: true, + contentPadding: EdgeInsets.symmetric(vertical: 4, horizontal: 5), + fillColor: Colors.white, + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.blue[800] ?? Colors.black26), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.blue[500] ?? Colors.black26, width: 2.0), + ), + ), + keyboardType: TextInputType.number, + textInputAction: TextInputAction.done, + onFieldSubmitted: onTextChanged, + ), + ); + } + Divider subDivider() => Divider(height: 1, thickness: 1, color: Colors.lightBlue[100], endIndent: 0); @@ -873,8 +972,6 @@ class _ThemeCustomizationScreenState extends State value: font, elevation: 4, isExpanded: true, - //style: const TextStyle(color: Colors.deepPurple), - //underline: Container(height: 2, color: Colors.deepPurpleAccent), onChanged: (String? value) { selectedFontFamily.value = value!; }, @@ -935,6 +1032,51 @@ class _ThemeCustomizationScreenState extends State ], ); } + + Widget _dropDownModifier( + String s, + List values, + String title, + String? selection, + Function(String selection) onSelected, + ) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible(child: Text(title)), + _dropDown(values, selection, onSelected), + ], + ); + } + + Widget _dropDown(List values, String? selection, Function(String selection) onSelected) { + final selectionNotifier = ValueNotifier(selection); + return ValueListenableBuilder( + valueListenable: selectionNotifier, + builder: (context, defaultSelection, child) { + return DropdownButton( + value: defaultSelection, + items: values.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value, style: TextStyle(fontSize: 12)), + ); + }).toList(), + onChanged: (String? newValue) { + if (newValue != null) { + onSelected(newValue); + selectionNotifier.value = newValue; + } + }, + + icon: Icon(Icons.arrow_downward, color: Colors.lightBlueAccent), + elevation: 16, + style: TextStyle(color: Colors.deepPurple, fontSize: 12), + underline: Container(height: 2, color: Colors.lightBlueAccent), + ); + }, + ); + } } class CrossingLinesPainter extends CustomPainter { diff --git a/Sample/pubspec.yaml b/Sample/pubspec.yaml index 8e9507f..abf73f5 100644 --- a/Sample/pubspec.yaml +++ b/Sample/pubspec.yaml @@ -19,7 +19,9 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+2 environment: - sdk: ^3.9.0 + sdk: ^3.10.0 + flutter: ">=3.38.0" + # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -46,14 +48,13 @@ dependencies: equatable: ^2.0.0 dio: ^5.7.0 json_annotation: ^4.9.0 - logger: 2.4.0 + logger: ^2.7.0 flutter_colorpicker: ^1.1.0 provider: 6.1.2 get_it: 8.2.0 intl: ^0.20.2 dev_dependencies: - build_runner: ^2.5.1 json_serializable: ^6.9.5 flutter_launcher_icons: ^0.14.4 diff --git a/android/src/main/kotlin/com/ottu/flutter/checkout/CheckoutView.kt b/android/src/main/kotlin/com/ottu/flutter/checkout/CheckoutView.kt index 9c935be..e83dea9 100644 --- a/android/src/main/kotlin/com/ottu/flutter/checkout/CheckoutView.kt +++ b/android/src/main/kotlin/com/ottu/flutter/checkout/CheckoutView.kt @@ -27,11 +27,11 @@ import com.squareup.moshi.JsonAdapter import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.platform.PlatformView +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.concurrent.atomic.AtomicBoolean @@ -319,11 +319,12 @@ internal class CheckoutView( selectPaymentMethodHeaderBackgroundColor = selectPaymentMethodHeaderBackgroundColor?.toCheckoutColor(), modalBackgroundColor = modalBackgroundColor?.toCheckoutColor(), paymentItemBackgroundColor = paymentItemBackgroundColor?.toCheckoutColor(), + paymentItemDescriptionTextColor = paymentItemDescriptionTextColor?.toCheckoutColor(), selectorIconColor = selectorIconColor?.toCheckoutColor(), savePhoneNumberIconColor = savePhoneNumberIconColor?.toCheckoutColor(), - button = button?.toCheckoutButton(), + button = button?.toCheckoutButton(resources, packageName), backButton = backButton?.toCheckoutRipple(), - selectorButton = selectorButton?.toCheckoutButton(), + selectorButton = selectorButton?.toCheckoutButton(resources, packageName), switch = switchControl?.toCheckoutSwitch() ) }, @@ -351,9 +352,9 @@ internal class CheckoutView( paymentItemBackgroundColor = paymentItemBackgroundColor?.toCheckoutColor(), selectorIconColor = selectorIconColor?.toCheckoutColor(), savePhoneNumberIconColor = savePhoneNumberIconColor?.toCheckoutColor(), - button = button?.toCheckoutButton(), + button = button?.toCheckoutButton(resources, packageName), backButton = backButton?.toCheckoutRipple(), - selectorButton = selectorButton?.toCheckoutButton(), + selectorButton = selectorButton?.toCheckoutButton(resources, packageName), switch = switchControl?.toCheckoutSwitch() ) }) diff --git a/android/src/main/kotlin/com/ottu/flutter/checkout/CustomerTheme.kt b/android/src/main/kotlin/com/ottu/flutter/checkout/CustomerTheme.kt index d53c7fa..1f007bf 100644 --- a/android/src/main/kotlin/com/ottu/flutter/checkout/CustomerTheme.kt +++ b/android/src/main/kotlin/com/ottu/flutter/checkout/CustomerTheme.kt @@ -19,6 +19,7 @@ data class CustomerTheme( val modalBackgroundColor: ColorState?, val selectPaymentMethodHeaderBackgroundColor: ColorState?, val paymentItemBackgroundColor: ColorState?, + val paymentItemDescriptionTextColor: ColorState?, val selectorIconColor: ColorState?, val savePhoneNumberIconColor: ColorState?, val button: ButtonComponent?, @@ -68,8 +69,11 @@ data class Margins( @Serializable data class ButtonComponent( val rippleColor: RippleColor? = null, - val fontType: Int? = null, + val fontFamily: String? = null, val textColor: ColorState? = null, + val borderColor: ColorState? = null, + val borderWidth: Float? = null, + val cornerRadius: Float? = null, ) @Serializable diff --git a/android/src/main/kotlin/com/ottu/flutter/checkout/ext/Extensions.kt b/android/src/main/kotlin/com/ottu/flutter/checkout/ext/Extensions.kt index 948dfd2..1098d72 100644 --- a/android/src/main/kotlin/com/ottu/flutter/checkout/ext/Extensions.kt +++ b/android/src/main/kotlin/com/ottu/flutter/checkout/ext/Extensions.kt @@ -12,9 +12,8 @@ import com.ottu.flutter.checkout.RippleColor import com.ottu.flutter.checkout.SwitchComponent import com.ottu.flutter.checkout.TextFieldStyle import com.ottu.flutter.checkout.TextStyle -import java.lang.Exception -import com.ottu.checkout.ui.theme.style.Margins as CheckoutMargins import com.ottu.checkout.data.model.localization.PayButtonText as pbt +import com.ottu.checkout.ui.theme.style.Margins as CheckoutMargins fun String.toColor() = this.let { try { @@ -30,14 +29,12 @@ fun ColorState.toCheckoutColor() = CheckoutTheme.Color( ) fun TextStyle.toCheckoutText(resources: Resources, packageName: String): CheckoutTheme.Text { - var fontResId: Int? = null; - try { - fontResId = resources.getIdentifier(this.fontFamily, "font", packageName) - } catch (e: Exception) { - Log.e("Extensions", "toCheckoutText", e) - } + val fontResId = this.fontFamily?.findFontResId(resources = resources, packageName = packageName) - return CheckoutTheme.Text(textColor = this.textColor?.toCheckoutColor(), fontType = fontResId) + return CheckoutTheme.Text( + textColor = this.textColor?.toCheckoutColor(), + fontType = fontResId + ) } fun TextFieldStyle.toCheckoutTextField(resources: Resources, packageName: String) = @@ -56,11 +53,20 @@ fun Margins.toMargins() = CheckoutMargins( bottom = this.bottom, ) -fun ButtonComponent.toCheckoutButton() = CheckoutTheme.Button( - textColor = this.textColor?.toCheckoutColor(), - rippleColor = this.rippleColor?.toCheckoutRipple(), - fontType = this.fontType -) +fun ButtonComponent.toCheckoutButton( + resources: Resources, + packageName: String, +): CheckoutTheme.Button { + val fontResId = this.fontFamily?.findFontResId(resources = resources, packageName = packageName) + return CheckoutTheme.Button( + textColor = this.textColor?.toCheckoutColor(), + rippleColor = this.rippleColor?.toCheckoutRipple(), + fontType = fontResId, + borderColor = this.borderColor?.toCheckoutColor(), + borderWidth = this.borderWidth, + cornerRadius = this.cornerRadius, + ) +} fun RippleColor.toCheckoutRipple() = CheckoutTheme.RippleColor( color = this.color?.toColor(), @@ -77,4 +83,13 @@ fun SwitchComponent.toCheckoutSwitch() = CheckoutTheme.Switch( uncheckedTrackDecorationColor = this.uncheckedTrackDecorationColor?.toColor() ) -fun PayButtonText.toPayButtonText() = pbt(en = en, ar = ar) \ No newline at end of file +fun PayButtonText.toPayButtonText() = pbt(en = en, ar = ar) + +fun String.findFontResId(resources: Resources, packageName: String) = try { + val sanitized = this.lowercase().replace(" ", "_") + println("findFontResId, with name: $sanitized") + resources.getIdentifier(sanitized, "font", packageName).let { if (it == 0) null else it } +} catch (e: Exception) { + Log.e("Extensions", "toCheckoutText", e) + null +} \ No newline at end of file diff --git a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutPlatformView.swift b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutPlatformView.swift index 87110a7..e6ab623 100644 --- a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutPlatformView.swift +++ b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutPlatformView.swift @@ -385,6 +385,12 @@ public class CheckoutPlatformView: NSObject, FlutterPlatformView { } } + if let color = theme?.paymentItemDescriptionTextColor?.toUIColors() { + if let cc = color { + cht.selectPaymentMethodDescriptionTextColor = cc + } + } + if let switchColor = theme?.switchControl?.toCheckoutSwitch() { cht.switchOnTintColor = switchColor } diff --git a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutViewFactory.swift b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutViewFactory.swift index cde24ec..c3593b5 100644 --- a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutViewFactory.swift +++ b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutViewFactory.swift @@ -5,24 +5,31 @@ // Created by Vi on 25.09.2024. // -import Foundation import Flutter +import Foundation + +public class CheckoutViewFactory: NSObject, + @preconcurrency FlutterPlatformViewFactory +{ -public class CheckoutViewFactory: NSObject, @preconcurrency FlutterPlatformViewFactory { - private var messenger: FlutterBinaryMessenger - + init(messenger: FlutterBinaryMessenger) { self.messenger = messenger + super.init() } - @MainActor public func create(withFrame frame: CGRect, - viewIdentifier viewId: Int64, - arguments args: Any?) -> FlutterPlatformView { - return CheckoutPlatformView(messenger: messenger, - frame: frame, - viewId: viewId, - args: args) + @MainActor public func create( + withFrame frame: CGRect, + viewIdentifier viewId: Int64, + arguments args: Any? + ) -> FlutterPlatformView { + return CheckoutPlatformView( + messenger: messenger, + frame: frame, + viewId: viewId, + args: args + ) } public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { diff --git a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CustomerTheme.swift b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CustomerTheme.swift index 23b4cd4..0dbe6b3 100644 --- a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CustomerTheme.swift +++ b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CustomerTheme.swift @@ -21,6 +21,7 @@ struct CustomerTheme: Decodable { let modalBackgroundColor: ColorState? let selectPaymentMethodHeaderBackgroundColor: ColorState? let paymentItemBackgroundColor: ColorState? + let paymentItemDescriptionTextColor: ColorState? let selectorIconColor: ColorState? let savePhoneNumberIconColor: ColorState? let button: ButtonCmt? @@ -64,9 +65,12 @@ struct Margins: Decodable { struct ButtonCmt: Decodable { let rippleColor: RippleColor? - let fontType: Int? + let fontFamily: String? let textColor: ColorState? let textDisabledColor: ColorState? + let borderColor: ColorState? + let borderWidth: Float? + let cornerRadius: Float? } struct SwitchComponent: Decodable { diff --git a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/ext.swift b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/ext.swift index 308739b..95c52e3 100644 --- a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/ext.swift +++ b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/ext.swift @@ -5,6 +5,7 @@ // Created by Vi on 29.10.2024. // import Foundation +import OSLog import SwiftUI import UIKit import ottu_checkout_sdk @@ -190,7 +191,7 @@ extension ButtonCmt { let textColors = self.textColor?.toUIColors() let buttonColor = self.rippleColor?.color?.toUIColor() let buttonDisabledColor = self.rippleColor?.colorDisabled?.toUIColor() - let fontType = self.fontType + let borderColor = self.borderColor?.toUIColors() if let btnC = buttonColor { bc.enabledBackgroundColor = btnC @@ -203,10 +204,32 @@ extension ButtonCmt { if let textColorNormal = textColors?.color { bc.enabledTitleColor = textColorNormal } + if let textColorDisabled = textColors?.disabledColor { bc.disabledTitleColor = textColorDisabled } + if let bColor = borderColor?.color { + bc.borderColor = bColor + } + + if let border = self.borderWidth { + bc.borderWidth = CGFloat(border) + } + + if let corner = self.cornerRadius { + bc.cornerRadius = CGFloat(corner) + } + + if let fontFamily = self.fontFamily { + let name = fontFamily.replacingOccurrences( + of: " ", + with: "-", + ) + bc.fontFamily = name + //Logger.sdk.debug("toCheckoutButton, name: \(name), set fontFamily: \(bc.fontFamily)") + } + return bc } } diff --git a/lib/src/checkout_arguments.g.dart b/lib/src/checkout_arguments.g.dart index 35ebe20..d1dd7cd 100644 --- a/lib/src/checkout_arguments.g.dart +++ b/lib/src/checkout_arguments.g.dart @@ -14,7 +14,8 @@ CheckoutArguments _$CheckoutArgumentsFromJson(Map json) => amount: (json['amount'] as num).toDouble(), showPaymentDetails: json['showPaymentDetails'] as bool, paymentOptionsDisplaySettings: PaymentOptionsDisplaySettings.fromJson( - json['paymentOptionsDisplaySettings'] as Map), + json['paymentOptionsDisplaySettings'] as Map, + ), setupPreload: json['apiTransactionDetails'] as String?, formsOfPayment: (json['formsOfPayment'] as List?) ?.map((e) => $enumDecode(_$FormsOfPaymentEnumMap, e)) @@ -25,7 +26,8 @@ CheckoutArguments _$CheckoutArgumentsFromJson(Map json) => payButtonText: json['payButtonText'] == null ? null : PayButtonText.fromJson( - json['payButtonText'] as Map), + json['payButtonText'] as Map, + ), ); Map _$CheckoutArgumentsToJson(CheckoutArguments instance) => diff --git a/lib/src/checkout_theme.dart b/lib/src/checkout_theme.dart index b760479..19067c9 100644 --- a/lib/src/checkout_theme.dart +++ b/lib/src/checkout_theme.dart @@ -32,6 +32,7 @@ class CheckoutTheme extends Equatable { final ColorState? modalBackgroundColor; final ColorState? selectPaymentMethodHeaderBackgroundColor; final ColorState? paymentItemBackgroundColor; + final ColorState? paymentItemDescriptionTextColor; final ColorState? selectorIconColor; final ColorState? savePhoneNumberIconColor; @@ -56,6 +57,7 @@ class CheckoutTheme extends Equatable { this.modalBackgroundColor, this.selectPaymentMethodHeaderBackgroundColor, this.paymentItemBackgroundColor, + this.paymentItemDescriptionTextColor, this.selectorIconColor, this.savePhoneNumberIconColor}); @@ -80,6 +82,7 @@ class CheckoutTheme extends Equatable { ColorState? modalBackgroundColor, ColorState? selectPaymentMethodHeaderBackgroundColor, ColorState? paymentItemBackgroundColor, + ColorState? paymentItemDescriptionTextColor, ColorState? selectorIconColor, ColorState? savePhoneNumberIconColor}) { return CheckoutTheme( @@ -102,9 +105,11 @@ class CheckoutTheme extends Equatable { margins: margins ?? this.margins, sdkBackgroundColor: sdkBackgroundColor ?? this.sdkBackgroundColor, modalBackgroundColor: modalBackgroundColor ?? this.modalBackgroundColor, - selectPaymentMethodHeaderBackgroundColor: selectPaymentMethodHeaderBackgroundColor ?? - this.selectPaymentMethodHeaderBackgroundColor, + selectPaymentMethodHeaderBackgroundColor: + selectPaymentMethodHeaderBackgroundColor ?? this.selectPaymentMethodHeaderBackgroundColor, paymentItemBackgroundColor: paymentItemBackgroundColor ?? this.paymentItemBackgroundColor, + paymentItemDescriptionTextColor: + paymentItemDescriptionTextColor ?? this.paymentItemDescriptionTextColor, selectorIconColor: selectorIconColor ?? this.selectorIconColor, savePhoneNumberIconColor: savePhoneNumberIconColor ?? this.savePhoneNumberIconColor, ); @@ -132,6 +137,7 @@ class CheckoutTheme extends Equatable { modalBackgroundColor, selectPaymentMethodHeaderBackgroundColor, paymentItemBackgroundColor, + paymentItemDescriptionTextColor, selectorIconColor, savePhoneNumberIconColor ]; @@ -256,16 +262,35 @@ final class TextFieldStyle { @JsonSerializable() class ButtonComponent { final RippleColor? rippleColor; - final int? fontType; + final String? fontFamily; final ColorState? textColor; - - ButtonComponent({this.rippleColor, this.fontType, this.textColor}); - - ButtonComponent copyWith({RippleColor? rippleColor, int? fontType, ColorState? textColor}) { + final ColorState? borderColor; + final double? borderWidth; + final double? cornerRadius; + + ButtonComponent( + {this.rippleColor, + this.fontFamily, + this.textColor, + this.borderColor, + this.borderWidth, + this.cornerRadius}); + + ButtonComponent copyWith( + {RippleColor? rippleColor, + String? fontFamily, + ColorState? textColor, + ColorState? borderColor, + double? borderWidth, + double? cornerRadius}) { return ButtonComponent( - rippleColor: rippleColor ?? this.rippleColor, - textColor: textColor ?? this.textColor, - fontType: fontType ?? this.fontType); + rippleColor: rippleColor ?? this.rippleColor, + textColor: textColor ?? this.textColor, + fontFamily: fontFamily ?? this.fontFamily, + borderColor: borderColor ?? this.borderColor, + borderWidth: borderWidth ?? this.borderWidth, + cornerRadius: cornerRadius ?? this.cornerRadius, + ); } factory ButtonComponent.fromJson(Map json) => _$ButtonComponentFromJson(json); diff --git a/lib/src/checkout_theme.g.dart b/lib/src/checkout_theme.g.dart index 012b26f..cd287fb 100644 --- a/lib/src/checkout_theme.g.dart +++ b/lib/src/checkout_theme.g.dart @@ -6,177 +6,203 @@ part of 'checkout_theme.dart'; // JsonSerializableGenerator // ************************************************************************** -CheckoutTheme _$CheckoutThemeFromJson(Map json) => - CheckoutTheme( - uiMode: json['uiMode'] == null - ? CustomerUiMode.auto - : const _UiModeJsonConverter().fromJson(json['uiMode'] as String), - titleText: json['titleText'] == null - ? null - : TextStyle.fromJson(json['titleText'] as Map), - mainTitleText: json['mainTitleText'] == null - ? null - : TextStyle.fromJson(json['mainTitleText'] as Map), - selectPaymentMethodHeaderText: json['selectPaymentMethodHeaderText'] == - null - ? null - : TextStyle.fromJson( - json['selectPaymentMethodHeaderText'] as Map), - subtitleText: json['subtitleText'] == null - ? null - : TextStyle.fromJson(json['subtitleText'] as Map), - feesTitleText: json['feesTitleText'] == null - ? null - : TextStyle.fromJson(json['feesTitleText'] as Map), - feesSubtitleText: json['feesSubtitleText'] == null - ? null - : TextStyle.fromJson( - json['feesSubtitleText'] as Map), - dataLabelText: json['dataLabelText'] == null - ? null - : TextStyle.fromJson(json['dataLabelText'] as Map), - dataValueText: json['dataValueText'] == null - ? null - : TextStyle.fromJson(json['dataValueText'] as Map), - errorMessageText: json['errorMessageText'] == null - ? null - : TextStyle.fromJson( - json['errorMessageText'] as Map), - inputTextField: json['inputTextField'] == null - ? null - : TextFieldStyle.fromJson( - json['inputTextField'] as Map), - button: json['button'] == null - ? null - : ButtonComponent.fromJson(json['button'] as Map), - backButton: json['backButton'] == null - ? null - : RippleColor.fromJson(json['backButton'] as Map), - selectorButton: json['selectorButton'] == null - ? null - : ButtonComponent.fromJson( - json['selectorButton'] as Map), - switchControl: json['switchControl'] == null - ? null - : SwitchComponent.fromJson( - json['switchControl'] as Map), - margins: json['margins'] == null - ? null - : Margins.fromJson(json['margins'] as Map), - sdkBackgroundColor: json['sdkBackgroundColor'] == null - ? null - : ColorState.fromJson( - json['sdkBackgroundColor'] as Map), - modalBackgroundColor: json['modalBackgroundColor'] == null - ? null - : ColorState.fromJson( - json['modalBackgroundColor'] as Map), - selectPaymentMethodHeaderBackgroundColor: - json['selectPaymentMethodHeaderBackgroundColor'] == null - ? null - : ColorState.fromJson( - json['selectPaymentMethodHeaderBackgroundColor'] - as Map), - paymentItemBackgroundColor: json['paymentItemBackgroundColor'] == null - ? null - : ColorState.fromJson( - json['paymentItemBackgroundColor'] as Map), - selectorIconColor: json['selectorIconColor'] == null - ? null - : ColorState.fromJson( - json['selectorIconColor'] as Map), - savePhoneNumberIconColor: json['savePhoneNumberIconColor'] == null - ? null - : ColorState.fromJson( - json['savePhoneNumberIconColor'] as Map), - ); +CheckoutTheme _$CheckoutThemeFromJson( + Map json, +) => CheckoutTheme( + uiMode: json['uiMode'] == null + ? CustomerUiMode.auto + : const _UiModeJsonConverter().fromJson(json['uiMode'] as String), + titleText: json['titleText'] == null + ? null + : TextStyle.fromJson(json['titleText'] as Map), + mainTitleText: json['mainTitleText'] == null + ? null + : TextStyle.fromJson(json['mainTitleText'] as Map), + selectPaymentMethodHeaderText: json['selectPaymentMethodHeaderText'] == null + ? null + : TextStyle.fromJson( + json['selectPaymentMethodHeaderText'] as Map, + ), + subtitleText: json['subtitleText'] == null + ? null + : TextStyle.fromJson(json['subtitleText'] as Map), + feesTitleText: json['feesTitleText'] == null + ? null + : TextStyle.fromJson(json['feesTitleText'] as Map), + feesSubtitleText: json['feesSubtitleText'] == null + ? null + : TextStyle.fromJson(json['feesSubtitleText'] as Map), + dataLabelText: json['dataLabelText'] == null + ? null + : TextStyle.fromJson(json['dataLabelText'] as Map), + dataValueText: json['dataValueText'] == null + ? null + : TextStyle.fromJson(json['dataValueText'] as Map), + errorMessageText: json['errorMessageText'] == null + ? null + : TextStyle.fromJson(json['errorMessageText'] as Map), + inputTextField: json['inputTextField'] == null + ? null + : TextFieldStyle.fromJson(json['inputTextField'] as Map), + button: json['button'] == null + ? null + : ButtonComponent.fromJson(json['button'] as Map), + backButton: json['backButton'] == null + ? null + : RippleColor.fromJson(json['backButton'] as Map), + selectorButton: json['selectorButton'] == null + ? null + : ButtonComponent.fromJson( + json['selectorButton'] as Map, + ), + switchControl: json['switchControl'] == null + ? null + : SwitchComponent.fromJson(json['switchControl'] as Map), + margins: json['margins'] == null + ? null + : Margins.fromJson(json['margins'] as Map), + sdkBackgroundColor: json['sdkBackgroundColor'] == null + ? null + : ColorState.fromJson(json['sdkBackgroundColor'] as Map), + modalBackgroundColor: json['modalBackgroundColor'] == null + ? null + : ColorState.fromJson( + json['modalBackgroundColor'] as Map, + ), + selectPaymentMethodHeaderBackgroundColor: + json['selectPaymentMethodHeaderBackgroundColor'] == null + ? null + : ColorState.fromJson( + json['selectPaymentMethodHeaderBackgroundColor'] + as Map, + ), + paymentItemBackgroundColor: json['paymentItemBackgroundColor'] == null + ? null + : ColorState.fromJson( + json['paymentItemBackgroundColor'] as Map, + ), + paymentItemDescriptionTextColor: + json['paymentItemDescriptionTextColor'] == null + ? null + : ColorState.fromJson( + json['paymentItemDescriptionTextColor'] as Map, + ), + selectorIconColor: json['selectorIconColor'] == null + ? null + : ColorState.fromJson(json['selectorIconColor'] as Map), + savePhoneNumberIconColor: json['savePhoneNumberIconColor'] == null + ? null + : ColorState.fromJson( + json['savePhoneNumberIconColor'] as Map, + ), +); -Map _$CheckoutThemeToJson(CheckoutTheme instance) => - { - 'uiMode': const _UiModeJsonConverter().toJson(instance.uiMode), - 'mainTitleText': instance.mainTitleText, - 'selectPaymentMethodHeaderText': instance.selectPaymentMethodHeaderText, - 'titleText': instance.titleText, - 'subtitleText': instance.subtitleText, - 'feesTitleText': instance.feesTitleText, - 'feesSubtitleText': instance.feesSubtitleText, - 'dataLabelText': instance.dataLabelText, - 'dataValueText': instance.dataValueText, - 'errorMessageText': instance.errorMessageText, - 'inputTextField': instance.inputTextField, - 'button': instance.button, - 'backButton': instance.backButton, - 'selectorButton': instance.selectorButton, - 'switchControl': instance.switchControl, - 'margins': instance.margins, - 'sdkBackgroundColor': instance.sdkBackgroundColor, - 'modalBackgroundColor': instance.modalBackgroundColor, - 'selectPaymentMethodHeaderBackgroundColor': - instance.selectPaymentMethodHeaderBackgroundColor, - 'paymentItemBackgroundColor': instance.paymentItemBackgroundColor, - 'selectorIconColor': instance.selectorIconColor, - 'savePhoneNumberIconColor': instance.savePhoneNumberIconColor, - }; +Map _$CheckoutThemeToJson( + CheckoutTheme instance, +) => { + 'uiMode': const _UiModeJsonConverter().toJson(instance.uiMode), + 'mainTitleText': instance.mainTitleText, + 'selectPaymentMethodHeaderText': instance.selectPaymentMethodHeaderText, + 'titleText': instance.titleText, + 'subtitleText': instance.subtitleText, + 'feesTitleText': instance.feesTitleText, + 'feesSubtitleText': instance.feesSubtitleText, + 'dataLabelText': instance.dataLabelText, + 'dataValueText': instance.dataValueText, + 'errorMessageText': instance.errorMessageText, + 'inputTextField': instance.inputTextField, + 'button': instance.button, + 'backButton': instance.backButton, + 'selectorButton': instance.selectorButton, + 'switchControl': instance.switchControl, + 'margins': instance.margins, + 'sdkBackgroundColor': instance.sdkBackgroundColor, + 'modalBackgroundColor': instance.modalBackgroundColor, + 'selectPaymentMethodHeaderBackgroundColor': + instance.selectPaymentMethodHeaderBackgroundColor, + 'paymentItemBackgroundColor': instance.paymentItemBackgroundColor, + 'paymentItemDescriptionTextColor': instance.paymentItemDescriptionTextColor, + 'selectorIconColor': instance.selectorIconColor, + 'savePhoneNumberIconColor': instance.savePhoneNumberIconColor, +}; ColorState _$ColorStateFromJson(Map json) => ColorState( - color: _$JsonConverterFromJson( - json['color'], const _ColorJsonConverter().fromJson), - colorDisabled: _$JsonConverterFromJson( - json['colorDisabled'], const _ColorJsonConverter().fromJson), - ); + color: _$JsonConverterFromJson( + json['color'], + const _ColorJsonConverter().fromJson, + ), + colorDisabled: _$JsonConverterFromJson( + json['colorDisabled'], + const _ColorJsonConverter().fromJson, + ), +); Map _$ColorStateToJson(ColorState instance) => { 'color': _$JsonConverterToJson( - instance.color, const _ColorJsonConverter().toJson), + instance.color, + const _ColorJsonConverter().toJson, + ), 'colorDisabled': _$JsonConverterToJson( - instance.colorDisabled, const _ColorJsonConverter().toJson), + instance.colorDisabled, + const _ColorJsonConverter().toJson, + ), }; Value? _$JsonConverterFromJson( Object? json, Value? Function(Json json) fromJson, -) => - json == null ? null : fromJson(json as Json); +) => json == null ? null : fromJson(json as Json); Json? _$JsonConverterToJson( Value? value, Json? Function(Value value) toJson, -) => - value == null ? null : toJson(value); +) => value == null ? null : toJson(value); RippleColor _$RippleColorFromJson(Map json) => RippleColor( - color: _$JsonConverterFromJson( - json['color'], const _ColorJsonConverter().fromJson), - rippleColor: _$JsonConverterFromJson( - json['rippleColor'], const _ColorJsonConverter().fromJson), - colorDisabled: _$JsonConverterFromJson( - json['colorDisabled'], const _ColorJsonConverter().fromJson), - ); + color: _$JsonConverterFromJson( + json['color'], + const _ColorJsonConverter().fromJson, + ), + rippleColor: _$JsonConverterFromJson( + json['rippleColor'], + const _ColorJsonConverter().fromJson, + ), + colorDisabled: _$JsonConverterFromJson( + json['colorDisabled'], + const _ColorJsonConverter().fromJson, + ), +); Map _$RippleColorToJson(RippleColor instance) => { 'color': _$JsonConverterToJson( - instance.color, const _ColorJsonConverter().toJson), + instance.color, + const _ColorJsonConverter().toJson, + ), 'rippleColor': _$JsonConverterToJson( - instance.rippleColor, const _ColorJsonConverter().toJson), + instance.rippleColor, + const _ColorJsonConverter().toJson, + ), 'colorDisabled': _$JsonConverterToJson( - instance.colorDisabled, const _ColorJsonConverter().toJson), + instance.colorDisabled, + const _ColorJsonConverter().toJson, + ), }; TextStyle _$TextStyleFromJson(Map json) => TextStyle( - textColor: json['textColor'] == null - ? null - : ColorState.fromJson(json['textColor'] as Map), - fontFamily: json['fontFamily'] as String?, - fontSize: (json['fontSize'] as num?)?.toInt(), - ); + textColor: json['textColor'] == null + ? null + : ColorState.fromJson(json['textColor'] as Map), + fontFamily: json['fontFamily'] as String?, + fontSize: (json['fontSize'] as num?)?.toInt(), +); Map _$TextStyleToJson(TextStyle instance) => { - 'textColor': instance.textColor, - 'fontFamily': instance.fontFamily, - 'fontSize': instance.fontSize, - }; + 'textColor': instance.textColor, + 'fontFamily': instance.fontFamily, + 'fontSize': instance.fontSize, +}; TextFieldStyle _$TextFieldStyleFromJson(Map json) => TextFieldStyle( @@ -211,67 +237,93 @@ ButtonComponent _$ButtonComponentFromJson(Map json) => rippleColor: json['rippleColor'] == null ? null : RippleColor.fromJson(json['rippleColor'] as Map), - fontType: (json['fontType'] as num?)?.toInt(), + fontFamily: json['fontFamily'] as String?, textColor: json['textColor'] == null ? null : ColorState.fromJson(json['textColor'] as Map), + borderColor: json['borderColor'] == null + ? null + : ColorState.fromJson(json['borderColor'] as Map), + borderWidth: (json['borderWidth'] as num?)?.toDouble(), + cornerRadius: (json['cornerRadius'] as num?)?.toDouble(), ); Map _$ButtonComponentToJson(ButtonComponent instance) => { 'rippleColor': instance.rippleColor, - 'fontType': instance.fontType, + 'fontFamily': instance.fontFamily, 'textColor': instance.textColor, + 'borderColor': instance.borderColor, + 'borderWidth': instance.borderWidth, + 'cornerRadius': instance.cornerRadius, }; SwitchComponent _$SwitchComponentFromJson(Map json) => SwitchComponent( checkedThumbTintColor: _$JsonConverterFromJson( - json['checkedThumbTintColor'], const _ColorJsonConverter().fromJson), + json['checkedThumbTintColor'], + const _ColorJsonConverter().fromJson, + ), uncheckedThumbTintColor: _$JsonConverterFromJson( - json['uncheckedThumbTintColor'], - const _ColorJsonConverter().fromJson), + json['uncheckedThumbTintColor'], + const _ColorJsonConverter().fromJson, + ), checkedTrackTintColor: _$JsonConverterFromJson( - json['checkedTrackTintColor'], const _ColorJsonConverter().fromJson), + json['checkedTrackTintColor'], + const _ColorJsonConverter().fromJson, + ), uncheckedTrackTintColor: _$JsonConverterFromJson( - json['uncheckedTrackTintColor'], - const _ColorJsonConverter().fromJson), + json['uncheckedTrackTintColor'], + const _ColorJsonConverter().fromJson, + ), checkedTrackDecorationColor: _$JsonConverterFromJson( - json['checkedTrackDecorationColor'], - const _ColorJsonConverter().fromJson), + json['checkedTrackDecorationColor'], + const _ColorJsonConverter().fromJson, + ), uncheckedTrackDecorationColor: _$JsonConverterFromJson( - json['uncheckedTrackDecorationColor'], - const _ColorJsonConverter().fromJson), + json['uncheckedTrackDecorationColor'], + const _ColorJsonConverter().fromJson, + ), ); Map _$SwitchComponentToJson(SwitchComponent instance) => { 'checkedThumbTintColor': _$JsonConverterToJson( - instance.checkedThumbTintColor, const _ColorJsonConverter().toJson), + instance.checkedThumbTintColor, + const _ColorJsonConverter().toJson, + ), 'uncheckedThumbTintColor': _$JsonConverterToJson( - instance.uncheckedThumbTintColor, const _ColorJsonConverter().toJson), + instance.uncheckedThumbTintColor, + const _ColorJsonConverter().toJson, + ), 'checkedTrackTintColor': _$JsonConverterToJson( - instance.checkedTrackTintColor, const _ColorJsonConverter().toJson), + instance.checkedTrackTintColor, + const _ColorJsonConverter().toJson, + ), 'uncheckedTrackTintColor': _$JsonConverterToJson( - instance.uncheckedTrackTintColor, const _ColorJsonConverter().toJson), + instance.uncheckedTrackTintColor, + const _ColorJsonConverter().toJson, + ), 'checkedTrackDecorationColor': _$JsonConverterToJson( - instance.checkedTrackDecorationColor, - const _ColorJsonConverter().toJson), + instance.checkedTrackDecorationColor, + const _ColorJsonConverter().toJson, + ), 'uncheckedTrackDecorationColor': _$JsonConverterToJson( - instance.uncheckedTrackDecorationColor, - const _ColorJsonConverter().toJson), + instance.uncheckedTrackDecorationColor, + const _ColorJsonConverter().toJson, + ), }; Margins _$MarginsFromJson(Map json) => Margins( - left: (json['left'] as num?)?.toInt() ?? 0, - top: (json['top'] as num?)?.toInt() ?? 0, - right: (json['right'] as num?)?.toInt() ?? 0, - bottom: (json['bottom'] as num?)?.toInt() ?? 0, - ); + left: (json['left'] as num?)?.toInt() ?? 0, + top: (json['top'] as num?)?.toInt() ?? 0, + right: (json['right'] as num?)?.toInt() ?? 0, + bottom: (json['bottom'] as num?)?.toInt() ?? 0, +); Map _$MarginsToJson(Margins instance) => { - 'left': instance.left, - 'top': instance.top, - 'right': instance.right, - 'bottom': instance.bottom, - }; + 'left': instance.left, + 'top': instance.top, + 'right': instance.right, + 'bottom': instance.bottom, +}; diff --git a/lib/src/pay_button_text.g.dart b/lib/src/pay_button_text.g.dart index bc0a5ae..c2f4ddf 100644 --- a/lib/src/pay_button_text.g.dart +++ b/lib/src/pay_button_text.g.dart @@ -7,13 +7,7 @@ part of 'pay_button_text.dart'; // ************************************************************************** PayButtonText _$PayButtonTextFromJson(Map json) => - PayButtonText( - en: json['en'] as String, - ar: json['ar'] as String, - ); + PayButtonText(en: json['en'] as String, ar: json['ar'] as String); Map _$PayButtonTextToJson(PayButtonText instance) => - { - 'en': instance.en, - 'ar': instance.ar, - }; + {'en': instance.en, 'ar': instance.ar}; diff --git a/lib/src/payment_options_display_settings.g.dart b/lib/src/payment_options_display_settings.g.dart index b2d2e58..5409f0c 100644 --- a/lib/src/payment_options_display_settings.g.dart +++ b/lib/src/payment_options_display_settings.g.dart @@ -7,20 +7,20 @@ part of 'payment_options_display_settings.dart'; // ************************************************************************** PaymentOptionsDisplaySettings _$PaymentOptionsDisplaySettingsFromJson( - Map json) => - PaymentOptionsDisplaySettings( - mode: $enumDecode(_$PaymentOptionsDisplayModeEnumMap, json['mode']), - defaultSelectedPgCode: json['defaultSelectedPgCode'] as String?, - visibleItemsCount: (json['visibleItemsCount'] as num).toInt(), - ); + Map json, +) => PaymentOptionsDisplaySettings( + mode: $enumDecode(_$PaymentOptionsDisplayModeEnumMap, json['mode']), + defaultSelectedPgCode: json['defaultSelectedPgCode'] as String?, + visibleItemsCount: (json['visibleItemsCount'] as num).toInt(), +); Map _$PaymentOptionsDisplaySettingsToJson( - PaymentOptionsDisplaySettings instance) => - { - 'mode': _$PaymentOptionsDisplayModeEnumMap[instance.mode]!, - 'defaultSelectedPgCode': instance.defaultSelectedPgCode, - 'visibleItemsCount': instance.visibleItemsCount, - }; + PaymentOptionsDisplaySettings instance, +) => { + 'mode': _$PaymentOptionsDisplayModeEnumMap[instance.mode]!, + 'defaultSelectedPgCode': instance.defaultSelectedPgCode, + 'visibleItemsCount': instance.visibleItemsCount, +}; const _$PaymentOptionsDisplayModeEnumMap = { PaymentOptionsDisplayMode.LIST: 'list', diff --git a/pubspec.yaml b/pubspec.yaml index 2ed52ba..3f920e3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ^3.6.0 + sdk: ^3.8.0 # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -31,9 +31,9 @@ dependencies: flutter: sdk: flutter - logger: ^2.4.0 + logger: ^2.7.0 equatable: ^2.0.0 - json_annotation: ^4.9.0 + json_annotation: ^4.11.0 dev_dependencies: From 8a6fd624a7922046f4a8376e11410d98097d862c Mon Sep 17 00:00:00 2001 From: viktor Date: Fri, 27 Mar 2026 07:26:39 +0200 Subject: [PATCH 2/2] fix color assignment --- .../Sources/ottu_flutter_checkout/CheckoutPlatformView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutPlatformView.swift b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutPlatformView.swift index e6ab623..66fa937 100644 --- a/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutPlatformView.swift +++ b/ios/ottu_flutter_checkout/Sources/ottu_flutter_checkout/CheckoutPlatformView.swift @@ -386,7 +386,7 @@ public class CheckoutPlatformView: NSObject, FlutterPlatformView { } if let color = theme?.paymentItemDescriptionTextColor?.toUIColors() { - if let cc = color { + if let cc = color.color { cht.selectPaymentMethodDescriptionTextColor = cc } }