diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index e0cd8f7919..22cddf84ce 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -3333,6 +3333,8 @@
Scan QR code
Use the camera on this device to scan the QR code shown on your other device:
+ Sign in with QR code
+ Use your signed in device to scan the QR code below:
Secure connection established
Check your signed in device, the code below should be displayed. Confirm that the code below matches with that device:
Open Element on your other device
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginAction.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginAction.kt
index 948a771118..d946f744cf 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginAction.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginAction.kt
@@ -20,4 +20,6 @@ import im.vector.app.core.platform.VectorViewModelAction
sealed class QrCodeLoginAction : VectorViewModelAction {
data class OnQrCodeScanned(val qrCode: String) : QrCodeLoginAction()
+ object QrCodeViewStarted : QrCodeLoginAction()
+ object ShowQrCode : QrCodeLoginAction()
}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginActivity.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginActivity.kt
index 5e359bfb26..18efdca4ef 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginActivity.kt
@@ -23,7 +23,7 @@ import android.view.View
import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.viewModel
import dagger.hilt.android.AndroidEntryPoint
-import im.vector.app.core.extensions.addFragment
+import im.vector.app.core.extensions.addFragmentToBackstack
import im.vector.app.core.platform.SimpleFragmentActivity
@AndroidEntryPoint
@@ -38,10 +38,11 @@ class QrCodeLoginActivity : SimpleFragmentActivity() {
val qrCodeLoginArgs: QrCodeLoginArgs? = intent?.extras?.getParcelable(Mavericks.KEY_ARG)
if (isFirstCreation()) {
if (qrCodeLoginArgs?.loginType == QrCodeLoginType.LOGIN) {
- addFragment(
+ addFragmentToBackstack(
views.container,
QrCodeLoginInstructionsFragment::class.java,
- qrCodeLoginArgs
+ qrCodeLoginArgs,
+ tag = FRAGMENT_QR_CODE_INSTRUCTIONS_TAG
)
}
}
@@ -53,19 +54,33 @@ class QrCodeLoginActivity : SimpleFragmentActivity() {
viewModel.observeViewEvents {
when (it) {
QrCodeLoginViewEvents.NavigateToStatusScreen -> handleNavigateToStatusScreen()
+ QrCodeLoginViewEvents.NavigateToShowQrCodeScreen -> handleNavigateToShowQrCodeScreen()
}
}
}
- private fun handleNavigateToStatusScreen() {
- addFragment(
+ private fun handleNavigateToShowQrCodeScreen() {
+ addFragmentToBackstack(
views.container,
- QrCodeLoginStatusFragment::class.java
+ QrCodeLoginShowQrCodeFragment::class.java,
+ tag = FRAGMENT_SHOW_QR_CODE_TAG
+ )
+ }
+
+ private fun handleNavigateToStatusScreen() {
+ addFragmentToBackstack(
+ views.container,
+ QrCodeLoginStatusFragment::class.java,
+ tag = FRAGMENT_QR_CODE_STATUS_TAG
)
}
companion object {
+ private const val FRAGMENT_QR_CODE_INSTRUCTIONS_TAG = "FRAGMENT_QR_CODE_INSTRUCTIONS_TAG"
+ private const val FRAGMENT_SHOW_QR_CODE_TAG = "FRAGMENT_SHOW_QR_CODE_TAG"
+ private const val FRAGMENT_QR_CODE_STATUS_TAG = "FRAGMENT_QR_CODE_STATUS_TAG"
+
fun getIntent(context: Context, qrCodeLoginArgs: QrCodeLoginArgs): Intent {
return Intent(context, QrCodeLoginActivity::class.java).apply {
putExtra(Mavericks.KEY_ARG, qrCodeLoginArgs)
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt
index 99dea345eb..c9cf59a7d5 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginInstructionsFragment.kt
@@ -23,23 +23,32 @@ import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.fragmentViewModel
+import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentQrCodeLoginInstructionsBinding
import im.vector.app.features.qrcode.QrCodeScannerActivity
import timber.log.Timber
+@AndroidEntryPoint
class QrCodeLoginInstructionsFragment : VectorBaseFragment() {
private val viewModel: QrCodeLoginViewModel by activityViewModel()
+ override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentQrCodeLoginInstructionsBinding {
+ return FragmentQrCodeLoginInstructionsBinding.inflate(inflater, container, false)
+ }
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initScanQrCodeButton()
+ initShowQrCodeButton()
}
- override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentQrCodeLoginInstructionsBinding {
- return FragmentQrCodeLoginInstructionsBinding.inflate(inflater, container, false)
+ private fun initShowQrCodeButton() {
+ views.qrCodeLoginInstructionsShowQrCodeButton.debouncedClicks {
+ viewModel.handle(QrCodeLoginAction.ShowQrCode)
+ }
}
private fun initScanQrCodeButton() {
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginShowQrCodeFragment.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginShowQrCodeFragment.kt
new file mode 100644
index 0000000000..69fd8bde81
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginShowQrCodeFragment.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.login.qr
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.airbnb.mvrx.activityViewModel
+import dagger.hilt.android.AndroidEntryPoint
+import im.vector.app.core.platform.VectorBaseFragment
+import im.vector.app.databinding.FragmentQrCodeLoginShowQrCodeBinding
+
+@AndroidEntryPoint
+class QrCodeLoginShowQrCodeFragment : VectorBaseFragment() {
+
+ private val viewModel: QrCodeLoginViewModel by activityViewModel()
+
+ override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentQrCodeLoginShowQrCodeBinding {
+ return FragmentQrCodeLoginShowQrCodeBinding.inflate(inflater, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ initCancelButton()
+ observeViewState()
+ viewModel.handle(QrCodeLoginAction.QrCodeViewStarted)
+ }
+
+ private fun initCancelButton() {
+ views.qrCodeLoginShowQrCodeCancelButton.debouncedClicks {
+ activity?.supportFragmentManager?.popBackStack()
+ }
+ }
+
+ private fun observeViewState() {
+ viewModel.onEach {
+ it.generatedQrCodeData?.let { qrCodeData ->
+ showQrCode(qrCodeData)
+ }
+ }
+ }
+
+ private fun showQrCode(qrCodeData: String) {
+ views.qrCodeLoginSHowQrCodeImageView.setData(qrCodeData)
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginStatusFragment.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginStatusFragment.kt
index 52abfa788c..fa9ea1351e 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginStatusFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginStatusFragment.kt
@@ -22,11 +22,13 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import com.airbnb.mvrx.activityViewModel
+import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentQrCodeLoginStatusBinding
import im.vector.app.features.themes.ThemeUtils
+@AndroidEntryPoint
class QrCodeLoginStatusFragment : VectorBaseFragment() {
private val viewModel: QrCodeLoginViewModel by activityViewModel()
@@ -46,7 +48,7 @@ class QrCodeLoginStatusFragment : VectorBaseFragment handleConnectionEstablished(it.connectionStatus)
QrCodeLoginConnectionStatus.ConnectingToDevice -> handleConnectingToDevice()
QrCodeLoginConnectionStatus.SigningIn -> handleSigningIn()
- null -> TODO()
+ null -> { /* NOOP */ }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewEvents.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewEvents.kt
index b8ebb65308..dc258408e7 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewEvents.kt
@@ -20,4 +20,5 @@ import im.vector.app.core.platform.VectorViewEvents
sealed class QrCodeLoginViewEvents : VectorViewEvents {
object NavigateToStatusScreen : QrCodeLoginViewEvents()
+ object NavigateToShowQrCodeScreen : QrCodeLoginViewEvents()
}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewModel.kt
index ac3b68da15..29a258823b 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewModel.kt
@@ -40,6 +40,21 @@ class QrCodeLoginViewModel @AssistedInject constructor(
override fun handle(action: QrCodeLoginAction) {
when (action) {
is QrCodeLoginAction.OnQrCodeScanned -> handleOnQrCodeScanned(action)
+ QrCodeLoginAction.QrCodeViewStarted -> handleQrCodeViewStarted()
+ QrCodeLoginAction.ShowQrCode -> handleShowQrCode()
+ }
+ }
+
+ private fun handleShowQrCode() {
+ _viewEvents.post(QrCodeLoginViewEvents.NavigateToShowQrCodeScreen)
+ }
+
+ private fun handleQrCodeViewStarted() {
+ val qrCodeData = generateQrCodeData()
+ setState {
+ copy(
+ generatedQrCodeData = qrCodeData
+ )
}
}
@@ -84,4 +99,11 @@ class QrCodeLoginViewModel @AssistedInject constructor(
private fun isValidQrCode(qrCode: String): Boolean {
return qrCode.startsWith("http")
}
+
+ /**
+ * TODO. UI test purpose. Fixme accordingly.
+ */
+ private fun generateQrCodeData(): String {
+ return "https://element.io"
+ }
}
diff --git a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewState.kt b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewState.kt
index 2f52cf789d..0c4457c12f 100644
--- a/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewState.kt
+++ b/vector/src/main/java/im/vector/app/features/login/qr/QrCodeLoginViewState.kt
@@ -21,6 +21,7 @@ import com.airbnb.mvrx.MavericksState
data class QrCodeLoginViewState(
val loginType: QrCodeLoginType,
val connectionStatus: QrCodeLoginConnectionStatus? = null,
+ val generatedQrCodeData: String? = null,
) : MavericksState {
constructor(args: QrCodeLoginArgs) : this(
diff --git a/vector/src/main/res/layout/fragment_qr_code_login_instructions.xml b/vector/src/main/res/layout/fragment_qr_code_login_instructions.xml
index 83ea42d7e9..df043e8238 100644
--- a/vector/src/main/res/layout/fragment_qr_code_login_instructions.xml
+++ b/vector/src/main/res/layout/fragment_qr_code_login_instructions.xml
@@ -21,7 +21,6 @@
android:id="@+id/qrCodeLoginInstructionsView"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="8dp"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/vector/src/main/res/layout/fragment_qr_code_login_show_qr_code.xml b/vector/src/main/res/layout/fragment_qr_code_login_show_qr_code.xml
new file mode 100644
index 0000000000..060d02498e
--- /dev/null
+++ b/vector/src/main/res/layout/fragment_qr_code_login_show_qr_code.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+