mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Implement dialog for Yes/No Habits
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
package org.isoron.uhabits.activities.common.dialogs
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
|
||||
import android.widget.EditText
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
|
||||
import org.isoron.uhabits.inject.ActivityContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class CheckmarkDialog
|
||||
@Inject constructor(
|
||||
@ActivityContext private val context: Context
|
||||
) {
|
||||
|
||||
fun create(
|
||||
notes: String,
|
||||
callback: ListHabitsBehavior.CheckMarkDialogCallback
|
||||
): AlertDialog {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val view = inflater.inflate(R.layout.checkmark_dialog, null)
|
||||
|
||||
val etNotes = view.findViewById<EditText>(R.id.etNotes)
|
||||
|
||||
etNotes.setText(notes)
|
||||
val dialog = AlertDialog.Builder(context)
|
||||
.setView(view)
|
||||
.setTitle(R.string.edit_notes)
|
||||
.setPositiveButton(R.string.save) { _, _ ->
|
||||
val note = etNotes.text.toString()
|
||||
callback.onNotesSaved(note)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
callback.onNotesDismissed()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
callback.onNotesDismissed()
|
||||
}
|
||||
.create()
|
||||
|
||||
dialog.setOnShowListener {
|
||||
etNotes.requestFocus()
|
||||
dialog.window?.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
}
|
||||
|
||||
return dialog
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ class NumberPickerFactory
|
||||
val note = etNotes.text.toString()
|
||||
callback.onNumberPicked(v, note)
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { _, _ ->
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
callback.onNumberPickerDismissed()
|
||||
}
|
||||
.setOnDismissListener {
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.content.Intent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import dagger.Lazy
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog
|
||||
import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory
|
||||
import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog
|
||||
import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory
|
||||
@@ -89,6 +90,7 @@ class ListHabitsScreen
|
||||
private val importTaskFactory: ImportDataTaskFactory,
|
||||
private val colorPickerFactory: ColorPickerDialogFactory,
|
||||
private val numberPickerFactory: NumberPickerFactory,
|
||||
private val checkMarkDialog: CheckmarkDialog,
|
||||
private val behavior: Lazy<ListHabitsBehavior>
|
||||
) : CommandRunner.Listener,
|
||||
ListHabitsBehavior.Screen,
|
||||
@@ -231,6 +233,13 @@ class ListHabitsScreen
|
||||
numberPickerFactory.create(value, unit, notes, callback).show()
|
||||
}
|
||||
|
||||
override fun showCheckmarkDialog(
|
||||
notes: String,
|
||||
callback: ListHabitsBehavior.CheckMarkDialogCallback
|
||||
) {
|
||||
checkMarkDialog.create(notes, callback).show()
|
||||
}
|
||||
|
||||
private fun getExecuteString(command: Command): String? {
|
||||
when (command) {
|
||||
is ArchiveHabitsCommand -> {
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.isoron.uhabits.core.preferences.Preferences
|
||||
import org.isoron.uhabits.inject.ActivityContext
|
||||
import org.isoron.uhabits.utils.dim
|
||||
import org.isoron.uhabits.utils.getFontAwesome
|
||||
import org.isoron.uhabits.utils.showMessage
|
||||
import org.isoron.uhabits.utils.sres
|
||||
import org.isoron.uhabits.utils.toMeasureSpec
|
||||
import javax.inject.Inject
|
||||
@@ -78,6 +77,8 @@ class CheckmarkButtonView(
|
||||
}
|
||||
|
||||
var onToggle: (Int) -> Unit = {}
|
||||
|
||||
var onEdit: () -> Unit = {}
|
||||
private var drawer = Drawer()
|
||||
|
||||
init {
|
||||
@@ -99,7 +100,7 @@ class CheckmarkButtonView(
|
||||
|
||||
override fun onClick(v: View) {
|
||||
if (preferences.isShortToggleEnabled) performToggle()
|
||||
else showMessage(resources.getString(R.string.long_press_to_toggle))
|
||||
else onEdit()
|
||||
}
|
||||
|
||||
override fun onLongClick(v: View): Boolean {
|
||||
@@ -133,6 +134,8 @@ class CheckmarkButtonView(
|
||||
textAlign = Paint.Align.CENTER
|
||||
}
|
||||
|
||||
private val pNotesIndicator: Paint = Paint()
|
||||
|
||||
fun draw(canvas: Canvas) {
|
||||
paint.color = when (value) {
|
||||
YES_MANUAL, YES_AUTO, SKIP -> color
|
||||
@@ -142,6 +145,7 @@ class CheckmarkButtonView(
|
||||
}
|
||||
else -> lowContrastColor
|
||||
}
|
||||
pNotesIndicator.color = color
|
||||
val id = when (value) {
|
||||
SKIP -> R.string.fa_skipped
|
||||
NO -> R.string.fa_times
|
||||
@@ -176,6 +180,11 @@ class CheckmarkButtonView(
|
||||
paint.style = Paint.Style.FILL
|
||||
canvas.drawText(label, rect.centerX(), rect.centerY(), paint)
|
||||
}
|
||||
|
||||
if (hasNotes) {
|
||||
val cy = 0.8f * em
|
||||
canvas.drawCircle(width.toFloat() - cy, cy, 8f, pNotesIndicator)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,12 @@ class CheckmarkPanelView(
|
||||
setupButtons()
|
||||
}
|
||||
|
||||
var onEdit: (Timestamp) -> Unit = {}
|
||||
set(value) {
|
||||
field = value
|
||||
setupButtons()
|
||||
}
|
||||
|
||||
override fun createButton(): CheckmarkButtonView = buttonFactory.create()
|
||||
|
||||
@Synchronized
|
||||
@@ -84,6 +90,7 @@ class CheckmarkPanelView(
|
||||
}
|
||||
button.color = color
|
||||
button.onToggle = { value -> onToggle(timestamp, value) }
|
||||
button.onEdit = { onEdit(timestamp) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class HabitCardView(
|
||||
}
|
||||
|
||||
var notes
|
||||
get() = numberPanel.notes
|
||||
get() = checkmarkPanel.notes
|
||||
set(values) {
|
||||
checkmarkPanel.notes = values
|
||||
numberPanel.notes = values
|
||||
@@ -150,7 +150,11 @@ class HabitCardView(
|
||||
checkmarkPanel = checkmarkPanelFactory.create().apply {
|
||||
onToggle = { timestamp, value ->
|
||||
triggerRipple(timestamp)
|
||||
habit?.let { behavior.onToggle(it, timestamp, value, "") }
|
||||
habit?.let { behavior.onToggle(it, timestamp, value) }
|
||||
}
|
||||
onEdit = { timestamp ->
|
||||
triggerRipple(timestamp)
|
||||
habit?.let { behavior.onEdit(it, timestamp) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ class NumberButtonView(
|
||||
pNumber.color = activeColor
|
||||
pNumber.typeface = typeface
|
||||
pUnit.color = activeColor
|
||||
pNotesIndicator.color = activeColor
|
||||
pNotesIndicator.color = color
|
||||
|
||||
if (units.isBlank()) {
|
||||
rect.set(0f, 0f, width.toFloat(), height.toFloat())
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.isoron.uhabits.HabitsApplication
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
||||
import org.isoron.uhabits.activities.HabitsDirFinder
|
||||
import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog
|
||||
import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog
|
||||
import org.isoron.uhabits.activities.common.dialogs.HistoryEditorDialog
|
||||
import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory
|
||||
@@ -170,6 +171,13 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
||||
NumberPickerFactory(this@ShowHabitActivity).create(value, unit, notes, callback).show()
|
||||
}
|
||||
|
||||
override fun showCheckmarkDialog(
|
||||
notes: String,
|
||||
callback: ListHabitsBehavior.CheckMarkDialogCallback
|
||||
) {
|
||||
CheckmarkDialog(this@ShowHabitActivity).create(notes, callback).show()
|
||||
}
|
||||
|
||||
override fun showEditHabitScreen(habit: Habit) {
|
||||
startActivity(IntentFactory().startEditActivity(this@ShowHabitActivity, habit))
|
||||
}
|
||||
|
||||
18
uhabits-android/src/main/res/layout/checkmark_dialog.xml
Normal file
18
uhabits-android/src/main/res/layout/checkmark_dialog.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="30dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etNotes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textCapSentences|textMultiLine"
|
||||
style="@style/TextAppearance.AppCompat.Body1"
|
||||
android:scrollbars="vertical"
|
||||
android:hint="@string/example_notes"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -55,7 +55,6 @@
|
||||
<string name="clear">Clear</string>
|
||||
<string name="reminder">Reminder</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="streaks">Streaks</string>
|
||||
<string name="no_habits_found">You have no active habits</string>
|
||||
<string name="no_habits_left_to_do">You\'re all done for today!</string>
|
||||
@@ -233,4 +232,5 @@
|
||||
<string name="activity_not_found">No app was found to support this action</string>
|
||||
<string name="pref_midnight_delay_title">Extend day a few hours past midnight</string>
|
||||
<string name="pref_midnight_delay_description">Wait until 3:00 AM to show a new day. Useful if you typically go to sleep after midnight. Requires app restart.</string>
|
||||
<string name="edit_notes">Edit notes</string>
|
||||
</resources>
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.isoron.uhabits.core.commands.CommandRunner
|
||||
import org.isoron.uhabits.core.commands.CreateRepetitionCommand
|
||||
import org.isoron.uhabits.core.models.Habit
|
||||
import org.isoron.uhabits.core.models.HabitList
|
||||
import org.isoron.uhabits.core.models.HabitType
|
||||
import org.isoron.uhabits.core.models.Timestamp
|
||||
import org.isoron.uhabits.core.preferences.Preferences
|
||||
import org.isoron.uhabits.core.tasks.ExportCSVTask
|
||||
@@ -48,15 +49,24 @@ open class ListHabitsBehavior @Inject constructor(
|
||||
|
||||
fun onEdit(habit: Habit, timestamp: Timestamp?) {
|
||||
val entries = habit.computedEntries.get(timestamp!!)
|
||||
val oldValue = entries.value.toDouble()
|
||||
val notes = entries.notes
|
||||
screen.showNumberPicker(
|
||||
oldValue / 1000,
|
||||
habit.unit,
|
||||
notes
|
||||
) { newValue: Double, newNotes:String, ->
|
||||
val value = (newValue * 1000).roundToInt()
|
||||
commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes))
|
||||
if (habit.type == HabitType.NUMERICAL) {
|
||||
val oldValue = entries.value.toDouble()
|
||||
screen.showNumberPicker(
|
||||
oldValue / 1000,
|
||||
habit.unit,
|
||||
notes
|
||||
) { newValue: Double, newNotes:String, ->
|
||||
val value = (newValue * 1000).roundToInt()
|
||||
commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes))
|
||||
}
|
||||
} else {
|
||||
val value = entries.value
|
||||
screen.showCheckmarkDialog(
|
||||
notes
|
||||
) { newNotes ->
|
||||
commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,9 +116,10 @@ open class ListHabitsBehavior @Inject constructor(
|
||||
if (prefs.isFirstRun) onFirstRun()
|
||||
}
|
||||
|
||||
fun onToggle(habit: Habit, timestamp: Timestamp?, value: Int, notes: String) {
|
||||
fun onToggle(habit: Habit, timestamp: Timestamp?, value: Int) {
|
||||
val notes = habit.computedEntries.get(timestamp!!).notes
|
||||
commandRunner.run(
|
||||
CreateRepetitionCommand(habitList, habit, timestamp!!, value, notes)
|
||||
CreateRepetitionCommand(habitList, habit, timestamp, value, notes)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -137,6 +148,11 @@ open class ListHabitsBehavior @Inject constructor(
|
||||
fun onNumberPickerDismissed() {}
|
||||
}
|
||||
|
||||
fun interface CheckMarkDialogCallback {
|
||||
fun onNotesSaved(notes: String)
|
||||
fun onNotesDismissed() {}
|
||||
}
|
||||
|
||||
interface Screen {
|
||||
fun showHabitScreen(h: Habit)
|
||||
fun showIntroScreen()
|
||||
@@ -147,6 +163,10 @@ open class ListHabitsBehavior @Inject constructor(
|
||||
notes: String,
|
||||
callback: NumberPickerCallback
|
||||
)
|
||||
fun showCheckmarkDialog(
|
||||
notes: String,
|
||||
callback: CheckMarkDialogCallback
|
||||
)
|
||||
|
||||
fun showSendBugReportToDeveloperScreen(log: String)
|
||||
fun showSendFileScreen(filename: String)
|
||||
|
||||
@@ -162,5 +162,9 @@ class HistoryCardPresenter(
|
||||
notes: String,
|
||||
callback: ListHabitsBehavior.NumberPickerCallback,
|
||||
)
|
||||
fun showCheckmarkDialog(
|
||||
notes: String,
|
||||
callback: ListHabitsBehavior.CheckMarkDialogCallback,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user