From 72bc263d8a0f15f41133e7e66e809afd37ac466a Mon Sep 17 00:00:00 2001
From: Taras Smakula <tarassmakula@gmail.com>
Date: Thu, 4 Jan 2024 16:33:52 +0200
Subject: [PATCH] Update select signup type to handle free or paid flows

---
 .../auth/feature/sign_up/SignUpDataSource.kt  |  1 +
 .../SelectSignUpTypeDataSource.kt             | 31 +++++++++-
 .../sign_up_type/SelectSignUpTypeFragment.kt  | 41 +++++++------
 .../sign_up_type/SelectSignUpTypeViewModel.kt |  9 ++-
 .../layout/fragment_select_sign_up_type.xml   | 59 +++++++++++--------
 auth/src/main/res/values/strings.xml          |  5 +-
 6 files changed, 96 insertions(+), 50 deletions(-)

diff --git a/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpDataSource.kt
index f918bc02a..fc3ea29dd 100644
--- a/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/SignUpDataSource.kt
@@ -143,6 +143,7 @@ class SignUpDataSource @Inject constructor(
     }
 
     companion object {
+        const val REGISTRATION_FREE_TYPE = "org.futo.subscriptions.free_forever"
         const val REGISTRATION_TOKEN_TYPE = "m.login.registration_token"
         const val REGISTRATION_SUBSCRIPTION_TYPE = "org.futo.subscription.google_play"
         const val REGISTRATION_EMAIL_REQUEST_TOKEN_TYPE = "m.enroll.email.request_token"
diff --git a/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
index e4fcd63c8..5e5a0abaf 100644
--- a/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeDataSource.kt
@@ -4,9 +4,12 @@ import android.content.Context
 import dagger.hilt.android.qualifiers.ApplicationContext
 import org.futo.circles.auth.R
 import org.futo.circles.auth.feature.sign_up.SignUpDataSource
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_FREE_TYPE
+import org.futo.circles.auth.feature.sign_up.SignUpDataSource.Companion.REGISTRATION_SUBSCRIPTION_TYPE
 import org.futo.circles.core.extensions.createResult
 import org.futo.circles.core.provider.MatrixInstanceProvider
 import org.futo.circles.core.utils.HomeServerUtils.buildHomeServerConfigFromDomain
+import org.matrix.android.sdk.api.auth.registration.Stage
 import javax.inject.Inject
 
 class SelectSignUpTypeDataSource @Inject constructor(
@@ -14,19 +17,41 @@ class SelectSignUpTypeDataSource @Inject constructor(
     private val signUpDataSource: SignUpDataSource
 ) {
 
+    private var registrationFlowsForDomain: Pair<String, List<List<Stage>>>? = null
+
     fun clearSubtitle() {
         signUpDataSource.clearSubtitle()
     }
 
-    suspend fun startNewRegistration(domain: String) = createResult {
+    suspend fun getAuthFlowsFor(domain: String) = createResult {
+        registrationFlowsForDomain = null
         val authService = MatrixInstanceProvider.matrix.authenticationService().apply {
             cancelPendingLoginOrRegistration()
             initiateAuth(buildHomeServerConfigFromDomain(domain))
         }
-        val stages = authService.getRegistrationWizard().getAllRegistrationFlows().firstOrNull()
-            ?: throw IllegalArgumentException(context.getString(R.string.wrong_signup_config))
+        authService.getRegistrationWizard().getAllRegistrationFlows().also {
+            registrationFlowsForDomain = domain to it
+        }
+    }
+
+    suspend fun startNewRegistration(isSubscription: Boolean) = createResult {
+        val (domain, flows) = registrationFlowsForDomain ?: throw IllegalArgumentException(
+            context.getString(R.string.wrong_signup_config)
+        )
+        val stages = if (isSubscription) getSubscriptionSignupStages(flows)
+        else getFreeSignupStages(flows)
+
+        stages ?: throw IllegalArgumentException(context.getString(R.string.wrong_signup_config))
 
         signUpDataSource.startSignUpStages(stages, domain)
     }
 
+    // Must start with org.futo.subscriptions.free_forever
+    private fun getFreeSignupStages(flows: List<List<Stage>>): List<Stage>? =
+        flows.firstOrNull { (it.firstOrNull() as? Stage.Other)?.type == REGISTRATION_FREE_TYPE }
+
+    // Must start with org.futo.subscription.google_play
+    private fun getSubscriptionSignupStages(flows: List<List<Stage>>): List<Stage>? =
+        flows.firstOrNull { (it.firstOrNull() as? Stage.Other)?.type == REGISTRATION_SUBSCRIPTION_TYPE }
+
 }
\ No newline at end of file
diff --git a/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
index 47eefff35..21b158251 100644
--- a/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeFragment.kt
@@ -1,11 +1,12 @@
 package org.futo.circles.auth.feature.sign_up.sign_up_type
 
 import android.os.Bundle
-import android.text.Html
 import android.view.View
+import androidx.core.view.children
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.viewModels
 import by.kirich1409.viewbindingdelegate.viewBinding
+import com.google.android.material.radiobutton.MaterialRadioButton
 import dagger.hilt.android.AndroidEntryPoint
 import org.futo.circles.auth.R
 import org.futo.circles.auth.databinding.FragmentSelectSignUpTypeBinding
@@ -31,18 +32,25 @@ class SelectSignUpTypeFragment : Fragment(R.layout.fragment_select_sign_up_type)
 
     private fun setupViews() {
         with(binding) {
-            btnEU.text = Html.fromHtml(
-                getString(R.string.eu_server_format, CirclesAppConfig.euServerDomain),
-                Html.FROM_HTML_MODE_COMPACT
-            )
-            btnUS.text =
-                Html.fromHtml(
-                    getString(R.string.us_server_format, CirclesAppConfig.usServerDomain),
-                    Html.FROM_HTML_MODE_COMPACT
+            serverDomainGroup.setOnCheckedChangeListener { _, _ ->
+                viewModel.loadSignupFlowsForDomain(getDomain())
+            }
+            CirclesAppConfig.serverDomains.forEach { domain ->
+                serverDomainGroup.addView(
+                    MaterialRadioButton(requireContext()).apply {
+                        text = domain
+                        textSize = 20f
+                    }
                 )
-            btnSignup.setOnClickListener {
-                startLoading(btnSignup)
-                viewModel.startSignUp(getDomain())
+            }
+            serverDomainGroup.check(serverDomainGroup.children.first().id)
+            btnSubscription.setOnClickListener {
+                startLoading(btnSubscription)
+                viewModel.startSignUp(true)
+            }
+            btnFree.setOnClickListener {
+                startLoading(btnFree)
+                viewModel.startSignUp(false)
             }
         }
     }
@@ -51,9 +59,8 @@ class SelectSignUpTypeFragment : Fragment(R.layout.fragment_select_sign_up_type)
         viewModel.startSignUpEventLiveData.observeResponse(this)
     }
 
-    private fun getDomain() = when (binding.serverLocationGroup.checkedRadioButtonId) {
-        binding.btnUS.id -> CirclesAppConfig.usServerDomain
-        binding.btnEU.id -> CirclesAppConfig.euServerDomain
-        else -> CirclesAppConfig.usServerDomain
-    }
+    private fun getDomain() =
+        binding.serverDomainGroup
+            .findViewById<MaterialRadioButton>(binding.serverDomainGroup.checkedRadioButtonId).text.toString()
+
 }
\ No newline at end of file
diff --git a/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
index 79e0b26ff..89d7513d4 100644
--- a/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
+++ b/auth/src/main/java/org/futo/circles/auth/feature/sign_up/sign_up_type/SelectSignUpTypeViewModel.kt
@@ -14,9 +14,10 @@ class SelectSignUpTypeViewModel @Inject constructor(
 
     val startSignUpEventLiveData = SingleEventLiveData<Response<Unit?>>()
 
-    fun startSignUp(serverDomain: String) {
+    fun startSignUp(isSubscription: Boolean) {
         launchBg {
-            startSignUpEventLiveData.postValue(dataSource.startNewRegistration(serverDomain))
+            val result = dataSource.startNewRegistration(isSubscription)
+            startSignUpEventLiveData.postValue(result)
         }
     }
 
@@ -24,4 +25,8 @@ class SelectSignUpTypeViewModel @Inject constructor(
         dataSource.clearSubtitle()
     }
 
+    fun loadSignupFlowsForDomain(domain: String) {
+        launchBg { dataSource.getAuthFlowsFor(domain) }
+    }
+
 }
\ No newline at end of file
diff --git a/auth/src/main/res/layout/fragment_select_sign_up_type.xml b/auth/src/main/res/layout/fragment_select_sign_up_type.xml
index 41faa2fff..c79ca4f15 100644
--- a/auth/src/main/res/layout/fragment_select_sign_up_type.xml
+++ b/auth/src/main/res/layout/fragment_select_sign_up_type.xml
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingHorizontal="24dp"
@@ -26,53 +25,63 @@
 
 
     <TextView
-        android:id="@+id/tvServerLocationTitle"
+        android:id="@+id/tvServerTitle"
         style="@style/headline"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="16dp"
-        android:text="@string/server_location"
+        android:text="@string/server"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@id/guidelineLogo" />
 
     <RadioGroup
-        android:id="@+id/serverLocationGroup"
+        android:id="@+id/serverDomainGroup"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="vertical"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/tvServerLocationTitle">
+        app:layout_constraintTop_toBottomOf="@id/tvServerTitle" />
 
-        <com.google.android.material.radiobutton.MaterialRadioButton
-            android:id="@+id/btnUS"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:checked="true"
-            android:paddingHorizontal="8dp"
-            android:textSize="17sp"
-            tools:text="US some.server.domain" />
 
-        <com.google.android.material.radiobutton.MaterialRadioButton
-            android:id="@+id/btnEU"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:paddingHorizontal="8dp"
-            android:textSize="17sp"
-            tools:text="EU - (some.server.domain)" />
-
-    </RadioGroup>
+    <org.futo.circles.core.view.LoadingButton
+        android:id="@+id/btnFree"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="24dp"
+        android:text="@string/sign_up_for_free"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/serverDomainGroup" />
 
+    <TextView
+        android:id="@+id/tvOr"
+        style="@style/headline"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:gravity="center"
+        android:text="@string/or"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/btnFree" />
 
     <org.futo.circles.core.view.LoadingButton
-        android:id="@+id/btnSignup"
+        android:id="@+id/btnSubscription"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginTop="24dp"
+        android:layout_marginTop="8dp"
         android:text="@string/sign_up_with_subscription"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/serverLocationGroup" />
+        app:layout_constraintTop_toBottomOf="@id/tvOr" />
+
+    <androidx.constraintlayout.widget.Group
+        android:id="@+id/groupFree"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:constraint_referenced_ids="tvOr,btnFree" />
+
 
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/auth/src/main/res/values/strings.xml b/auth/src/main/res/values/strings.xml
index cd4e34c60..c66157042 100644
--- a/auth/src/main/res/values/strings.xml
+++ b/auth/src/main/res/values/strings.xml
@@ -14,8 +14,6 @@
     <string name="us_server_format"><![CDATA[<b>US</b> - (%s)]]></string>
     <string name="eu_server_format"><![CDATA[<b>EU</b> - (%s)]]></string>
     <string name="sign_up_using_active_subscription">Sign Up using your active subscription</string>
-    <string name="choose_a_subscription">Choose a subscription</string>
-    <string name="create_a_subscription">Create a subscription</string>
     <string name="sign_up">Sign Up</string>
     <string name="not_supported_stage_format">Not supported stage %s</string>
     <string name="sign_up_stage_subtitle_format">Stage %1$d of %2$d</string>
@@ -61,8 +59,9 @@
     <string name="enter_your_password">Enter your password</string>
     <string name="password">Password</string>
     <string name="repeat_password">Repeat password</string>
-    <string name="server_location">Server Location</string>
+    <string name="server">Server</string>
     <string name="sign_up_with_subscription">Sign up with subscription</string>
+    <string name="sign_up_for_free">Sign up for free</string>
     <string name="or">Or</string>
     <string name="setup_profile">Setup profile</string>
     <string name="upload_a_profile_photo">Upload a profile photo</string>
-- 
GitLab