From 2db4491328e80f0e656cca5dc55a3546eee9b36b Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Sat, 13 Aug 2022 18:16:11 +0200 Subject: [PATCH] Handling multiple dialogs correctly --- .../org/isoron/uhabits/HabitsApplication.kt | 7 +++++ .../common/dialogs/CheckmarkPopup.kt | 4 +++ .../common/dialogs/ColorPickerDialog.kt | 20 +++++++++++- .../common/dialogs/ConfirmDeleteDialog.kt | 9 ++++++ .../common/dialogs/FrequencyPickerDialog.kt | 12 ++++++- .../common/dialogs/HistoryEditorDialog.kt | 31 ++++++++++++++++--- .../activities/common/dialogs/NumberPopup.kt | 17 +++------- .../common/dialogs/WeekdayPickerDialog.kt | 14 +++++++-- 8 files changed, 92 insertions(+), 22 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt b/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt index 4f00f4d1f..6a3e38cb8 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt @@ -20,6 +20,7 @@ package org.isoron.uhabits import android.app.Application +import android.app.Dialog import android.content.Context import org.isoron.uhabits.core.database.UnsupportedDatabaseVersionException import org.isoron.uhabits.core.reminders.ReminderScheduler @@ -118,5 +119,11 @@ class HabitsApplication : Application() { false } } + + var currentDialog: Dialog? = null + fun clearCurrentDialog() { + currentDialog?.dismiss() + currentDialog = null + } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt index 9a862076f..2a203d937 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt @@ -25,6 +25,7 @@ import android.view.LayoutInflater import android.view.View import android.view.View.GONE import android.view.View.VISIBLE +import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R import org.isoron.uhabits.core.models.Entry.Companion.NO import org.isoron.uhabits.core.models.Entry.Companion.SKIP @@ -98,6 +99,7 @@ class CheckmarkPopup( } fun show() { + HabitsApplication.clearCurrentDialog() dialog = Dialog(context, android.R.style.Theme_NoTitleBar) dialog.setContentView(view.root) dialog.window?.apply { @@ -117,11 +119,13 @@ class CheckmarkPopup( view.unknownBtn.setOnClickListener { onClick(UNKNOWN) } dialog.setCanceledOnTouchOutside(true) dialog.dimBehind() + HabitsApplication.currentDialog = dialog dialog.show() } fun save() { onToggle(value, view.notes.text.toString().trim()) + HabitsApplication.currentDialog = null dialog.dismiss() } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ColorPickerDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ColorPickerDialog.kt index cf6248600..46ce4d253 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ColorPickerDialog.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ColorPickerDialog.kt @@ -18,7 +18,11 @@ */ 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 org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.core.ui.callbacks.OnColorPickedCallback import org.isoron.uhabits.utils.toPaletteColor @@ -28,8 +32,22 @@ import org.isoron.uhabits.utils.toPaletteColor class ColorPickerDialog : ColorPickerDialog() { fun setListener(callback: OnColorPickedCallback) { super.setOnColorSelectedListener { c: Int -> - val pc = c.toPaletteColor(context!!) + val pc = c.toPaletteColor(requireContext()) 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) + } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ConfirmDeleteDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ConfirmDeleteDialog.kt index bac6180b2..74786c00a 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ConfirmDeleteDialog.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/ConfirmDeleteDialog.kt @@ -21,6 +21,7 @@ package org.isoron.uhabits.activities.common.dialogs import android.content.Context import android.content.DialogInterface import androidx.appcompat.app.AlertDialog +import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R import org.isoron.uhabits.core.ui.callbacks.OnConfirmedCallback import org.isoron.uhabits.inject.ActivityContext @@ -34,6 +35,7 @@ class ConfirmDeleteDialog( quantity: Int ) : AlertDialog(context) { init { + HabitsApplication.clearCurrentDialog() val res = context.resources setTitle(res.getQuantityString(R.plurals.delete_habits_title, quantity)) setMessage(res.getQuantityString(R.plurals.delete_habits_message, quantity)) @@ -45,5 +47,12 @@ class ConfirmDeleteDialog( BUTTON_NEGATIVE, res.getString(R.string.no) ) { dialog: DialogInterface?, which: Int -> } + + HabitsApplication.currentDialog = this + + this.setOnDismissListener{ + HabitsApplication.currentDialog = null + } } + } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt index 8411e3a96..6774bba71 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/FrequencyPickerDialog.kt @@ -20,6 +20,7 @@ package org.isoron.uhabits.activities.common.dialogs import android.app.Dialog +import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -30,6 +31,7 @@ import android.widget.TextView import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatDialogFragment import kotlinx.android.synthetic.main.frequency_picker_dialog.view.* +import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R class FrequencyPickerDialog( @@ -43,6 +45,7 @@ class FrequencyPickerDialog( constructor() : this(1, 1) override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + HabitsApplication.clearCurrentDialog() val inflater = LayoutInflater.from(requireActivity()) contentView = inflater.inflate(R.layout.frequency_picker_dialog, null) @@ -111,10 +114,17 @@ class FrequencyPickerDialog( if (hasFocus) check(contentView.xTimesPerYDaysRadioButton) } - return AlertDialog.Builder(requireActivity()) + val dialog = AlertDialog.Builder(requireActivity()) .setView(contentView) .setPositiveButton(R.string.save) { _, _ -> onSaveClicked() } .create() + HabitsApplication.currentDialog = dialog + return dialog + } + + override fun onDismiss(dialog: DialogInterface) { + super.onDismiss(dialog) + HabitsApplication.currentDialog = null } private fun addBeforeAfterText( diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/HistoryEditorDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/HistoryEditorDialog.kt index 5cfe90ea6..3ff243a27 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/HistoryEditorDialog.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/HistoryEditorDialog.kt @@ -19,6 +19,7 @@ package org.isoron.uhabits.activities.common.dialogs import android.app.Dialog +import android.content.DialogInterface import android.os.Bundle import androidx.appcompat.app.AppCompatDialogFragment 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.OnDateClickedListener import org.isoron.uhabits.core.utils.DateUtils +import org.isoron.uhabits.inject.HabitsApplicationComponent import java.util.Locale import kotlin.math.min @@ -49,12 +51,13 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { private var onDateClickedListener: OnDateClickedListener? = null override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val component = (activity!!.application as HabitsApplication).component + clearCurrentDialog() + val component = (requireActivity().application as HabitsApplication).component commandRunner = component.commandRunner - habit = component.habitList.getById(arguments!!.getLong("habit"))!! + habit = component.habitList.getById(requireArguments().getLong("habit"))!! preferences = component.preferences - val themeSwitcher = AndroidThemeSwitcher(activity!!, preferences) + val themeSwitcher = AndroidThemeSwitcher(requireActivity(), preferences) themeSwitcher.apply() chart = HistoryChart( @@ -69,15 +72,23 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { onDateClickedListener = onDateClickedListener ?: object : OnDateClickedListener {}, padding = 10.0, ) - dataView = AndroidDataView(context!!, null) + dataView = AndroidDataView(requireContext(), null) dataView.view = chart!! - return Dialog(context!!).apply { + val dialog = Dialog(requireContext()).apply { val metrics = resources.displayMetrics val maxHeight = resources.getDimensionPixelSize(R.dimen.history_editor_max_height) setContentView(dataView) 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() { @@ -111,4 +122,14 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { override fun onCommandFinished(command: Command) { 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 + } + } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt index 28ecc50ed..cb549b84e 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPopup.kt @@ -27,6 +27,7 @@ import android.view.MotionEvent.ACTION_DOWN import android.view.View import android.view.View.GONE import android.view.View.VISIBLE +import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.core.models.Entry import org.isoron.uhabits.core.preferences.Preferences import org.isoron.uhabits.databinding.CheckmarkPopupBinding @@ -73,7 +74,7 @@ class NumberPopup( } fun show() { - clearCurrentDialog() + HabitsApplication.clearCurrentDialog() dialog = Dialog(context, android.R.style.Theme_NoTitleBar) dialog.setContentView(view.root) dialog.window?.apply { @@ -85,7 +86,7 @@ class NumberPopup( } dialog.setOnDismissListener { onDismiss() - currentDialog = null + HabitsApplication.currentDialog = null } view.value.setOnKeyListener { _, keyCode, event -> @@ -105,7 +106,7 @@ class NumberPopup( view.value.requestFocusWithKeyboard() dialog.setCanceledOnTouchOutside(true) dialog.dimBehind() - currentDialog = dialog + HabitsApplication.currentDialog = dialog dialog.show() } @@ -115,14 +116,4 @@ class NumberPopup( onToggle(value, notes) 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 - } - } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/WeekdayPickerDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/WeekdayPickerDialog.kt index 6e1f8cf28..17f3755fb 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/WeekdayPickerDialog.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/WeekdayPickerDialog.kt @@ -24,6 +24,7 @@ import android.content.DialogInterface.OnMultiChoiceClickListener import android.os.Bundle import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatDialogFragment +import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R import org.isoron.uhabits.core.models.WeekdayList import org.isoron.uhabits.core.utils.DateUtils @@ -59,8 +60,9 @@ class WeekdayPickerDialog : } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + HabitsApplication.clearCurrentDialog() val builder = AlertDialog.Builder( - activity!! + requireActivity() ) builder .setTitle(R.string.select_weekdays) @@ -73,7 +75,15 @@ class WeekdayPickerDialog : .setNegativeButton( android.R.string.cancel ) { _: 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?) {