Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videostreaming/futopayclientlibraries
  • alex/futopayclientlibraries
2 results
Show changes
Commits on Source (11)
Showing
with 78 additions and 565 deletions
# Default ignored files
/shelf/
/workspace.xml
PolycentricCore
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidTestResultsUserPreferences">
<option name="androidTestResultsTableState">
<map>
<entry key="-2030737957">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1888365331">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1766545009">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1603504896">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1533817792">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1348472475">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1191746456">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1089424001">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1030942155">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Pixel_C_API_33" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1013244967">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-998275601">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-693989101">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-483192549">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-396783379">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Pixel_C_API_33" value="120" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-285941453">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-43042216">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="143109477">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="217836404">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="309039273">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="568179418">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="728115857">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="762617096">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="1154603043">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="1367930197">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="1392532197">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="1445499490">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="1489134328">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="1814633309">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="1823866028">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="1824280393">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="1956518097">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Pixel_3a_API_33_x86_64" value="120" />
<entry key="R5CNC07TZCY" value="120" />
<entry key="Tests" value="360" />
<entry key="samsung&#10; SM-G998B" value="120" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="2076253436">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
</map>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_C_API_33.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-08-03T14:42:06.113626110Z" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="Embedded JDK" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.7.20" />
</component>
</project>
\ No newline at end of file
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.10'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.8.20'
}
android {
......@@ -9,8 +9,8 @@ android {
compileSdk 33
defaultConfig {
minSdk 26
targetSdk 32
minSdk 24
targetSdk 33
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
......@@ -31,10 +31,10 @@ android {
}
dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1'
implementation 'androidx.recyclerview:recyclerview:1.3.0'
implementation 'com.caverock:androidsvg-aar:1.4'
implementation 'com.google.code.gson:gson:2.10.1'
......
package com.futo.futopay
import android.util.Base64
import java.lang.Exception
import java.security.KeyFactory
import java.security.PublicKey
import java.security.Signature
......@@ -20,6 +21,10 @@ class LicenseValidator(publicKey: String) {
sig.initVerify(_publicPaymentKey);
sig.update(licenseKey.toByteArray());
return sig.verify(java.util.Base64.getUrlDecoder().decode(activationKey)!!);
return try {
sig.verify(java.util.Base64.getUrlDecoder().decode(activationKey)!!)
} catch(e: Exception) {
false
}
}
}
\ No newline at end of file
package com.futo.futopay
import android.content.Context
import android.util.Log
import android.view.ViewGroup
import androidx.activity.ComponentActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.lifecycleScope
import com.stripe.android.PaymentConfiguration
import com.stripe.android.paymentsheet.PaymentSheet
......@@ -11,58 +14,61 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
interface PaymentStatusListener {
fun onSuccess(purchaseId: String?);
fun onCancel();
fun onFailure(error: Throwable);
}
class PaymentManager {
private val _fragment: Fragment;
private val _overlayContainer: ViewGroup;
private val _sheet: PaymentSheet;
private val _paymentState: PaymentState;
private val _listener: PaymentStatusListener;
private var _lastPurchaseId: String? = null;
constructor(paymentState: PaymentState, fragment: Fragment, overlayContainer: ViewGroup, onCompleted: (success: Boolean, purchaseId: String?, exception: Throwable?)->Unit) {
constructor(paymentState: PaymentState, fragment: Fragment, overlayContainer: ViewGroup, listener: PaymentStatusListener) {
_fragment = fragment;
_paymentState = paymentState;
_overlayContainer = overlayContainer;
_listener = listener;
_sheet = PaymentSheet(_fragment) { paymentSheetResult ->
when(paymentSheetResult) {
is PaymentSheetResult.Canceled -> {
_listener.onCancel();
}
is PaymentSheetResult.Failed -> {
onCompleted(false, null, paymentSheetResult.error)
_listener.onFailure(paymentSheetResult.error);
}
is PaymentSheetResult.Completed -> {
onCompleted(true, _lastPurchaseId,null);
_listener.onSuccess(_lastPurchaseId);
}
}
};
}
fun startPayment(paymentState: PaymentState, scope: CoroutineScope, productId: String) {
scope.launch(Dispatchers.IO){
try{
val availableCurrencies = _paymentState.getAvailableCurrencies(productId);
val country = paymentState.getPaymentCountryFromIP()?.let { c -> PaymentConfigurations.COUNTRIES.find { it.id.equals(c, ignoreCase = true) } };
withContext(Dispatchers.Main) {
SlideUpPayment.startPayment(paymentState, _overlayContainer, productId, country, availableCurrencies) { method, request ->
SlideUpPayment.startPayment(paymentState, _overlayContainer, productId, country, availableCurrencies, { method, request ->
when(method) {
"stripe" -> startPaymentStripe(productId, request.currency, request.mail, request.country, request.zipcode);
}
};
}, { _listener.onCancel() });
}
}
catch(ex: Throwable) {
Log.e(TAG, "startPayment failed", ex);
scope.launch(Dispatchers.Main){
UIDialogs.showGeneralErrorDialog(_fragment.requireContext(), "Failed to get required payment data", ex);
UIDialogs.showGeneralErrorDialog(_fragment.requireContext(), "Failed to get required payment data (did you grant the app network permission?)", ex, onOk = { _listener.onCancel() });
}
}
}
......
......@@ -64,10 +64,13 @@ abstract class PaymentState {
}
fun setPaymentLicenseUrl(url: String): Boolean {
var urlToUse = if(url.startsWith("grayjay://", true))
url.substring("grayjay://".length);
else
val protocolIndex = url.indexOf("://");
var urlToUse = if(protocolIndex == -1) {
url;
} else {
url.substring(protocolIndex + "://".length);
}
if(urlToUse.startsWith("license/", true))
urlToUse = urlToUse.substring("license/".length);
......
......@@ -54,7 +54,7 @@ class SlideUpPayment : RelativeLayout {
private var _isVisible = false;
var onOK: (() -> Unit)? = null;
var onCancel: (() -> Unit)? = null;
var onCancel: (() -> Unit)? = SlideUpPayment._onCancel;
constructor(paymentState: PaymentState, context: Context, parent: ViewGroup, titleText: String, okText: String?, vararg items: View): super(context){
init(paymentState, okText);
......@@ -86,7 +86,9 @@ class SlideUpPayment : RelativeLayout {
private var _currentSlideUpPayment: SlideUpPayment? = null;
private val _animationDuration = 300L;
fun startPayment(paymentState: PaymentState, overlayContainer: ViewGroup, productId: String, country: PaymentConfigurations.CountryDescriptor?, currencies: List<String>? = null, onSelected: (String, PaymentManager.PaymentRequest)->Unit) {
private var _onCancel: (() -> Unit)? = null;
fun startPayment(paymentState: PaymentState, overlayContainer: ViewGroup, productId: String, country: PaymentConfigurations.CountryDescriptor?, currencies: List<String>? = null, onSelected: (String, PaymentManager.PaymentRequest)->Unit, onCancel: () -> Unit) {
_productId = productId;
_paymentMethod = null;
_country = country;
......@@ -94,6 +96,7 @@ class SlideUpPayment : RelativeLayout {
_currency = country?.let { c -> PaymentConfigurations.CURRENCIES.find { it.id == c.defaultCurrencyId && (_currencies?.contains(it.id) ?: true) } };
_postalCode = null;
_onSelected = onSelected;
_onCancel = onCancel;
_currentSlideUpPayment = null;
requestNext(paymentState, overlayContainer);
......
......@@ -10,6 +10,7 @@ import android.widget.EditText
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import com.futo.futopay.PaymentBreakdown
......@@ -32,7 +33,7 @@ class PaymentCheckoutView : ConstraintLayout {
private val editEmail: EditText
private val layoutBreakdown: LinearLayout
private val layoutLoader: FrameLayout
private val imageLoader: ImageView
private val imageLoader: View
private val textError: TextView
private val textEmailSubtext: TextView
private val textPostalCodeHeader: TextView
......@@ -83,10 +84,10 @@ class PaymentCheckoutView : ConstraintLayout {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val text = editEmail.text.toString();
_isValid = emailRegex.matches(text);
_isValid = emailRegex.matches(text.lowercase());
if (_isValid) {
textEmailSubtext.setTextColor(Color.rgb(0x99, 0x99, 0x99));
textEmailSubtext.setText("Required to accurately calculate the applicable sales tax");
textEmailSubtext.setText("Required to send the license key");
buttonPay.alpha = 1.0f;
} else {
textEmailSubtext.setTextColor(Color.rgb(0xFF, 0x00, 0x00));
......@@ -134,14 +135,14 @@ class PaymentCheckoutView : ConstraintLayout {
textError.visibility = View.GONE
layoutBreakdown.visibility = View.GONE
layoutLoader.visibility = View.VISIBLE
(imageLoader.drawable as Animatable?)?.start()
imageLoader.visibility = View.VISIBLE
return;
}
val currency = PaymentConfigurations.CURRENCIES.find { it.id == paymentBreakdown.currency };
val symbol = currency?.symbol ?: "";
(imageLoader.drawable as Animatable?)?.stop()
imageLoader.visibility = View.GONE
layoutLoader.visibility = View.GONE
textError.visibility = View.GONE
layoutBreakdown.visibility = View.VISIBLE
......@@ -156,7 +157,7 @@ class PaymentCheckoutView : ConstraintLayout {
fun setError(error: String) {
editEmail.text.clear()
buttonPay.alpha = 0.4f
(imageLoader.drawable as Animatable?)?.stop()
imageLoader.visibility = View.GONE
layoutLoader.visibility = View.GONE
layoutBreakdown.visibility = View.GONE
textError.visibility = View.VISIBLE
......
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1500"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:repeatMode="restart"
android:repeatCount="infinite"
android:interpolator="@android:anim/linear_interpolator" />
\ No newline at end of file
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:repeatMode="restart"
android:repeatCount="infinite"
android:interpolator="@android:anim/linear_interpolator" />
\ No newline at end of file
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2500"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="-360"
android:repeatMode="restart"
android:repeatCount="infinite"
android:interpolator="@android:anim/linear_interpolator" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#2F2F2F" />
<corners android:radius="6dp" />
<corners android:radius="@dimen/button_corners" />
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/button_black" />
<corners android:radius="@dimen/button_corners" />
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
\ No newline at end of file