creating a ftue version of the policy fragment

This commit is contained in:
Adam Brown 2022-04-06 16:37:48 +01:00
parent 11dbd0e80c
commit 06147967a4
4 changed files with 264 additions and 3 deletions

View file

@ -116,6 +116,7 @@ import im.vector.app.features.onboarding.ftueauth.FtueAuthUseCaseFragment
import im.vector.app.features.onboarding.ftueauth.FtueAuthWaitForEmailFragment
import im.vector.app.features.onboarding.ftueauth.FtueAuthWebFragment
import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthLegacyStyleTermsFragment
import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthTermsFragment
import im.vector.app.features.pin.PinFragment
import im.vector.app.features.poll.create.CreatePollFragment
import im.vector.app.features.qrcode.QrCodeScannerFragment
@ -481,7 +482,12 @@ interface FragmentModule {
@Binds
@IntoMap
@FragmentKey(FtueAuthLegacyStyleTermsFragment::class)
fun bindFtueAuthTermsFragment(fragment: FtueAuthLegacyStyleTermsFragment): Fragment
fun bindFtueAuthLegacyStyleTermsFragment(fragment: FtueAuthLegacyStyleTermsFragment): Fragment
@Binds
@IntoMap
@FragmentKey(FtueAuthTermsFragment::class)
fun bindFtueAuthTermsFragment(fragment: FtueAuthTermsFragment): Fragment
@Binds
@IntoMap

View file

@ -52,6 +52,7 @@ import im.vector.app.features.onboarding.OnboardingViewEvents
import im.vector.app.features.onboarding.OnboardingViewModel
import im.vector.app.features.onboarding.OnboardingViewState
import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthLegacyStyleTermsFragment
import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthTermsFragment
import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthTermsLegacyStyleFragmentArgument
import org.matrix.android.sdk.api.auth.registration.FlowResult
import org.matrix.android.sdk.api.auth.registration.Stage
@ -397,14 +398,27 @@ class FtueAuthVariant(
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption
)
is Stage.Terms -> activity.addFragmentToBackstack(
is Stage.Terms -> onTerms(stage)
else -> Unit // Should not happen
}
}
private fun onTerms(stage: Stage.Terms) {
when {
vectorFeatures.isOnboardingCombinedRegisterEnabled() -> activity.addFragmentToBackstack(
views.loginFragmentContainer,
FtueAuthTermsFragment::class.java,
FtueAuthTermsLegacyStyleFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(R.string.resources_language))),
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption
)
else -> activity.addFragmentToBackstack(
views.loginFragmentContainer,
FtueAuthLegacyStyleTermsFragment::class.java,
FtueAuthTermsLegacyStyleFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(R.string.resources_language))),
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption
)
else -> Unit // Should not happen
}
}

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.onboarding.ftueauth.terms
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.args
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.toReducedUrl
import im.vector.app.core.utils.openUrlInChromeCustomTab
import im.vector.app.databinding.FragmentFtueLoginTermsBinding
import im.vector.app.features.login.terms.LocalizedFlowDataLoginTermsChecked
import im.vector.app.features.login.terms.LoginTermsViewState
import im.vector.app.features.login.terms.PolicyController
import im.vector.app.features.onboarding.OnboardingAction
import im.vector.app.features.onboarding.OnboardingViewState
import im.vector.app.features.onboarding.RegisterAction
import im.vector.app.features.onboarding.ftueauth.AbstractFtueAuthFragment
import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms
import javax.inject.Inject
/**
* LoginTermsFragment displays the list of policies the user has to accept
*/
class FtueAuthTermsFragment @Inject constructor(
private val policyController: PolicyController
) : AbstractFtueAuthFragment<FragmentFtueLoginTermsBinding>(),
PolicyController.PolicyControllerListener {
private val params: FtueAuthTermsLegacyStyleFragmentArgument by args()
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueLoginTermsBinding {
return FragmentFtueLoginTermsBinding.inflate(inflater, container, false)
}
private var loginTermsViewState: LoginTermsViewState = LoginTermsViewState(emptyList())
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupViews()
views.loginTermsPolicyList.configureWith(policyController, hasFixedSize = false)
policyController.listener = this
val list = ArrayList<LocalizedFlowDataLoginTermsChecked>()
params.localizedFlowDataLoginTerms
.forEach {
list.add(LocalizedFlowDataLoginTermsChecked(it))
}
loginTermsViewState = LoginTermsViewState(list)
}
private fun setupViews() {
views.displayNameSubmit.setOnClickListener { submit() }
views.loginTermsPolicyList.setHasFixedSize(false)
}
override fun onDestroyView() {
views.loginTermsPolicyList.cleanup()
policyController.listener = null
super.onDestroyView()
}
private fun renderState() {
policyController.setData(loginTermsViewState.localizedFlowDataLoginTermsChecked)
// Button is enabled only if all checkboxes are checked
views.displayNameSubmit.isEnabled = loginTermsViewState.allChecked()
}
override fun setChecked(localizedFlowDataLoginTerms: LocalizedFlowDataLoginTerms, isChecked: Boolean) {
if (isChecked) {
loginTermsViewState.check(localizedFlowDataLoginTerms)
} else {
loginTermsViewState.uncheck(localizedFlowDataLoginTerms)
}
renderState()
}
override fun openPolicy(localizedFlowDataLoginTerms: LocalizedFlowDataLoginTerms) {
localizedFlowDataLoginTerms.localizedUrl
?.takeIf { it.isNotBlank() }
?.let {
openUrlInChromeCustomTab(requireContext(), null, it)
}
}
private fun submit() {
viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.AcceptTerms))
}
override fun updateWithState(state: OnboardingViewState) {
policyController.homeServer = state.selectedHomeserver.userFacingUrl.toReducedUrl()
renderState()
}
override fun resetViewModel() {
viewModel.handle(OnboardingAction.ResetAuthenticationAttempt)
}
}

