From 334e08730e1014fa41b1e021162c0bd2d01bf22c Mon Sep 17 00:00:00 2001 From: Koitharu Date: Wed, 13 Jul 2022 10:30:30 +0300 Subject: [PATCH] Option to enable exit confirmation --- .../kotatsu/core/prefs/AppSettings.kt | 4 ++ .../koitharu/kotatsu/main/ui/ExitCallback.kt | 54 +++++++++++++++++++ .../koitharu/kotatsu/main/ui/MainActivity.kt | 20 +------ app/src/main/res/values/strings.xml | 4 +- app/src/main/res/xml/pref_appearance.xml | 10 +++- 5 files changed, 70 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/main/ui/ExitCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 356458852..69756fae8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -130,6 +130,9 @@ class AppSettings(context: Context) { get() = prefs.getBoolean(KEY_PROTECT_APP_BIOMETRIC, true) set(value) = prefs.edit { putBoolean(KEY_PROTECT_APP_BIOMETRIC, value) } + val isExitConfirmationEnabled: Boolean + get() = prefs.getBoolean(KEY_EXIT_CONFIRM, false) + var sourcesOrder: List get() = prefs.getString(KEY_SOURCES_ORDER, null) ?.split('|') @@ -306,6 +309,7 @@ class AppSettings(context: Context) { const val KEY_DOWNLOADS_SLOWDOWN = "downloads_slowdown" const val KEY_ALL_FAVOURITES_VISIBLE = "all_favourites_visible" const val KEY_DOH = "doh" + const val KEY_EXIT_CONFIRM = "exit_confirm" // About const val KEY_APP_UPDATE = "app_update" diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/ExitCallback.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/ExitCallback.kt new file mode 100644 index 000000000..9d6fcfd81 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/ExitCallback.kt @@ -0,0 +1,54 @@ +package org.koitharu.kotatsu.main.ui + +import android.view.View +import androidx.activity.ComponentActivity +import androidx.activity.OnBackPressedCallback +import androidx.lifecycle.lifecycleScope +import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import org.koin.android.ext.android.get +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.prefs.observeAsFlow + +class ExitCallback( + private val activity: ComponentActivity, + private val snackbarHost: View, +) : OnBackPressedCallback(false) { + + private var job: Job? = null + + init { + observeSettings() + } + + override fun handleOnBackPressed() { + job?.cancel() + job = activity.lifecycleScope.launch { + resetExitConfirmation() + } + } + + private suspend fun resetExitConfirmation() { + isEnabled = false + val snackbar = Snackbar.make(snackbarHost, R.string.confirm_exit, Snackbar.LENGTH_INDEFINITE) + snackbar.show() + delay(2000) + snackbar.dismiss() + isEnabled = true + } + + private fun observeSettings() { + activity.get() + .observeAsFlow(AppSettings.KEY_EXIT_CONFIRM) { isExitConfirmationEnabled } + .flowOn(Dispatchers.Default) + .onEach { isEnabled = it } + .launchIn(activity.lifecycleScope) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt index e294b1990..5e3097eb3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.MenuItem import android.view.View import android.view.ViewGroup.MarginLayoutParams -import android.widget.Toast import androidx.activity.result.ActivityResultCallback import androidx.annotation.IdRes import androidx.appcompat.view.ActionMode @@ -21,8 +20,6 @@ import com.google.android.material.appbar.AppBarLayout.LayoutParams.* import com.google.android.material.navigation.NavigationBarView import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.koin.android.ext.android.get import org.koin.androidx.viewmodel.ext.android.viewModel @@ -63,8 +60,6 @@ class MainActivity : View.OnFocusChangeListener, SearchSuggestionListener, NavigationBarView.OnItemSelectedListener { - private var isConfirmingExit: Boolean = false - private val viewModel by viewModel() private val searchSuggestionViewModel by viewModel() private val voiceInputLauncher = registerForActivityResult(VoiceInputContract(), VoiceInputCallback()) @@ -99,6 +94,7 @@ class MainActivity : binding.navRail?.headerView?.setOnClickListener(this) binding.searchView.isVoiceSearchEnabled = voiceInputLauncher.resolve(this, null) != null + onBackPressedDispatcher.addCallback(ExitCallback(this, binding.container)) supportFragmentManager.findFragmentByTag(TAG_PRIMARY)?.let { if (it is LibraryFragment) binding.fab?.show() else binding.fab?.hide() } ?: onNavigationItemSelected(navBar.selectedItemId) @@ -136,7 +132,6 @@ class MainActivity : setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) runOnCommit { onSearchClosed() } } - shouldHandleExitConfirmation() -> lifecycleScope.launch { resetExitConfirmation() } else -> super.onBackPressed() } } @@ -153,19 +148,6 @@ class MainActivity : return super.onOptionsItemSelected(item) } - private suspend fun resetExitConfirmation() { - isConfirmingExit = true - val toast = Toast.makeText(this, R.string.confirm_exit, Toast.LENGTH_LONG) - toast.show() - delay(2000) - toast.cancel() - isConfirmingExit = false - } - - private fun shouldHandleExitConfirmation(): Boolean { - return !isConfirmingExit - } - override fun onClick(v: View) { when (v.id) { R.id.fab -> viewModel.openLastReader() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 91ef4caa8..f6dbc8432 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -337,5 +337,7 @@ Changelog Explore Tools - Press back again to exit + Press "Back" again to exit + Press "Back" twice to exit the app + Exit confirmation \ No newline at end of file diff --git a/app/src/main/res/xml/pref_appearance.xml b/app/src/main/res/xml/pref_appearance.xml index eac08e162..0f472b72e 100644 --- a/app/src/main/res/xml/pref_appearance.xml +++ b/app/src/main/res/xml/pref_appearance.xml @@ -43,11 +43,17 @@ android:valueTo="150" app:defaultValue="100" /> + + + android:title="@string/protect_application" /> \ No newline at end of file