From a1374d228e0e958f29c49b996bb223ae8da4a442 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 17 Nov 2023 17:40:32 +0100 Subject: [PATCH] Changes for first launches & proper back nav --- .../java/org/linphone/core/CorePreferences.kt | 7 +++ .../ui/assistant/AssistantActivity.kt | 52 ++++++++++++++++++- .../ui/assistant/fragment/LoginFragment.kt | 22 ++------ .../assistant/fragment/PermissionsFragment.kt | 12 ++--- .../viewmodel/AccountLoginViewModel.kt | 14 +++-- .../java/org/linphone/ui/main/MainActivity.kt | 18 ++++++- .../linphone/ui/welcome/WelcomeActivity.kt | 4 ++ .../res/layout/assistant_login_fragment.xml | 1 + .../res/navigation/assistant_nav_graph.xml | 4 +- 9 files changed, 97 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/org/linphone/core/CorePreferences.kt b/app/src/main/java/org/linphone/core/CorePreferences.kt index fa40d4a21..ada7415c2 100644 --- a/app/src/main/java/org/linphone/core/CorePreferences.kt +++ b/app/src/main/java/org/linphone/core/CorePreferences.kt @@ -48,6 +48,13 @@ class CorePreferences @UiThread constructor(private val context: Context) { config.setBool("app", "debug", value) } + @get:WorkerThread @set:WorkerThread + var firstLaunch: Boolean + get() = config.getBool("app", "first_6.0_launch", true) + set(value) { + config.setBool("app", "first_6.0_launch", value) + } + @get:WorkerThread @set:WorkerThread var defaultFragment: Int get() = config.getInt("app", "default_page", -1) diff --git a/app/src/main/java/org/linphone/ui/assistant/AssistantActivity.kt b/app/src/main/java/org/linphone/ui/assistant/AssistantActivity.kt index 37651a4ce..62a7ebf50 100644 --- a/app/src/main/java/org/linphone/ui/assistant/AssistantActivity.kt +++ b/app/src/main/java/org/linphone/ui/assistant/AssistantActivity.kt @@ -19,34 +19,73 @@ */ package org.linphone.ui.assistant +import android.Manifest +import android.content.pm.PackageManager import android.os.Bundle +import android.os.PersistableBundle import android.view.ViewGroup +import androidx.activity.addCallback import androidx.annotation.DrawableRes import androidx.annotation.UiThread import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import androidx.core.view.WindowCompat import androidx.databinding.DataBindingUtil import androidx.lifecycle.lifecycleScope -import org.linphone.LinphoneApplication +import androidx.navigation.findNavController +import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R +import org.linphone.core.tools.Log import org.linphone.databinding.AssistantActivityBinding +import org.linphone.ui.assistant.fragment.PermissionsFragmentDirections import org.linphone.utils.AppUtils import org.linphone.utils.slideInToastFromTopForDuration @UiThread class AssistantActivity : AppCompatActivity() { + companion object { + private const val TAG = "[Assistant Activity]" + + val PERMISSIONS = arrayOf( + Manifest.permission.POST_NOTIFICATIONS, + Manifest.permission.READ_CONTACTS, + Manifest.permission.RECORD_AUDIO, + Manifest.permission.CAMERA + ) + } + private lateinit var binding: AssistantActivityBinding override fun onCreate(savedInstanceState: Bundle?) { WindowCompat.setDecorFitsSystemWindows(window, true) super.onCreate(savedInstanceState) - while (!LinphoneApplication.coreContext.isReady()) { + while (!coreContext.isReady()) { Thread.sleep(20) } binding = DataBindingUtil.setContentView(this, R.layout.assistant_activity) binding.lifecycleOwner = this + + coreContext.postOnCoreThread { core -> + if (core.accountList.isEmpty()) { + Log.i("$TAG No account configured, disabling back gesture") + coreContext.postOnMainThread { + // Disable back gesture / button + onBackPressedDispatcher.addCallback { } + } + } + } + } + + override fun onPostCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { + super.onPostCreate(savedInstanceState, persistentState) + + if (!areAllPermissionsGranted()) { + Log.w("$TAG Not all required permissions are granted, showing Permissions fragment") + val action = PermissionsFragmentDirections.actionGlobalPermissionsFragment() + binding.assistantNavContainer.findNavController().navigate(action) + } } fun showGreenToast(message: String, @DrawableRes icon: Int) { @@ -68,4 +107,13 @@ class AssistantActivity : AppCompatActivity() { lifecycleScope ) } + + private fun areAllPermissionsGranted(): Boolean { + for (permission in PERMISSIONS) { + if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { + return false + } + } + return true + } } diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt index 6842f9561..78ccbbbb9 100644 --- a/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt @@ -25,7 +25,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.activity.OnBackPressedCallback import androidx.annotation.UiThread import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope @@ -34,6 +33,7 @@ import androidx.navigation.navGraphViewModels import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.core.tools.Log import org.linphone.databinding.AssistantLoginFragmentBinding @@ -56,12 +56,6 @@ class LoginFragment : Fragment() { R.id.assistant_nav_graph ) - private val onBackPressedCallback = object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - goBack() - } - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -77,13 +71,8 @@ class LoginFragment : Fragment() { binding.lifecycleOwner = viewLifecycleOwner binding.viewModel = viewModel - requireActivity().onBackPressedDispatcher.addCallback( - viewLifecycleOwner, - onBackPressedCallback - ) - binding.setBackClickListener { - goBack() + requireActivity().finish() } binding.setRegisterClickListener { @@ -156,10 +145,6 @@ class LoginFragment : Fragment() { } } - private fun goBack() { - requireActivity().finish() - } - private fun goToRegisterFragment() { val action = LoginFragmentDirections.actionLoginFragmentToRegisterFragment() findNavController().navigate(action) @@ -190,8 +175,7 @@ class LoginFragment : Fragment() { it.consume { Log.i("$TAG Conditions & Privacy policy have been accepted") coreContext.postOnCoreThread { - // TODO FIXME: uncomment - // corePreferences.conditionsAndPrivacyPolicyAccepted = true + corePreferences.conditionsAndPrivacyPolicyAccepted = true } dialog.dismiss() diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt index 3b64dfe9f..b17a6bf0a 100644 --- a/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/PermissionsFragment.kt @@ -32,18 +32,12 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import org.linphone.core.tools.Log import org.linphone.databinding.AssistantPermissionsFragmentBinding +import org.linphone.ui.assistant.AssistantActivity @UiThread class PermissionsFragment : Fragment() { companion object { private const val TAG = "[Permissions Fragment]" - - private val PERMISSIONS = arrayOf( - Manifest.permission.POST_NOTIFICATIONS, - Manifest.permission.READ_CONTACTS, - Manifest.permission.RECORD_AUDIO, - Manifest.permission.CAMERA - ) } private lateinit var binding: AssistantPermissionsFragmentBinding @@ -94,7 +88,7 @@ class PermissionsFragment : Fragment() { binding.setGrantAllClickListener { Log.i("$TAG Requesting all permissions") requestPermissionLauncher.launch( - PERMISSIONS + AssistantActivity.PERMISSIONS ) } @@ -113,7 +107,7 @@ class PermissionsFragment : Fragment() { } private fun areAllPermissionsGranted(): Boolean { - for (permission in PERMISSIONS) { + for (permission in AssistantActivity.PERMISSIONS) { if (ContextCompat.checkSelfPermission(requireContext(), permission) != PackageManager.PERMISSION_GRANTED) { return false } diff --git a/app/src/main/java/org/linphone/ui/assistant/viewmodel/AccountLoginViewModel.kt b/app/src/main/java/org/linphone/ui/assistant/viewmodel/AccountLoginViewModel.kt index 3cd685458..d616d323d 100644 --- a/app/src/main/java/org/linphone/ui/assistant/viewmodel/AccountLoginViewModel.kt +++ b/app/src/main/java/org/linphone/ui/assistant/viewmodel/AccountLoginViewModel.kt @@ -43,6 +43,8 @@ class AccountLoginViewModel @UiThread constructor() : ViewModel() { private const val TAG = "[Account Login ViewModel]" } + val showBackButton = MutableLiveData() + val username = MutableLiveData() val password = MutableLiveData() @@ -55,9 +57,13 @@ class AccountLoginViewModel @UiThread constructor() : ViewModel() { val registrationInProgress = MutableLiveData() - val accountLoggedInEvent = MutableLiveData>() + val accountLoggedInEvent: MutableLiveData> by lazy { + MutableLiveData>() + } - val accountLoginErrorEvent = MutableLiveData>() + val accountLoginErrorEvent: MutableLiveData> by lazy { + MutableLiveData>() + } var conditionsAndPrivacyPolicyAccepted = false @@ -111,7 +117,9 @@ class AccountLoginViewModel @UiThread constructor() : ViewModel() { showPassword.value = false registrationInProgress.value = false - coreContext.postOnCoreThread { + coreContext.postOnCoreThread { core -> + // Prevent user from leaving assistant if no account was configured yet + showBackButton.postValue(core.accountList.isNotEmpty()) conditionsAndPrivacyPolicyAccepted = corePreferences.conditionsAndPrivacyPolicyAccepted } diff --git a/app/src/main/java/org/linphone/ui/main/MainActivity.kt b/app/src/main/java/org/linphone/ui/main/MainActivity.kt index 3128cb579..c5ae06133 100644 --- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt @@ -50,8 +50,10 @@ import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.core.tools.Log import org.linphone.databinding.MainActivityBinding +import org.linphone.ui.assistant.AssistantActivity import org.linphone.ui.main.viewmodel.MainViewModel import org.linphone.ui.main.viewmodel.SharedMainViewModel +import org.linphone.ui.welcome.WelcomeActivity import org.linphone.utils.AppUtils import org.linphone.utils.FileUtils import org.linphone.utils.LinphoneUtils @@ -173,8 +175,20 @@ class MainActivity : AppCompatActivity() { override fun onPostCreate(savedInstanceState: Bundle?) { super.onPostCreate(savedInstanceState) - // TODO FIXME: uncomment - // startActivity(Intent(this, WelcomeActivity::class.java)) + coreContext.postOnCoreThread { core -> + if (corePreferences.firstLaunch) { + Log.i("$TAG First time Linphone 6.0 has been started, showing Welcome activity") + corePreferences.firstLaunch = false + coreContext.postOnMainThread { + startActivity(Intent(this, WelcomeActivity::class.java)) + } + } else if (core.accountList.isEmpty()) { + Log.w("$TAG No account found, showing Assistant activity") + coreContext.postOnMainThread { + startActivity(Intent(this, AssistantActivity::class.java)) + } + } + } coreContext.greenToastToShowEvent.observe(this) { it.consume { pair -> diff --git a/app/src/main/java/org/linphone/ui/welcome/WelcomeActivity.kt b/app/src/main/java/org/linphone/ui/welcome/WelcomeActivity.kt index a70eaf4c6..5f6c01de9 100644 --- a/app/src/main/java/org/linphone/ui/welcome/WelcomeActivity.kt +++ b/app/src/main/java/org/linphone/ui/welcome/WelcomeActivity.kt @@ -22,6 +22,7 @@ package org.linphone.ui.welcome import android.content.Intent import android.os.Bundle import android.view.View +import androidx.activity.addCallback import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat import androidx.databinding.DataBindingUtil @@ -59,6 +60,9 @@ class WelcomeActivity : AppCompatActivity() { Thread.sleep(20) } + // Disable back gesture / button + onBackPressedDispatcher.addCallback { } + binding = DataBindingUtil.setContentView(this, R.layout.welcome_activity) binding.lifecycleOwner = this diff --git a/app/src/main/res/layout/assistant_login_fragment.xml b/app/src/main/res/layout/assistant_login_fragment.xml index fbf76198d..9c09c3344 100644 --- a/app/src/main/res/layout/assistant_login_fragment.xml +++ b/app/src/main/res/layout/assistant_login_fragment.xml @@ -45,6 +45,7 @@ android:layout_height="@dimen/top_bar_height" android:padding="15dp" android:src="@drawable/caret_left" + android:visibility="@{viewModel.showBackButton ? View.VISIBLE : View.INVISIBLE, default=invisible}" app:tint="@color/gray_main2_500" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"/> diff --git a/app/src/main/res/navigation/assistant_nav_graph.xml b/app/src/main/res/navigation/assistant_nav_graph.xml index 50970ba87..20157b639 100644 --- a/app/src/main/res/navigation/assistant_nav_graph.xml +++ b/app/src/main/res/navigation/assistant_nav_graph.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/assistant_nav_graph" - app:startDestination="@id/permissionsFragment"> + app:startDestination="@id/loginFragment"> - + \ No newline at end of file