Skip to content
Snippets Groups Projects
Commit e0cf3579 authored by Vitalii Nikitchyn's avatar Vitalii Nikitchyn
Browse files

link existing account: landscape layout

Change-Id: Ieb7d84627c388a0e9183b3baa32640ca18dc3f61
parent 12b3181b
No related branches found
No related tags found
No related merge requests found
Showing
with 291 additions and 511 deletions
......@@ -108,7 +108,6 @@ dependencies {
implementation ("androidx.tvprovider:tvprovider:1.1.0-alpha01")
implementation ("androidx.media:media:1.7.0")
implementation ("androidx.sharetarget:sharetarget:1.2.0")
implementation ("androidx.percentlayout:percentlayout:1.0.0")
implementation ("androidx.emoji2:emoji2:1.4.0")
implementation ("androidx.emoji2:emoji2-emojipicker:1.4.0")
implementation ("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
......
......@@ -26,7 +26,6 @@ import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import cx.ring.R
import cx.ring.application.JamiApplication
......@@ -47,11 +46,9 @@ import net.jami.model.Account
import net.jami.model.AccountConfig
import net.jami.utils.VCardUtils
@AndroidEntryPoint
class AccountWizardActivity : BaseActivity<AccountWizardPresenter>(), AccountWizardView {
private var mProgress: AlertDialog? = null
private var mAccountType: String? = null
private var mAlertDialog: AlertDialog? = null
private var biometricEnroll: BiometricHelper.BiometricEnroll? = null
private val enrollBiometricLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
......@@ -60,39 +57,21 @@ class AccountWizardActivity : BaseActivity<AccountWizardPresenter>(), AccountWiz
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
onBackInvokedDispatcher.registerOnBackInvokedCallback(1) { onBackPressed() }
JamiApplication.instance?.startDaemon(this)
val model: AccountCreationViewModel by viewModels()
setContentView(R.layout.activity_wizard)
var accountToMigrate: String? = null
val intent = intent
if (intent != null) {
mAccountType = intent.action
val path = intent.data
if (path != null) {
accountToMigrate = path.lastPathSegment
}
}
if (mAccountType == null) {
mAccountType = AccountConfig.ACCOUNT_TYPE_JAMI
}
if (savedInstanceState == null) {
if (accountToMigrate != null) {
// ======= check if migration is needed =======
val path = intent?.data?.lastPathSegment
if (path != null) { // start migration
val fragment = AccountMigrationFragment().apply {
arguments = Bundle().apply { putString(AccountEditionFragment.ACCOUNT_ID_KEY, accountToMigrate) }
arguments = Bundle().apply { putString(AccountEditionFragment.ACCOUNT_ID_KEY, path) }
}
supportFragmentManager
.beginTransaction()
supportFragmentManager.beginTransaction()
.replace(R.id.wizard_container, fragment)
.commit()
} else {
presenter.init(getIntent().action ?: AccountConfig.ACCOUNT_TYPE_JAMI)
}
}
else{
presenter.init(getIntent().action ?: AccountConfig.ACCOUNT_TYPE_JAMI, true)
}
} else // migration is not needed
presenter.init(intent.action ?: AccountConfig.ACCOUNT_TYPE_JAMI)
}
override fun onDestroy() {
......@@ -136,17 +115,16 @@ class AccountWizardActivity : BaseActivity<AccountWizardPresenter>(), AccountWiz
}
override fun goToHomeCreation() {
val fragmentManager = supportFragmentManager
fragmentManager.beginTransaction()
supportFragmentManager
.beginTransaction()
.replace(R.id.wizard_container, HomeAccountCreationFragment(), HomeAccountCreationFragment.TAG)
.commit()
}
override fun goToSipCreation() {
val fragment: Fragment = SIPAccountCreationFragment()
val fragmentManager = supportFragmentManager
fragmentManager.beginTransaction()
.replace(R.id.wizard_container, fragment, SIPAccountCreationFragment.TAG)
supportFragmentManager
.beginTransaction()
.replace(R.id.wizard_container, SIPAccountCreationFragment(), SIPAccountCreationFragment.TAG)
.commit()
}
......@@ -173,9 +151,7 @@ class AccountWizardActivity : BaseActivity<AccountWizardPresenter>(), AccountWiz
val fragments = supportFragmentManager.fragments
if (fragments.size > 0) {
val fragment = fragments[0]
if (fragment is JamiLinkAccountFragment) {
fragment.scrollPagerFragment()
} else if (fragment is JamiAccountConnectFragment) {
if (fragment is JamiLinkAccountFragment || fragment is JamiAccountConnectFragment) {
profileCreated(false)
}
}
......
......@@ -26,13 +26,13 @@ import androidx.fragment.app.activityViewModels
import com.google.android.material.snackbar.Snackbar
import cx.ring.R
import cx.ring.databinding.FragAccHomeCreateBinding
import cx.ring.fragments.SIPAccountCreationFragment
import cx.ring.mvp.BaseSupportFragment
import cx.ring.utils.AndroidFileUtils.getCacheFile
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import net.jami.account.HomeAccountCreationPresenter
import net.jami.account.HomeAccountCreationView
import net.jami.model.AccountConfig
import java.io.File
@AndroidEntryPoint
......@@ -59,27 +59,25 @@ class HomeAccountCreationFragment :
override fun goToAccountCreation() {
model.model = AccountCreationModelImpl()
replaceFragmentWithSlide(JamiAccountCreationFragment(), R.id.wizard_container)
replaceFragmentWithSlide(JamiAccountCreationFragment(), JamiAccountCreationFragment.TAG, R.id.wizard_container)
}
override fun goToAccountLink() {
model.model = AccountCreationModelImpl().apply {
isLink = true
}
replaceFragmentWithSlide(JamiLinkAccountFragment(), R.id.wizard_container)
replaceFragmentWithSlide(JamiLinkAccountFragment(), JamiLinkAccountFragment.TAG, R.id.wizard_container)
}
override fun goToAccountConnect() {
model.model = AccountCreationModelImpl().apply {
isLink = true
}
replaceFragmentWithSlide(JamiAccountConnectFragment(), R.id.wizard_container)
replaceFragmentWithSlide(JamiAccountConnectFragment(), JamiAccountConnectFragment.TAG, R.id.wizard_container)
}
override fun goToSIPAccountCreation() {
val intent = Intent(activity, AccountWizardActivity::class.java)
intent.action = AccountConfig.ACCOUNT_TYPE_SIP
startActivityForResult(intent, ADD_SIP_ACCOUNT)
replaceFragmentWithSlide(SIPAccountCreationFragment(), SIPAccountCreationFragment.TAG, R.id.wizard_container)
}
private fun performFileSearch() {
......@@ -103,20 +101,21 @@ class HomeAccountCreationFragment :
isLink = true
archive = file
}
replaceFragmentWithSlide(JamiLinkAccountFragment(), R.id.wizard_container)
replaceFragmentWithSlide(
JamiLinkAccountFragment(), JamiLinkAccountFragment.TAG, R.id.wizard_container)
}) { e: Throwable ->
view?.let { v ->
Snackbar.make(v, "Can't import archive: " + e.message, Snackbar.LENGTH_LONG).show() }
}
}
} else if (requestCode == ADD_SIP_ACCOUNT && resultCode == Activity.RESULT_OK) {
(activity as AccountWizardActivity?)?.displaySuccessDialog()
}
// else if (requestCode == ADD_SIP_ACCOUNT && resultCode == Activity.RESULT_OK) {
// (activity as AccountWizardActivity?)?.displaySuccessDialog()
// }
}
companion object {
private const val ARCHIVE_REQUEST_CODE = 42
private const val ADD_SIP_ACCOUNT = 101
val TAG = HomeAccountCreationFragment::class.simpleName!!
}
}
\ No newline at end of file
......@@ -85,10 +85,14 @@ class JamiAccountConnectFragment : BaseSupportFragment<JamiAccountConnectPresent
}
override fun createAccount() {
(activity as AccountWizardActivity?)?.createAccount()
(activity as? AccountWizardActivity)?.createAccount()
}
override fun cancel() {
activity?.onBackPressedDispatcher?.onBackPressed()
}
companion object {
val TAG = HomeAccountCreationFragment::class.simpleName!!
}
}
\ No newline at end of file
......@@ -121,4 +121,8 @@ class JamiAccountCreationFragment : Fragment() {
fun getRegisteredFragment(position: Int): Fragment? = registeredFragments[position]
}
companion object {
val TAG = JamiAccountCreationFragment::class.simpleName!!
}
}
\ No newline at end of file
......@@ -17,112 +17,162 @@
package cx.ring.account
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.util.SparseArray
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.OnBackPressedCallback
import android.view.inputmethod.InputMethodManager
import android.widget.LinearLayout
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.ViewModelProvider
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import cx.ring.R
import cx.ring.account.pinInput.EditTextPinInputFragment
import cx.ring.account.pinInput.EditTextPinInputViewModel
import cx.ring.account.pinInput.QrCodePinInputFragment
import cx.ring.account.pinInput.QrCodePinInputViewModel
import cx.ring.databinding.FragAccJamiLinkBinding
import cx.ring.mvp.BaseSupportFragment
import dagger.hilt.android.AndroidEntryPoint
import net.jami.account.JamiLinkAccountPresenter
import net.jami.account.JamiLinkAccountView
class JamiLinkAccountFragment : Fragment() {
private var mBinding: FragAccJamiLinkBinding? = null
private var mCurrentFragment: Fragment? = null
@AndroidEntryPoint
class JamiLinkAccountFragment :
BaseSupportFragment<JamiLinkAccountPresenter, JamiLinkAccountView>(),
JamiLinkAccountView {
private val model: AccountCreationViewModel by activityViewModels()
private var binding: FragAccJamiLinkBinding? = null
private val onBackPressedCallback: OnBackPressedCallback =
object : OnBackPressedCallback(false) {
override fun handleOnBackPressed() {
if (mCurrentFragment is ProfileCreationFragment) {
//val fragment = mCurrentFragment as ProfileCreationFragment
(activity as AccountWizardActivity).profileCreated(false)
return
// the 2 view models connected to this fragment
private val qrCodePinInputViewModel by lazy {
ViewModelProvider(this)[QrCodePinInputViewModel::class.java]
}
mBinding!!.pager.currentItem = mBinding!!.pager.currentItem - 1
private val editTextPinInputViewModel by lazy {
ViewModelProvider(this)[EditTextPinInputViewModel::class.java]
}
private fun setLayoutOrientation(linearLayout: LinearLayout?, conf: Configuration) {
linearLayout?.orientation = if (conf.orientation == Configuration.ORIENTATION_LANDSCAPE) {
LinearLayout.HORIZONTAL
} else LinearLayout.VERTICAL
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
FragAccJamiLinkBinding.inflate(inflater, container, false).apply {
val pagerAdapter = ScreenSlidePagerAdapter(childFragmentManager)
pager.apply {
disableScroll(true)
adapter = pagerAdapter
addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = FragAccJamiLinkBinding.inflate(inflater, container, false).apply {
setLayoutOrientation(root, resources.configuration)
override fun onPageSelected(position: Int) {
mCurrentFragment = pagerAdapter.getRegisteredFragment(position)
onBackPressedCallback.isEnabled = mCurrentFragment is ProfileCreationFragment
val adapter = SectionsPagerAdapter(this@JamiLinkAccountFragment)
adapter.addFragment(QrCodePinInputFragment(), getString(R.string.connect_device_scanqr))
adapter.addFragment(EditTextPinInputFragment(), getString(R.string.connect_device_enterPIN))
pager.adapter = adapter
pager.currentItem = 0
TabLayoutMediator(tabLayout, pager) { tab, position ->
tab.text = adapter.getTabTitle(position)
}.attach()
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
presenter.resetPin()
// emit the pin again when switching tabs
if (tab?.position == 0) {
qrCodePinInputViewModel.emitPinAgain()
} else {
editTextPinInputViewModel.emitPinAgain()
}
}
override fun onPageScrollStateChanged(state: Int) {}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
override fun onTabReselected(tab: TabLayout.Tab?) {}
})
linkButton.setOnClickListener { presenter.linkClicked() }
existingPassword.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
presenter.passwordChanged(s.toString())
}
mBinding = this
})
binding = this
}.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
qrCodePinInputViewModel.init({ presenter.pinChanged(it) }, { presenter.resetPin() })
editTextPinInputViewModel.init({ presenter.pinChanged(it) }, { presenter.resetPin() })
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
setLayoutOrientation(binding?.root, resources.configuration)
}
override fun onDestroyView() {
super.onDestroyView()
mBinding = null
binding = null
}
override fun onAttach(context: Context) {
super.onAttach(context)
requireActivity().onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
override fun initPresenter(presenter: JamiLinkAccountPresenter) {
presenter.init(model.model)
}
fun scrollPagerFragment() {
mBinding?.let { it.pager.currentItem = it.pager.currentItem + 1 }
//mBinding!!.pager.currentItem = mBinding!!.pager.currentItem + 1
/*if (accountCreationModel == null) {
mBinding!!.pager.currentItem = mBinding!!.pager.currentItem - 1
return
override fun enableLinkButton(enable: Boolean) {
binding!!.linkButton.isEnabled = enable
}
mBinding!!.pager.currentItem = mBinding!!.pager.currentItem + 1
for (fragment in childFragmentManager.fragments) {
if (fragment is JamiAccountPasswordFragment) {
fragment.setUsername(accountCreationModel.username)
}
}*/
override fun showPin(show: Boolean) {
val binding = binding ?: return
binding.pager.visibility = if (show) View.VISIBLE else View.GONE
binding.tabLayout.visibility = if (show) View.VISIBLE else View.GONE
binding.linkButton.setText(if (show) R.string.account_link_device else R.string.account_link_archive_button)
}
private class ScreenSlidePagerAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm) {
var mRegisteredFragments = SparseArray<Fragment>()
override fun getItem(position: Int): Fragment =
when (position) {
0 -> JamiLinkAccountPasswordFragment()
1 -> ProfileCreationFragment()
else -> throw IllegalArgumentException()
override fun createAccount() {
(activity as AccountWizardActivity?)?.createAccount()
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.hideSoftInputFromWindow(binding!!.existingPassword.windowToken, 0)
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val fragment = super.instantiateItem(container, position) as Fragment
mRegisteredFragments.put(position, fragment)
return super.instantiateItem(container, position)
override fun cancel() {
activity?.onBackPressedDispatcher?.onBackPressed()
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
mRegisteredFragments.remove(position)
super.destroyItem(container, position, `object`)
internal class SectionsPagerAdapter(hostFragment: Fragment) : FragmentStateAdapter(hostFragment) {
private val mFragmentList = ArrayList<Fragment>(2)
private val mFragmentTitleList = ArrayList<String>(2)
fun getTabTitle(position: Int): String {
return mFragmentTitleList[position]
}
override fun getCount(): Int {
return NUM_PAGES
fun addFragment(fragment: Fragment, title: String) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
fun getRegisteredFragment(position: Int): Fragment {
return mRegisteredFragments[position]
override fun getItemCount(): Int {
return mFragmentList.size
}
override fun createFragment(position: Int): Fragment {
return mFragmentList[position]
}
}
companion object {
val TAG = JamiLinkAccountFragment::class.simpleName!!
private const val NUM_PAGES = 2
}
}
\ No newline at end of file
/*
* Copyright (C) 2004-2024 Savoir-faire Linux Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package cx.ring.account
import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.ViewModelProvider
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import cx.ring.R
import cx.ring.account.pinInput.EditTextPinInputFragment
import cx.ring.account.pinInput.EditTextPinInputViewModel
import cx.ring.account.pinInput.QrCodePinInputFragment
import cx.ring.account.pinInput.QrCodePinInputViewModel
import cx.ring.databinding.FragAccJamiLinkPasswordBinding
import cx.ring.mvp.BaseSupportFragment
import dagger.hilt.android.AndroidEntryPoint
import net.jami.account.JamiLinkAccountPresenter
import net.jami.account.JamiLinkAccountView
@AndroidEntryPoint
class JamiLinkAccountPasswordFragment :
BaseSupportFragment<JamiLinkAccountPresenter, JamiLinkAccountView>(),
JamiLinkAccountView {
private val model: AccountCreationViewModel by activityViewModels()
private var binding: FragAccJamiLinkPasswordBinding? = null
// the 2 view models connected to this fragment
private val qrCodePinInputViewModel by lazy {
ViewModelProvider(this)[QrCodePinInputViewModel::class.java]
}
private val editTextPinInputViewModel by lazy {
ViewModelProvider(this)[EditTextPinInputViewModel::class.java]
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View =
FragAccJamiLinkPasswordBinding.inflate(inflater, container, false).apply {
val adapter = SectionsPagerAdapter(this@JamiLinkAccountPasswordFragment)
adapter.addFragment(
QrCodePinInputFragment(),
getString(R.string.connect_device_scanqr)
)
adapter.addFragment(
EditTextPinInputFragment(),
getString(R.string.connect_device_enterPIN)
)
pager.adapter = adapter
pager.currentItem = 0
TabLayoutMediator(tabLayout, pager) { tab, position ->
tab.text = adapter.getTabTitle(position)
}.attach()
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
presenter.resetPin()
// emit the pin again when switching tabs
if (tab?.position == 0) {
qrCodePinInputViewModel.emitPinAgain()
} else {
editTextPinInputViewModel.emitPinAgain()
}
}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
override fun onTabReselected(tab: TabLayout.Tab?) {}
})
linkButton.setOnClickListener { presenter.linkClicked() }
ringExistingPassword.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(
s: CharSequence,
start: Int,
count: Int,
after: Int
) {
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
presenter.passwordChanged(s.toString())
}
})
binding = this
}.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// init the 2 view models
qrCodePinInputViewModel.init({ presenter.pinChanged(it) }, { presenter.resetPin() })
editTextPinInputViewModel.init({ presenter.pinChanged(it) }, { presenter.resetPin() })
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
override fun initPresenter(presenter: JamiLinkAccountPresenter) {
presenter.init(model.model)
}
override fun enableLinkButton(enable: Boolean) {
binding!!.linkButton.isEnabled = enable
}
override fun showPin(show: Boolean) {
val binding = binding ?: return
binding.pager.visibility = if (show) View.VISIBLE else View.GONE
binding.tabLayout.visibility = if (show) View.VISIBLE else View.GONE
binding.linkButton.setText(if (show) R.string.account_link_device else R.string.account_link_archive_button)
}
override fun createAccount() {
(activity as AccountWizardActivity?)?.createAccount()
val imm =
requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
imm?.hideSoftInputFromWindow(binding!!.ringExistingPassword.windowToken, 0)
}
override fun cancel() {
activity?.onBackPressedDispatcher?.onBackPressed()
}
internal class SectionsPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
private val mFragmentList: MutableList<Fragment> = ArrayList()
private val mFragmentTitleList: MutableList<String> = ArrayList()
fun getTabTitle(position: Int): String {
return mFragmentTitleList[position]
}
fun addFragment(fragment: Fragment, title: String) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
override fun getItemCount(): Int {
return mFragmentList.size
}
override fun createFragment(position: Int): Fragment {
return mFragmentList[position]
}
}
companion object {
val TAG = JamiLinkAccountPasswordFragment::class.simpleName!!
}
}
\ No newline at end of file
......@@ -27,7 +27,6 @@ import com.google.android.material.textfield.TextInputEditText
import cx.ring.R
import cx.ring.databinding.EditTextPinInputBinding
import dagger.hilt.android.AndroidEntryPoint
import net.jami.utils.Log
@AndroidEntryPoint
class EditTextPinInputFragment : Fragment() {
......@@ -35,11 +34,6 @@ class EditTextPinInputFragment : Fragment() {
private val viewModel: EditTextPinInputViewModel by viewModels({ requireParentFragment() })
private lateinit var binding: EditTextPinInputBinding
companion object {
private val TAG = EditTextPinInputFragment::class.simpleName!!
}
// inflate the layout and link with viewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
......@@ -69,4 +63,8 @@ class EditTextPinInputFragment : Fragment() {
binding.enterPin.error = getString(R.string.error_format_not_supported)
binding.enterPin.requestFocus()
}
companion object {
private val TAG = EditTextPinInputFragment::class.simpleName!!
}
}
......@@ -16,9 +16,7 @@
*/
package cx.ring.fragments
import android.app.Activity
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.ActivityInfo
import android.os.Bundle
import android.view.KeyEvent
......@@ -30,6 +28,7 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import cx.ring.R
import cx.ring.account.AccountWizardActivity
import cx.ring.databinding.FragAccSipCreateBinding
import cx.ring.databinding.ItemProgressDialogBinding
import cx.ring.mvp.BaseSupportFragment
......@@ -126,9 +125,7 @@ class SIPAccountCreationFragment : BaseSupportFragment<SIPCreationPresenter, SIP
getString(R.string.account_sip_register_anyway),
{ dialog: DialogInterface?, which: Int -> presenter.removeAccount() }
) { dialog: DialogInterface?, id: Int ->
val activity: Activity = requireActivity()
activity.setResult(Activity.RESULT_OK, Intent())
activity.finish()
(activity as? AccountWizardActivity)?.displaySuccessDialog()
}
}
......@@ -139,9 +136,7 @@ class SIPAccountCreationFragment : BaseSupportFragment<SIPCreationPresenter, SIP
getString(R.string.account_sip_register_anyway),
{ dialog: DialogInterface?, which: Int -> presenter.removeAccount() }
) { dialog: DialogInterface?, id: Int ->
val activity: Activity = requireActivity()
activity.setResult(Activity.RESULT_OK, Intent())
activity.finish()
(activity as? AccountWizardActivity)?.displaySuccessDialog()
}
}
......@@ -152,9 +147,7 @@ class SIPAccountCreationFragment : BaseSupportFragment<SIPCreationPresenter, SIP
getString(android.R.string.ok),
null,
{ dialog: DialogInterface?, which: Int ->
val activity: Activity = requireActivity()
activity.setResult(Activity.RESULT_OK, Intent())
activity.finish()
(activity as? AccountWizardActivity)?.displaySuccessDialog()
},
null
)
......
......@@ -46,24 +46,19 @@ abstract class BaseSupportFragment<T : RootPresenter<in V>, in V> : Fragment() {
protected open fun initPresenter(presenter: T) {}
protected fun replaceFragmentWithSlide(fragment: Fragment, @IdRes content: Int) {
parentFragmentManager
.beginTransaction()
protected fun replaceFragmentWithSlide(fragment: Fragment, tag: String?, @IdRes containerID: Int) {
parentFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right)
.replace(content, fragment, TAG)
.addToBackStack(TAG)
.replace(containerID, fragment, tag)
.addToBackStack(tag)
.commit()
}
protected fun replaceFragment(fragment: Fragment, @IdRes content: Int) {
parentFragmentManager
.beginTransaction()
.replace(content, fragment, TAG)
.addToBackStack(TAG)
protected fun replaceFragment(fragment: Fragment, tag: String?, @IdRes containerID: Int) {
parentFragmentManager.beginTransaction()
.replace(containerID, fragment, tag)
.addToBackStack(tag)
.commit()
}
companion object {
protected val TAG = BaseSupportFragment::class.simpleName!!
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="12dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2004-2024 Savoir-faire Linux Inc.
~
~ This program is free software; you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation; either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program; if not, write to the Free Software
~ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/color_primary_light" android:state_enabled="true"/>
<item android:color="@color/grey_300" android:state_enabled="false"/>
</selector>
\ No newline at end of file
......@@ -3,17 +3,15 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
android:gravity="center">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/pin_box"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:layout_marginTop="130dp"
android:paddingHorizontal="20dp"
app:counterEnabled="true"
app:counterMaxLength="17">
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="@color/color_primary_dark"
android:gravity="center_vertical"
android:orientation="vertical">
android:gravity="center"
android:orientation="vertical"
android:paddingVertical="16dp">
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center_horizontal"
android:orientation="vertical">
android:layout_height="wrap_content">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:layout_centerInParent="true"
android:text="@string/account_link_device"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
android:textColor="@color/color_primary_light"
android:textStyle="bold" />
</LinearLayout>
<ImageView
android:id="@+id/background"
android:layout_width="@dimen/wizard_image_background"
......@@ -45,14 +39,90 @@
app:tint="@color/white" />
</RelativeLayout>
<cx.ring.views.WizardViewPager
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/background_rounded_12dp"
android:backgroundTint="@color/white">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/connect_device_scanqr" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/connect_device_enterPIN" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="@dimen/wizard_card_width"
android:layout_height="500dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="22dp"
tools:background="@color/grey_400"
tools:layout_height="500dp" />
android:layout_height="@dimen/wizard_card_width"
tools:background="@color/grey_400" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/help_password_enter"
android:textAlignment="center"
android:textStyle="bold" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/password_txt_box"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:passwordToggleEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/existing_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/baseline_lock_24"
android:drawablePadding="5dp"
android:hint="@string/prompt_password"
android:imeOptions="actionNext"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/link_button"
style="@style/ButtonColored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"
android:enabled="false"
android:text="@string/account_link_button"
android:textSize="12sp"
android:theme="@style/ButtonColoredInverse" />
</LinearLayout>
</ScrollView>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (C) 2004-2024 Savoir-faire Linux Inc.
~
~ This program is free software; you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation; either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program; if not, write to the Free Software
~ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="cx.ring.account.AccountWizardActivity">
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:cardCornerRadius="12dp">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/wizard_card_padding">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/connect_device_scanqr" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/connect_device_enterPIN" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="300dp" />
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="@string/help_password_enter"
android:textStyle="bold" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/password_txt_box"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:passwordToggleEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/ring_existing_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/baseline_lock_24"
android:drawablePadding="5dp"
android:hint="@string/prompt_password"
android:imeOptions="actionNext"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/link_button"
style="@style/WizardButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="18dp"
android:enabled="false"
android:text="@string/account_link_button"
android:textSize="12sp"
android:theme="@style/ButtonColoredInverse" />
</LinearLayout>
</ScrollView>
</androidx.cardview.widget.CardView>
</FrameLayout>
\ No newline at end of file
......@@ -19,7 +19,6 @@ package net.jami.account
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Scheduler
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import io.reactivex.rxjava3.subjects.BehaviorSubject
import net.jami.model.Account
import net.jami.model.AccountConfig
......@@ -40,14 +39,12 @@ class AccountWizardPresenter @Inject constructor(
private val mDeviceService: DeviceRuntimeService,
@param:Named("UiScheduler") private val mUiScheduler: Scheduler
) : RootPresenter<AccountWizardView>() {
//private boolean mCreationError = false;
private var mCreatingAccount = false
private var mAccountType: String? = null
private var newAccount: Observable<Account>? = null
fun init(accountType: String, restoredInstance: Boolean = false) {
fun init(accountType: String) {
mAccountType = accountType
if (restoredInstance) return
if (AccountConfig.ACCOUNT_TYPE_SIP == mAccountType) {
view?.goToSipCreation()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment