Option to enable exit confirmation

This commit is contained in:
Koitharu
2022-07-13 10:30:30 +03:00
parent d6ff996dbe
commit 334e08730e
5 changed files with 70 additions and 22 deletions

View File

@@ -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<String>
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"

View File

@@ -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<AppSettings>()
.observeAsFlow(AppSettings.KEY_EXIT_CONFIRM) { isExitConfirmationEnabled }
.flowOn(Dispatchers.Default)
.onEach { isEnabled = it }
.launchIn(activity.lifecycleScope)
}
}

View File

@@ -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<MainViewModel>()
private val searchSuggestionViewModel by viewModel<SearchSuggestionViewModel>()
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()

View File

@@ -337,5 +337,7 @@
<string name="changelog">Changelog</string>
<string name="explore">Explore</string>
<string name="tools">Tools</string>
<string name="confirm_exit">Press back again to exit</string>
<string name="confirm_exit">Press "Back" again to exit</string>
<string name="exit_confirmation_summary">Press "Back" twice to exit the app</string>
<string name="exit_confirmation">Exit confirmation</string>
</resources>

View File

@@ -43,11 +43,17 @@
android:valueTo="150"
app:defaultValue="100" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="exit_confirm"
android:summary="@string/exit_confirmation_summary"
android:title="@string/exit_confirmation"
app:allowDividerAbove="true" />
<SwitchPreferenceCompat
android:key="protect_app"
android:persistent="false"
android:summary="@string/protect_application_summary"
android:title="@string/protect_application"
app:allowDividerAbove="true" />
android:title="@string/protect_application" />
</PreferenceScreen>