Skip to content

Commit

Permalink
Implement CheckmarkPopup
Browse files Browse the repository at this point in the history
  • Loading branch information
iSoron committed May 3, 2022
1 parent 0de6896 commit 825a5f2
Show file tree
Hide file tree
Showing 21 changed files with 530 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class EntryButtonViewTest : BaseViewTest() {
lateinit var view: CheckmarkButtonView

var toggled = false
var edited = false

@Before
override fun setUp() {
Expand All @@ -44,6 +45,7 @@ class EntryButtonViewTest : BaseViewTest() {
value = Entry.NO
color = PaletteUtils.getAndroidTestColor(5)
onToggle = { _, _, _ -> toggled = true }
onEdit = { _ -> edited = true }
}
measureView(view, dpToPixels(48), dpToPixels(48))
}
Expand All @@ -70,20 +72,28 @@ class EntryButtonViewTest : BaseViewTest() {
fun testClick_withShortToggleDisabled() {
prefs.isShortToggleEnabled = false
view.performClick()
assertFalse(toggled)
assertTrue(!toggled and edited)
}

@Test
fun testClick_withShortToggleEnabled() {
prefs.isShortToggleEnabled = true
view.performClick()
assertTrue(toggled)
assertTrue(toggled and !edited)
}

@Test
fun testLongClick() {
fun testLongClick_withShortToggleDisabled() {
prefs.isShortToggleEnabled = false
view.performLongClick()
assertTrue(toggled and !edited)
}

@Test
fun testLongClick_withShortToggleEnabled() {
prefs.isShortToggleEnabled = true
view.performLongClick()
assertTrue(toggled)
assertTrue(!toggled and edited)
}

private fun assertRendersCheckedExplicitly() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class NumberPanelViewTest : BaseViewTest() {
@Test
fun testEdit() {
val timestamps = mutableListOf<Timestamp>()
view.onEdit = { timestamps.plusAssign(it) }
view.onEdit = { _, t -> timestamps.plusAssign(t) }
view.buttons[0].performLongClick()
view.buttons[2].performLongClick()
view.buttons[3].performLongClick()
Expand All @@ -87,7 +87,7 @@ class NumberPanelViewTest : BaseViewTest() {
fun testEdit_withOffset() {
val timestamps = mutableListOf<Timestamp>()
view.dataOffset = 3
view.onEdit = { timestamps += it }
view.onEdit = { _, t -> timestamps += t }
view.buttons[0].performLongClick()
view.buttons[2].performLongClick()
view.buttons[3].performLongClick()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <[email protected]>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.isoron.uhabits.activities.common.dialogs

import android.content.Context
import android.graphics.drawable.ColorDrawable
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.widget.PopupWindow
import org.isoron.platform.gui.ScreenLocation
import org.isoron.uhabits.R
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.UNKNOWN
import org.isoron.uhabits.core.models.Entry.Companion.YES_AUTO
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome
import org.isoron.uhabits.utils.dimBehind
import org.isoron.uhabits.utils.dp
import org.isoron.uhabits.utils.sres

const val POPUP_WIDTH = 4 * 48f + 16f
const val POPUP_HEIGHT = 48f * 2.5f + 8f

class CheckmarkPopup(
private val context: Context,
private val color: Int,
private var notes: String,
private var value: Int,
private val prefs: Preferences,
private val anchor: View,
) {
var onToggle: (Int, String) -> Unit = { _, _ -> }

private val view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context)).apply {
// Required for round corners
container.clipToOutline = true
}

init {
initColors()
initTypefaces()
hideDisabledButtons()
populate()
}

private fun initColors() {
arrayOf(view.yesBtn, view.skipBtn).forEach {
it.setTextColor(color)
}
arrayOf(view.noBtn, view.unknownBtn).forEach {
it.setTextColor(view.root.sres.getColor(R.attr.contrast60))
}
}

private fun initTypefaces() {
arrayOf(view.yesBtn, view.noBtn, view.skipBtn, view.unknownBtn).forEach {
it.typeface = getFontAwesome(context)
}
}

private fun hideDisabledButtons() {
if (!prefs.isSkipEnabled) view.skipBtn.visibility = GONE
if (!prefs.areQuestionMarksEnabled) view.unknownBtn.visibility = GONE
}

private fun populate() {
val selectedBtn = when (value) {
YES_MANUAL -> view.yesBtn
YES_AUTO -> view.noBtn
NO -> view.noBtn
UNKNOWN -> if (prefs.areQuestionMarksEnabled) view.unknownBtn else view.noBtn
SKIP -> if (prefs.isSkipEnabled) view.skipBtn else view.noBtn
else -> null
}
selectedBtn?.background = ColorDrawable(view.root.sres.getColor(R.attr.contrast40))
view.notes.setText(notes)
}

fun show(location: ScreenLocation) {
val popup = PopupWindow()
popup.contentView = view.root
popup.width = view.root.dp(POPUP_WIDTH).toInt()
popup.height = view.root.dp(POPUP_HEIGHT).toInt()
popup.isFocusable = true
popup.elevation = view.root.dp(24f)
fun onClick(v: Int) {
this.value = v
popup.dismiss()
}
view.yesBtn.setOnClickListener { onClick(YES_MANUAL) }
view.noBtn.setOnClickListener { onClick(NO) }
view.skipBtn.setOnClickListener { onClick(SKIP) }
view.unknownBtn.setOnClickListener { onClick(UNKNOWN) }
popup.setOnDismissListener {
onToggle(value, view.notes.text.toString())
}
popup.showAtLocation(
anchor,
Gravity.NO_GRAVITY,
view.root.dp(location.x.toFloat()).toInt(),
view.root.dp(location.y.toFloat()).toInt(),
)
popup.dimBehind()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener {
private lateinit var commandRunner: CommandRunner
private lateinit var habit: Habit
private lateinit var preferences: Preferences
private lateinit var dataView: AndroidDataView
lateinit var dataView: AndroidDataView

private var chart: HistoryChart? = null
private var onDateClickedListener: OnDateClickedListener? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import dagger.Lazy
import org.isoron.platform.gui.ScreenLocation
import org.isoron.platform.gui.toInt
import org.isoron.platform.time.LocalDate
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog
import org.isoron.uhabits.activities.common.dialogs.CheckmarkPopup
import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory
import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog
import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory
import org.isoron.uhabits.activities.common.dialogs.POPUP_WIDTH
import org.isoron.uhabits.activities.habits.edit.HabitTypeDialog
import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter
import org.isoron.uhabits.core.commands.ArchiveHabitsCommand
Expand All @@ -43,6 +47,7 @@ import org.isoron.uhabits.core.commands.UnarchiveHabitsCommand
import org.isoron.uhabits.core.models.Frequency
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.tasks.TaskRunner
import org.isoron.uhabits.core.ui.ThemeSwitcher
import org.isoron.uhabits.core.ui.callbacks.OnColorPickedCallback
Expand All @@ -63,6 +68,7 @@ import org.isoron.uhabits.tasks.ExportDBTaskFactory
import org.isoron.uhabits.tasks.ImportDataTask
import org.isoron.uhabits.tasks.ImportDataTaskFactory
import org.isoron.uhabits.utils.copyTo
import org.isoron.uhabits.utils.currentTheme
import org.isoron.uhabits.utils.restartWithFade
import org.isoron.uhabits.utils.showMessage
import org.isoron.uhabits.utils.showSendEmailScreen
Expand Down Expand Up @@ -93,7 +99,9 @@ class ListHabitsScreen
private val colorPickerFactory: ColorPickerDialogFactory,
private val numberPickerFactory: NumberPickerFactory,
private val checkMarkDialog: CheckmarkDialog,
private val behavior: Lazy<ListHabitsBehavior>
private val behavior: Lazy<ListHabitsBehavior>,
private val preferences: Preferences,
private val rootView: Lazy<ListHabitsRootView>,
) : CommandRunner.Listener,
ListHabitsBehavior.Screen,
ListHabitsMenuBehavior.Screen,
Expand Down Expand Up @@ -237,6 +245,32 @@ class ListHabitsScreen
numberPickerFactory.create(value, unit, notes, dateString, frequency, callback).show()
}

override fun showCheckmarkPopup(
selectedValue: Int,
notes: String,
color: PaletteColor,
location: ScreenLocation,
callback: ListHabitsBehavior.CheckMarkDialogCallback
) {
val view = rootView.get()
CheckmarkPopup(
context = context,
prefs = preferences,
anchor = view,
color = view.currentTheme().color(color).toInt(),
notes = notes,
value = selectedValue,
).apply {
onToggle = { value, notes -> callback.onNotesSaved(value, notes) }
show(
ScreenLocation(
x = location.x - POPUP_WIDTH / 2,
y = location.y
)
)
}
}

override fun showCheckmarkDialog(
selectedValue: Int,
notes: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import android.text.TextPaint
import android.view.HapticFeedbackConstants
import android.view.View
import android.view.View.MeasureSpec.EXACTLY
import org.isoron.platform.gui.ScreenLocation
import org.isoron.uhabits.R
import org.isoron.uhabits.core.models.Entry
import org.isoron.uhabits.core.models.Entry.Companion.NO
Expand All @@ -38,6 +39,7 @@ import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.inject.ActivityContext
import org.isoron.uhabits.utils.drawNotesIndicator
import org.isoron.uhabits.utils.getCenter
import org.isoron.uhabits.utils.getFontAwesome
import org.isoron.uhabits.utils.sp
import org.isoron.uhabits.utils.sres
Expand Down Expand Up @@ -81,7 +83,8 @@ class CheckmarkButtonView(

var onToggle: (Int, String, Long) -> Unit = { _, _, _ -> }

var onEdit: () -> Unit = {}
var onEdit: (ScreenLocation) -> Unit = { _ -> }

private var drawer = Drawer()

init {
Expand All @@ -102,11 +105,11 @@ class CheckmarkButtonView(

override fun onClick(v: View) {
if (preferences.isShortToggleEnabled) performToggle(TOGGLE_DELAY_MILLIS)
else onEdit()
else onEdit(getCenter())
}

override fun onLongClick(v: View): Boolean {
if (preferences.isShortToggleEnabled) onEdit()
if (preferences.isShortToggleEnabled) onEdit(getCenter())
else performToggle(TOGGLE_DELAY_MILLIS)
return true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.isoron.uhabits.activities.habits.list.views

import android.content.Context
import org.isoron.platform.gui.ScreenLocation
import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN
import org.isoron.uhabits.core.models.Timestamp
import org.isoron.uhabits.core.preferences.Preferences
Expand Down Expand Up @@ -66,7 +67,7 @@ class CheckmarkPanelView(
setupButtons()
}

var onEdit: (Timestamp) -> Unit = {}
var onEdit: (ScreenLocation, Timestamp) -> Unit = { _, _ -> }
set(value) {
field = value
setupButtons()
Expand All @@ -90,7 +91,7 @@ class CheckmarkPanelView(
}
button.color = color
button.onToggle = { value, notes, delay -> onToggle(timestamp, value, notes, delay) }
button.onEdit = { onEdit(timestamp) }
button.onEdit = { location -> onEdit(location, timestamp) }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,17 +167,17 @@ class HabitCardView(
{ runPendingToggles(taskId) }.delay(delay)
}
}
onEdit = { timestamp ->
onEdit = { location, timestamp ->
triggerRipple(timestamp)
habit?.let { behavior.onEdit(it, timestamp) }
habit?.let { behavior.onEdit(location, it, timestamp) }
}
}

numberPanel = numberPanelFactory.create().apply {
visibility = GONE
onEdit = { timestamp ->
onEdit = { location, timestamp ->
triggerRipple(timestamp)
habit?.let { behavior.onEdit(it, timestamp) }
habit?.let { behavior.onEdit(location, it, timestamp) }
}
}

Expand Down
Loading

0 comments on commit 825a5f2

Please sign in to comment.