View file

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/LoginFormScrollView"
android:layout_height="match_parent"
android:background="?android:colorBackground"
android:fillViewport="true"
android:paddingTop="0dp"
android:paddingBottom="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/contentRoot"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/displayNameGutterStart"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintGuide_percent="@dimen/ftue_auth_gutter_start_percent" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/displayNameGutterEnd"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintGuide_percent="@dimen/ftue_auth_gutter_end_percent" />
<Space
android:id="@+id/headerSpacing"
android:layout_width="match_parent"
android:layout_height="52dp"
app:layout_constraintBottom_toTopOf="@id/displayNameHeaderIcon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0"
app:layout_constraintVertical_chainStyle="packed" />
<ImageView
android:id="@+id/displayNameHeaderIcon"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:adjustViewBounds="true"
android:background="@drawable/circle"
android:backgroundTint="?colorSecondary"
android:contentDescription="@null"
android:src="@drawable/ic_user_fg"
app:layout_constraintBottom_toTopOf="@id/displayNameHeaderTitle"
app:layout_constraintEnd_toEndOf="@id/displayNameGutterEnd"
app:layout_constraintHeight_percent="0.12"
app:layout_constraintStart_toStartOf="@id/displayNameGutterStart"
app:layout_constraintTop_toBottomOf="@id/headerSpacing"
app:tint="@color/palette_white" />
<TextView
android:id="@+id/displayNameHeaderTitle"
style="@style/Widget.Vector.TextView.Title.Medium"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="Our privacy policy"
android:textColor="?vctr_content_primary"
app:layout_constraintBottom_toTopOf="@id/displayNameHeaderSubtitle"
app:layout_constraintEnd_toEndOf="@id/displayNameGutterEnd"
app:layout_constraintStart_toStartOf="@id/displayNameGutterStart"
app:layout_constraintTop_toBottomOf="@id/displayNameHeaderIcon" />
<TextView
android:id="@+id/displayNameHeaderSubtitle"
style="@style/Widget.Vector.TextView.Subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="@string/auth_accept_policies"
android:textColor="?vctr_content_secondary"
app:layout_constraintBottom_toTopOf="@id/titleContentSpacing"
app:layout_constraintEnd_toEndOf="@id/displayNameGutterEnd"
app:layout_constraintStart_toStartOf="@id/displayNameGutterStart"
app:layout_constraintTop_toBottomOf="@id/displayNameHeaderTitle" />
<Space
android:id="@+id/titleContentSpacing"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/loginTermsPolicyList"
app:layout_constraintHeight_percent="0.03"
app:layout_constraintTop_toBottomOf="@id/displayNameHeaderSubtitle" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/loginTermsPolicyList"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/entrySpacing"
app:layout_constraintEnd_toEndOf="@id/displayNameGutterEnd"
app:layout_constraintStart_toStartOf="@id/displayNameGutterStart"
app:layout_constraintTop_toBottomOf="@id/titleContentSpacing" />
<Space
android:id="@+id/entrySpacing"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/displayNameSubmit"
app:layout_constraintHeight_percent="0.03"
app:layout_constraintTop_toBottomOf="@id/loginTermsPolicyList" />
<Button
android:id="@+id/displayNameSubmit"
style="@style/Widget.Vector.Button.Login"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/login_signup_submit"
android:textAllCaps="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/displayNameGutterEnd"
app:layout_constraintStart_toStartOf="@id/displayNameGutterStart"
app:layout_constraintTop_toBottomOf="@id/entrySpacing" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>