Handling multiple dialogs correctly

pull/1457/head
Jakub Kalinowski 3 years ago
parent 25a3509988
commit 2db4491328

@ -20,6 +20,7 @@
package org.isoron.uhabits package org.isoron.uhabits
import android.app.Application import android.app.Application
import android.app.Dialog
import android.content.Context import android.content.Context
import org.isoron.uhabits.core.database.UnsupportedDatabaseVersionException import org.isoron.uhabits.core.database.UnsupportedDatabaseVersionException
import org.isoron.uhabits.core.reminders.ReminderScheduler import org.isoron.uhabits.core.reminders.ReminderScheduler
@ -118,5 +119,11 @@ class HabitsApplication : Application() {
false false
} }
} }
var currentDialog: Dialog? = null
fun clearCurrentDialog() {
currentDialog?.dismiss()
currentDialog = null
}
} }
} }

@ -25,6 +25,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R import org.isoron.uhabits.R
import org.isoron.uhabits.core.models.Entry.Companion.NO import org.isoron.uhabits.core.models.Entry.Companion.NO
import org.isoron.uhabits.core.models.Entry.Companion.SKIP import org.isoron.uhabits.core.models.Entry.Companion.SKIP
@ -98,6 +99,7 @@ class CheckmarkPopup(
} }
fun show() { fun show() {
HabitsApplication.clearCurrentDialog()
dialog = Dialog(context, android.R.style.Theme_NoTitleBar) dialog = Dialog(context, android.R.style.Theme_NoTitleBar)
dialog.setContentView(view.root) dialog.setContentView(view.root)
dialog.window?.apply { dialog.window?.apply {
@ -117,11 +119,13 @@ class CheckmarkPopup(
view.unknownBtn.setOnClickListener { onClick(UNKNOWN) } view.unknownBtn.setOnClickListener { onClick(UNKNOWN) }
dialog.setCanceledOnTouchOutside(true) dialog.setCanceledOnTouchOutside(true)
dialog.dimBehind() dialog.dimBehind()
HabitsApplication.currentDialog = dialog
dialog.show() dialog.show()
} }
fun save() { fun save() {
onToggle(value, view.notes.text.toString().trim()) onToggle(value, view.notes.text.toString().trim())
HabitsApplication.currentDialog = null
dialog.dismiss() dialog.dismiss()
} }
} }

@ -18,7 +18,11 @@
*/ */
package org.isoron.uhabits.activities.common.dialogs package org.isoron.uhabits.activities.common.dialogs
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import com.android.colorpicker.ColorPickerDialog import com.android.colorpicker.ColorPickerDialog
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.core.ui.callbacks.OnColorPickedCallback import org.isoron.uhabits.core.ui.callbacks.OnColorPickedCallback
import org.isoron.uhabits.utils.toPaletteColor import org.isoron.uhabits.utils.toPaletteColor
@ -28,8 +32,22 @@ import org.isoron.uhabits.utils.toPaletteColor
class ColorPickerDialog : ColorPickerDialog() { class ColorPickerDialog : ColorPickerDialog() {
fun setListener(callback: OnColorPickedCallback) { fun setListener(callback: OnColorPickedCallback) {
super.setOnColorSelectedListener { c: Int -> super.setOnColorSelectedListener { c: Int ->
val pc = c.toPaletteColor(context!!) val pc = c.toPaletteColor(requireContext())
callback.onColorPicked(pc) callback.onColorPicked(pc)
} }
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
HabitsApplication.clearCurrentDialog()
HabitsApplication.currentDialog = this.dialog
return super.onCreateDialog(savedInstanceState)
}
override fun onColorSelected(color: Int) {
super.onColorSelected(color)
}
override fun onDismiss(dialog: DialogInterface) {
HabitsApplication.currentDialog = null
super.onDismiss(dialog)
}
} }

@ -21,6 +21,7 @@ package org.isoron.uhabits.activities.common.dialogs
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R import org.isoron.uhabits.R
import org.isoron.uhabits.core.ui.callbacks.OnConfirmedCallback import org.isoron.uhabits.core.ui.callbacks.OnConfirmedCallback
import org.isoron.uhabits.inject.ActivityContext import org.isoron.uhabits.inject.ActivityContext
@ -34,6 +35,7 @@ class ConfirmDeleteDialog(
quantity: Int quantity: Int
) : AlertDialog(context) { ) : AlertDialog(context) {
init { init {
HabitsApplication.clearCurrentDialog()
val res = context.resources val res = context.resources
setTitle(res.getQuantityString(R.plurals.delete_habits_title, quantity)) setTitle(res.getQuantityString(R.plurals.delete_habits_title, quantity))
setMessage(res.getQuantityString(R.plurals.delete_habits_message, quantity)) setMessage(res.getQuantityString(R.plurals.delete_habits_message, quantity))
@ -45,5 +47,12 @@ class ConfirmDeleteDialog(
BUTTON_NEGATIVE, BUTTON_NEGATIVE,
res.getString(R.string.no) res.getString(R.string.no)
) { dialog: DialogInterface?, which: Int -> } ) { dialog: DialogInterface?, which: Int -> }
HabitsApplication.currentDialog = this
this.setOnDismissListener{
HabitsApplication.currentDialog = null
} }
} }
}

@ -20,6 +20,7 @@
package org.isoron.uhabits.activities.common.dialogs package org.isoron.uhabits.activities.common.dialogs
import android.app.Dialog import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -30,6 +31,7 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDialogFragment import androidx.appcompat.app.AppCompatDialogFragment
import kotlinx.android.synthetic.main.frequency_picker_dialog.view.* import kotlinx.android.synthetic.main.frequency_picker_dialog.view.*
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R import org.isoron.uhabits.R
class FrequencyPickerDialog( class FrequencyPickerDialog(
@ -43,6 +45,7 @@ class FrequencyPickerDialog(
constructor() : this(1, 1) constructor() : this(1, 1)
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
HabitsApplication.clearCurrentDialog()
val inflater = LayoutInflater.from(requireActivity()) val inflater = LayoutInflater.from(requireActivity())
contentView = inflater.inflate(R.layout.frequency_picker_dialog, null) contentView = inflater.inflate(R.layout.frequency_picker_dialog, null)
@ -111,10 +114,17 @@ class FrequencyPickerDialog(
if (hasFocus) check(contentView.xTimesPerYDaysRadioButton) if (hasFocus) check(contentView.xTimesPerYDaysRadioButton)
} }
return AlertDialog.Builder(requireActivity()) val dialog = AlertDialog.Builder(requireActivity())
.setView(contentView) .setView(contentView)
.setPositiveButton(R.string.save) { _, _ -> onSaveClicked() } .setPositiveButton(R.string.save) { _, _ -> onSaveClicked() }
.create() .create()
HabitsApplication.currentDialog = dialog
return dialog
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
HabitsApplication.currentDialog = null
} }
private fun addBeforeAfterText( private fun addBeforeAfterText(

@ -19,6 +19,7 @@
package org.isoron.uhabits.activities.common.dialogs package org.isoron.uhabits.activities.common.dialogs
import android.app.Dialog import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatDialogFragment import androidx.appcompat.app.AppCompatDialogFragment
import org.isoron.platform.gui.AndroidDataView import org.isoron.platform.gui.AndroidDataView
@ -35,6 +36,7 @@ import org.isoron.uhabits.core.ui.views.HistoryChart
import org.isoron.uhabits.core.ui.views.LightTheme import org.isoron.uhabits.core.ui.views.LightTheme
import org.isoron.uhabits.core.ui.views.OnDateClickedListener import org.isoron.uhabits.core.ui.views.OnDateClickedListener
import org.isoron.uhabits.core.utils.DateUtils import org.isoron.uhabits.core.utils.DateUtils
import org.isoron.uhabits.inject.HabitsApplicationComponent
import java.util.Locale import java.util.Locale
import kotlin.math.min import kotlin.math.min
@ -49,12 +51,13 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener {
private var onDateClickedListener: OnDateClickedListener? = null private var onDateClickedListener: OnDateClickedListener? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val component = (activity!!.application as HabitsApplication).component clearCurrentDialog()
val component = (requireActivity().application as HabitsApplication).component
commandRunner = component.commandRunner commandRunner = component.commandRunner
habit = component.habitList.getById(arguments!!.getLong("habit"))!! habit = component.habitList.getById(requireArguments().getLong("habit"))!!
preferences = component.preferences preferences = component.preferences
val themeSwitcher = AndroidThemeSwitcher(activity!!, preferences) val themeSwitcher = AndroidThemeSwitcher(requireActivity(), preferences)
themeSwitcher.apply() themeSwitcher.apply()
chart = HistoryChart( chart = HistoryChart(
@ -69,15 +72,23 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener {
onDateClickedListener = onDateClickedListener ?: object : OnDateClickedListener {}, onDateClickedListener = onDateClickedListener ?: object : OnDateClickedListener {},
padding = 10.0, padding = 10.0,
) )
dataView = AndroidDataView(context!!, null) dataView = AndroidDataView(requireContext(), null)
dataView.view = chart!! dataView.view = chart!!
return Dialog(context!!).apply { val dialog = Dialog(requireContext()).apply {
val metrics = resources.displayMetrics val metrics = resources.displayMetrics
val maxHeight = resources.getDimensionPixelSize(R.dimen.history_editor_max_height) val maxHeight = resources.getDimensionPixelSize(R.dimen.history_editor_max_height)
setContentView(dataView) setContentView(dataView)
window!!.setLayout(metrics.widthPixels, min(metrics.heightPixels, maxHeight)) window!!.setLayout(metrics.widthPixels, min(metrics.heightPixels, maxHeight))
} }
currentDialog = dialog
return dialog
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
currentDialog = null
} }
override fun onResume() { override fun onResume() {
@ -111,4 +122,14 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener {
override fun onCommandFinished(command: Command) { override fun onCommandFinished(command: Command) {
refreshData() refreshData()
} }
companion object {
// HistoryEditorDialog handles multiple dialogs on its own,
// because sometimes we want it to be shown under another dialog (e.g. NumberPopup)
var currentDialog: Dialog? = null
fun clearCurrentDialog() {
currentDialog?.dismiss()
currentDialog = null
}
}
} }

@ -27,6 +27,7 @@ import android.view.MotionEvent.ACTION_DOWN
import android.view.View import android.view.View
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.core.models.Entry import org.isoron.uhabits.core.models.Entry
import org.isoron.uhabits.core.preferences.Preferences import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.databinding.CheckmarkPopupBinding import org.isoron.uhabits.databinding.CheckmarkPopupBinding
@ -73,7 +74,7 @@ class NumberPopup(
} }
fun show() { fun show() {
clearCurrentDialog() HabitsApplication.clearCurrentDialog()
dialog = Dialog(context, android.R.style.Theme_NoTitleBar) dialog = Dialog(context, android.R.style.Theme_NoTitleBar)
dialog.setContentView(view.root) dialog.setContentView(view.root)
dialog.window?.apply { dialog.window?.apply {
@ -85,7 +86,7 @@ class NumberPopup(
} }
dialog.setOnDismissListener { dialog.setOnDismissListener {
onDismiss() onDismiss()
currentDialog = null HabitsApplication.currentDialog = null
} }
view.value.setOnKeyListener { _, keyCode, event -> view.value.setOnKeyListener { _, keyCode, event ->
@ -105,7 +106,7 @@ class NumberPopup(
view.value.requestFocusWithKeyboard() view.value.requestFocusWithKeyboard()
dialog.setCanceledOnTouchOutside(true) dialog.setCanceledOnTouchOutside(true)
dialog.dimBehind() dialog.dimBehind()
currentDialog = dialog HabitsApplication.currentDialog = dialog
dialog.show() dialog.show()
} }
@ -115,14 +116,4 @@ class NumberPopup(
onToggle(value, notes) onToggle(value, notes)
dialog.dismiss() dialog.dismiss()
} }
companion object {
// Used to make sure that 2 popups aren't shown on top of each other
// If dialog that's already shown is detected, it's dismissed before the next one is opened.
private var currentDialog: Dialog? = null
fun clearCurrentDialog() {
currentDialog?.dismiss()
currentDialog = null
}
}
} }

@ -24,6 +24,7 @@ import android.content.DialogInterface.OnMultiChoiceClickListener
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDialogFragment import androidx.appcompat.app.AppCompatDialogFragment
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R import org.isoron.uhabits.R
import org.isoron.uhabits.core.models.WeekdayList import org.isoron.uhabits.core.models.WeekdayList
import org.isoron.uhabits.core.utils.DateUtils import org.isoron.uhabits.core.utils.DateUtils
@ -59,8 +60,9 @@ class WeekdayPickerDialog :
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
HabitsApplication.clearCurrentDialog()
val builder = AlertDialog.Builder( val builder = AlertDialog.Builder(
activity!! requireActivity()
) )
builder builder
.setTitle(R.string.select_weekdays) .setTitle(R.string.select_weekdays)
@ -73,7 +75,15 @@ class WeekdayPickerDialog :
.setNegativeButton( .setNegativeButton(
android.R.string.cancel android.R.string.cancel
) { _: DialogInterface?, _: Int -> dismiss() } ) { _: DialogInterface?, _: Int -> dismiss() }
return builder.create()
val dialog = builder.create()
HabitsApplication.currentDialog = dialog
return dialog
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
HabitsApplication.currentDialog = null
} }
fun setListener(listener: OnWeekdaysPickedListener?) { fun setListener(listener: OnWeekdaysPickedListener?) {

Loading…
Cancel
Save