mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Move showConfetti to ListHabitsScreen; use button location; other tweaks
This commit is contained in:
@@ -24,7 +24,6 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AppCompatDialogFragment
|
||||
import org.isoron.uhabits.HabitsApplication
|
||||
import org.isoron.uhabits.R
|
||||
@@ -34,18 +33,19 @@ import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN
|
||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
||||
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
|
||||
import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome
|
||||
import org.isoron.uhabits.utils.showConfetti
|
||||
import org.isoron.uhabits.utils.getCenter
|
||||
import org.isoron.uhabits.utils.sres
|
||||
|
||||
class CheckmarkDialog : AppCompatDialogFragment() {
|
||||
var onToggle: (Int, String) -> Unit = { _, _ -> }
|
||||
var onToggle: (Int, String, Float, Float) -> Unit = { _, _, _, _ -> }
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val appComponent = (requireActivity().application as HabitsApplication).component
|
||||
val prefs = appComponent.preferences
|
||||
val view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context))
|
||||
val color = requireArguments().getInt("color")
|
||||
arrayOf(view.yesBtn, view.skipBtn).forEach {
|
||||
it.setTextColor(requireArguments().getInt("color"))
|
||||
it.setTextColor(color)
|
||||
}
|
||||
arrayOf(view.noBtn, view.unknownBtn).forEach {
|
||||
it.setTextColor(view.root.sres.getColor(R.attr.contrast60))
|
||||
@@ -64,12 +64,9 @@ class CheckmarkDialog : AppCompatDialogFragment() {
|
||||
}
|
||||
fun onClick(v: Int) {
|
||||
val notes = view.notes.text.toString().trim()
|
||||
onToggle(v, notes)
|
||||
val location = view.yesBtn.getCenter()
|
||||
onToggle(v, notes, location.x, location.y)
|
||||
requireDialog().dismiss()
|
||||
val konfettiView = requireActivity().findViewById<LinearLayout>(R.id.konfettiLayout)
|
||||
when (v) {
|
||||
YES_MANUAL -> showConfetti(konfettiView)
|
||||
}
|
||||
}
|
||||
view.yesBtn.setOnClickListener { onClick(YES_MANUAL) }
|
||||
view.noBtn.setOnClickListener { onClick(NO) }
|
||||
|
||||
@@ -9,15 +9,14 @@ import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AppCompatDialogFragment
|
||||
import org.isoron.uhabits.HabitsApplication
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.core.models.Entry
|
||||
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
|
||||
import org.isoron.uhabits.utils.InterfaceUtils
|
||||
import org.isoron.uhabits.utils.getCenter
|
||||
import org.isoron.uhabits.utils.requestFocusWithKeyboard
|
||||
import org.isoron.uhabits.utils.showConfetti
|
||||
import org.isoron.uhabits.utils.sres
|
||||
import java.text.DecimalFormat
|
||||
import java.text.DecimalFormatSymbols
|
||||
@@ -26,7 +25,7 @@ import java.text.ParseException
|
||||
|
||||
class NumberDialog : AppCompatDialogFragment() {
|
||||
|
||||
var onToggle: (Double, String) -> Unit = { _, _ -> }
|
||||
var onToggle: (Double, String, Float, Float) -> Unit = { _, _, _, _ -> }
|
||||
var onDismiss: () -> Unit = {}
|
||||
|
||||
private var originalNotes: String = ""
|
||||
@@ -115,13 +114,8 @@ class NumberDialog : AppCompatDialogFragment() {
|
||||
// NOP
|
||||
}
|
||||
val notes = view.notes.text.toString()
|
||||
onToggle(value, notes)
|
||||
val location = view.saveBtn.getCenter()
|
||||
onToggle(value, notes, location.x, location.y)
|
||||
requireDialog().dismiss()
|
||||
val konfettiView = requireActivity().findViewById<LinearLayout>(R.id.konfettiLayout)
|
||||
|
||||
if (value > 0.0) {
|
||||
// To motivate, show confetti even if some value is present
|
||||
showConfetti(konfettiView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.Context
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.RelativeLayout
|
||||
import nl.dionsegijn.konfetti.xml.KonfettiView
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.activities.common.views.ScrollableChart
|
||||
import org.isoron.uhabits.activities.common.views.TaskProgressBar
|
||||
@@ -43,7 +44,6 @@ import org.isoron.uhabits.inject.ActivityScope
|
||||
import org.isoron.uhabits.utils.addAtBottom
|
||||
import org.isoron.uhabits.utils.addAtTop
|
||||
import org.isoron.uhabits.utils.addBelow
|
||||
import org.isoron.uhabits.utils.buildKonfettiView
|
||||
import org.isoron.uhabits.utils.buildToolbar
|
||||
import org.isoron.uhabits.utils.currentTheme
|
||||
import org.isoron.uhabits.utils.dim
|
||||
@@ -70,7 +70,9 @@ class ListHabitsRootView @Inject constructor(
|
||||
val listView: HabitCardListView = habitCardListViewFactory.create()
|
||||
val llEmpty = EmptyListView(context)
|
||||
val tbar = buildToolbar()
|
||||
val konfettiView = buildKonfettiView()
|
||||
val konfettiView = KonfettiView(context).apply {
|
||||
translationZ = 10f
|
||||
}
|
||||
val progressBar = TaskProgressBar(context, runner)
|
||||
val hintView: HintView
|
||||
val header = HeaderView(context, preferences, midnightTimer)
|
||||
|
||||
@@ -25,6 +25,9 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import dagger.Lazy
|
||||
import nl.dionsegijn.konfetti.core.Party
|
||||
import nl.dionsegijn.konfetti.core.Position
|
||||
import nl.dionsegijn.konfetti.core.emitter.Emitter
|
||||
import org.isoron.platform.gui.toInt
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog
|
||||
@@ -63,6 +66,7 @@ import org.isoron.uhabits.intents.IntentFactory
|
||||
import org.isoron.uhabits.tasks.ExportDBTaskFactory
|
||||
import org.isoron.uhabits.tasks.ImportDataTask
|
||||
import org.isoron.uhabits.tasks.ImportDataTaskFactory
|
||||
import org.isoron.uhabits.utils.ColorUtils
|
||||
import org.isoron.uhabits.utils.copyTo
|
||||
import org.isoron.uhabits.utils.currentTheme
|
||||
import org.isoron.uhabits.utils.dismissCurrentAndShow
|
||||
@@ -72,6 +76,7 @@ import org.isoron.uhabits.utils.showSendEmailScreen
|
||||
import org.isoron.uhabits.utils.showSendFileScreen
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
const val RESULT_IMPORT_DATA = 101
|
||||
@@ -218,6 +223,28 @@ class ListHabitsScreen
|
||||
activity.showSendFileScreen(filename)
|
||||
}
|
||||
|
||||
override fun showConfetti(color: PaletteColor, x: Float, y: Float) {
|
||||
val baseColor = themeSwitcher.currentTheme!!.color(color).toInt()
|
||||
rootView.get().konfettiView.start(
|
||||
Party(
|
||||
speed = 0f,
|
||||
maxSpeed = 16f,
|
||||
damping = 0.9f,
|
||||
spread = 360,
|
||||
angle = 0,
|
||||
colors = listOf(
|
||||
ColorUtils.changeHue(baseColor, 180f),
|
||||
ColorUtils.changeHue(baseColor, 20f),
|
||||
ColorUtils.changeHue(baseColor, -20f),
|
||||
baseColor
|
||||
),
|
||||
position = Position.Absolute(x, y),
|
||||
emitter = Emitter(duration = 25, TimeUnit.MILLISECONDS).max(25),
|
||||
timeToLive = 0
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun showSettingsScreen() {
|
||||
val intent = intentFactory.startSettingsActivity(activity)
|
||||
activity.startActivityForResult(intent, REQUEST_SETTINGS)
|
||||
@@ -240,7 +267,7 @@ class ListHabitsScreen
|
||||
putDouble("value", value)
|
||||
putString("notes", notes)
|
||||
}
|
||||
dialog.onToggle = { v, n -> callback.onNumberPicked(v, n) }
|
||||
dialog.onToggle = { v, n, x, y -> callback.onNumberPicked(v, n, x, y) }
|
||||
dialog.dismissCurrentAndShow(fm, "numberDialog")
|
||||
}
|
||||
|
||||
@@ -258,7 +285,7 @@ class ListHabitsScreen
|
||||
putInt("value", selectedValue)
|
||||
putString("notes", notes)
|
||||
}
|
||||
dialog.onToggle = { v, n -> callback.onNotesSaved(v, n) }
|
||||
dialog.onToggle = { v, n, x, y -> callback.onNotesSaved(v, n, x, y) }
|
||||
dialog.dismissCurrentAndShow(fm, "checkmarkDialog")
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.isoron.uhabits.core.preferences.Preferences
|
||||
import org.isoron.uhabits.inject.ActivityContext
|
||||
import org.isoron.uhabits.utils.drawNotesIndicator
|
||||
import org.isoron.uhabits.utils.getFontAwesome
|
||||
import org.isoron.uhabits.utils.showConfetti
|
||||
import org.isoron.uhabits.utils.sp
|
||||
import org.isoron.uhabits.utils.sres
|
||||
import org.isoron.uhabits.utils.toMeasureSpec
|
||||
@@ -89,7 +88,7 @@ class CheckmarkButtonView(
|
||||
setOnLongClickListener(this)
|
||||
}
|
||||
|
||||
fun performToggle(view: View) {
|
||||
fun performToggle() {
|
||||
value = Entry.nextToggleValue(
|
||||
value = value,
|
||||
isSkipEnabled = preferences.isSkipEnabled,
|
||||
@@ -97,15 +96,12 @@ class CheckmarkButtonView(
|
||||
)
|
||||
onToggle(value, notes)
|
||||
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
when (value) {
|
||||
YES_MANUAL -> showConfetti(view.rootView)
|
||||
}
|
||||
invalidate()
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
if (preferences.isShortToggleEnabled) {
|
||||
performToggle(v)
|
||||
performToggle()
|
||||
} else {
|
||||
onEdit()
|
||||
}
|
||||
@@ -115,7 +111,7 @@ class CheckmarkButtonView(
|
||||
if (preferences.isShortToggleEnabled) {
|
||||
onEdit()
|
||||
} else {
|
||||
performToggle(v)
|
||||
performToggle()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package org.isoron.uhabits.activities.habits.list.views
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.PointF
|
||||
import android.graphics.text.LineBreaker.BREAK_STRATEGY_BALANCED
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
@@ -154,7 +155,17 @@ class HabitCardView(
|
||||
checkmarkPanel = checkmarkPanelFactory.create().apply {
|
||||
onToggle = { timestamp, value, notes ->
|
||||
triggerRipple(timestamp)
|
||||
habit?.let { behavior.onToggle(it, timestamp, value, notes) }
|
||||
val location = getAbsoluteButtonLocation(timestamp)
|
||||
habit?.let {
|
||||
behavior.onToggle(
|
||||
it,
|
||||
timestamp,
|
||||
value,
|
||||
notes,
|
||||
location.x,
|
||||
location.y
|
||||
)
|
||||
}
|
||||
}
|
||||
onEdit = { timestamp ->
|
||||
triggerRipple(timestamp)
|
||||
@@ -206,12 +217,27 @@ class HabitCardView(
|
||||
}
|
||||
|
||||
fun triggerRipple(timestamp: Timestamp) {
|
||||
val location = getRelativeButtonLocation(timestamp)
|
||||
triggerRipple(location.x, location.y)
|
||||
}
|
||||
|
||||
private fun getRelativeButtonLocation(timestamp: Timestamp): PointF {
|
||||
val today = DateUtils.getTodayWithOffset()
|
||||
val offset = timestamp.daysUntil(today) - dataOffset
|
||||
val button = checkmarkPanel.buttons[offset]
|
||||
val y = button.height / 2.0f
|
||||
val x = checkmarkPanel.x + button.x + (button.width / 2).toFloat()
|
||||
triggerRipple(x, y)
|
||||
return PointF(x, y)
|
||||
}
|
||||
|
||||
private fun getAbsoluteButtonLocation(timestamp: Timestamp): PointF {
|
||||
val containerLocation = IntArray(2)
|
||||
this.getLocationOnScreen(containerLocation)
|
||||
val relButtonLocation = getRelativeButtonLocation(timestamp)
|
||||
return PointF(
|
||||
containerLocation[0].toFloat() + relButtonLocation.x,
|
||||
containerLocation[1].toFloat() - relButtonLocation.y
|
||||
)
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
|
||||
@@ -179,7 +179,7 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
||||
putDouble("value", value)
|
||||
putString("notes", notes)
|
||||
}
|
||||
dialog.onToggle = { v, n -> callback.onNumberPicked(v, n) }
|
||||
dialog.onToggle = { v, n, x, y -> callback.onNumberPicked(v, n, x, y) }
|
||||
dialog.dismissCurrentAndShow(supportFragmentManager, "numberDialog")
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
||||
putInt("value", selectedValue)
|
||||
putString("notes", notes)
|
||||
}
|
||||
dialog.onToggle = { v, n -> callback.onNotesSaved(v, n) }
|
||||
dialog.onToggle = { v, n, x, y -> callback.onNotesSaved(v, n, x, y) }
|
||||
dialog.dismissCurrentAndShow(supportFragmentManager, "checkmarkDialog")
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,13 @@ object ColorUtils {
|
||||
return a or r or g or b
|
||||
}
|
||||
|
||||
fun changeHue(color: Int, delta: Float): Int {
|
||||
val hsv = FloatArray(3)
|
||||
Color.colorToHSV(color, hsv)
|
||||
hsv[0] = (hsv[0] + delta).mod(360f)
|
||||
return Color.HSVToColor(hsv)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setAlpha(color: Int, newAlpha: Float): Int {
|
||||
val intAlpha = (newAlpha * 255).toInt()
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.content.Intent
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.PointF
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Handler
|
||||
import android.os.SystemClock
|
||||
@@ -36,7 +37,6 @@ import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import android.view.WindowManager
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM
|
||||
import android.widget.RelativeLayout.ALIGN_PARENT_TOP
|
||||
@@ -47,10 +47,6 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.FileProvider
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import nl.dionsegijn.konfetti.core.Party
|
||||
import nl.dionsegijn.konfetti.core.Position
|
||||
import nl.dionsegijn.konfetti.core.emitter.Emitter
|
||||
import nl.dionsegijn.konfetti.xml.KonfettiView
|
||||
import org.isoron.platform.gui.toInt
|
||||
import org.isoron.uhabits.HabitsApplication
|
||||
import org.isoron.uhabits.R
|
||||
@@ -58,7 +54,6 @@ import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
||||
import org.isoron.uhabits.core.models.PaletteColor
|
||||
import org.isoron.uhabits.core.ui.views.Theme
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
fun RelativeLayout.addBelow(
|
||||
view: View,
|
||||
@@ -83,9 +78,7 @@ fun RelativeLayout.addAtBottom(
|
||||
view.layoutParams = RelativeLayout.LayoutParams(width, height).apply {
|
||||
addRule(ALIGN_PARENT_BOTTOM)
|
||||
}
|
||||
if (view.id == null) {
|
||||
view.id = View.generateViewId()
|
||||
}
|
||||
view.id = View.generateViewId()
|
||||
this.addView(view)
|
||||
}
|
||||
|
||||
@@ -97,10 +90,7 @@ fun RelativeLayout.addAtTop(
|
||||
view.layoutParams = RelativeLayout.LayoutParams(width, height).apply {
|
||||
addRule(ALIGN_PARENT_TOP)
|
||||
}
|
||||
|
||||
if (view.id == null) {
|
||||
view.id = View.generateViewId()
|
||||
}
|
||||
view.id = View.generateViewId()
|
||||
this.addView(view)
|
||||
}
|
||||
|
||||
@@ -109,32 +99,6 @@ fun ViewGroup.buildToolbar(): Toolbar {
|
||||
return inflater.inflate(R.layout.toolbar, null) as Toolbar
|
||||
}
|
||||
|
||||
fun ViewGroup.buildKonfettiView(): View {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
return inflater.inflate(R.layout.konfetti, null) as View
|
||||
}
|
||||
|
||||
fun showConfetti(view: View) {
|
||||
val viewId = R.id.konfetttiView
|
||||
val linearLayout = view.findViewById<LinearLayout>(R.id.konfettiLayout)
|
||||
val kv = view.findViewById<KonfettiView>(viewId)
|
||||
if (linearLayout != null) {
|
||||
linearLayout.bringToFront()
|
||||
}
|
||||
val party = Party(
|
||||
speed = 0f,
|
||||
maxSpeed = 32f,
|
||||
damping = 0.9f,
|
||||
spread = 360,
|
||||
colors = listOf(0xfce18a, 0xff726d, 0xf4306d, 0xb48def, 0x818181, 0x81a48c),
|
||||
position = Position.Relative(0.5, 0.3),
|
||||
emitter = Emitter(duration = 300, TimeUnit.MILLISECONDS).max(300)
|
||||
)
|
||||
if (kv != null) {
|
||||
kv.start(party)
|
||||
}
|
||||
}
|
||||
|
||||
fun View.showMessage(msg: String) {
|
||||
try {
|
||||
val snackbar = Snackbar.make(this, msg, Snackbar.LENGTH_SHORT)
|
||||
@@ -172,7 +136,11 @@ fun Activity.startActivitySafely(intent: Intent) {
|
||||
}
|
||||
}
|
||||
|
||||
fun Activity.showSendEmailScreen(@StringRes toId: Int, @StringRes subjectId: Int, content: String?) {
|
||||
fun Activity.showSendEmailScreen(
|
||||
@StringRes toId: Int,
|
||||
@StringRes subjectId: Int,
|
||||
content: String?
|
||||
) {
|
||||
val to = this.getString(toId)
|
||||
val subject = this.getString(subjectId)
|
||||
this.startActivity(
|
||||
@@ -269,3 +237,11 @@ fun View.requestFocusWithKeyboard() {
|
||||
dispatchTouchEvent(MotionEvent.obtain(time, time, MotionEvent.ACTION_UP, 0f, 0f, 0))
|
||||
}, 250)
|
||||
}
|
||||
|
||||
fun View.getCenter(): PointF {
|
||||
val viewLocation = IntArray(2)
|
||||
this.getLocationOnScreen(viewLocation)
|
||||
viewLocation[0] += this.width / 2
|
||||
viewLocation[1] -= this.height / 2
|
||||
return PointF(viewLocation[0].toFloat(), viewLocation[1].toFloat())
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2013 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/konfettiLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="false"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<nl.dionsegijn.konfetti.xml.KonfettiView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/konfetttiView"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -20,9 +20,12 @@ package org.isoron.uhabits.core.ui.screens.habits.list
|
||||
|
||||
import org.isoron.uhabits.core.commands.CommandRunner
|
||||
import org.isoron.uhabits.core.commands.CreateRepetitionCommand
|
||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
||||
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.NumericalHabitType.AT_LEAST
|
||||
import org.isoron.uhabits.core.models.NumericalHabitType.AT_MOST
|
||||
import org.isoron.uhabits.core.models.PaletteColor
|
||||
import org.isoron.uhabits.core.models.Timestamp
|
||||
import org.isoron.uhabits.core.preferences.Preferences
|
||||
@@ -52,8 +55,16 @@ open class ListHabitsBehavior @Inject constructor(
|
||||
val entry = habit.computedEntries.get(timestamp!!)
|
||||
if (habit.type == HabitType.NUMERICAL) {
|
||||
val oldValue = entry.value.toDouble() / 1000
|
||||
screen.showNumberPopup(oldValue, entry.notes) { newValue: Double, newNotes: String ->
|
||||
screen.showNumberPopup(oldValue, entry.notes) { newValue: Double, newNotes: String, x: Float, y: Float ->
|
||||
val value = (newValue * 1000).roundToInt()
|
||||
if (newValue != oldValue) {
|
||||
if (
|
||||
(habit.targetType == AT_LEAST && newValue >= habit.targetValue) ||
|
||||
(habit.targetType == AT_MOST && newValue <= habit.targetValue)
|
||||
) {
|
||||
screen.showConfetti(habit.color, x, y)
|
||||
}
|
||||
}
|
||||
commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes))
|
||||
}
|
||||
} else {
|
||||
@@ -61,7 +72,8 @@ open class ListHabitsBehavior @Inject constructor(
|
||||
entry.value,
|
||||
entry.notes,
|
||||
habit.color
|
||||
) { newValue, newNotes ->
|
||||
) { newValue: Int, newNotes: String, x: Float, y: Float ->
|
||||
if (newValue != entry.value && newValue == YES_MANUAL) screen.showConfetti(habit.color, x, y)
|
||||
commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, newValue, newNotes))
|
||||
}
|
||||
}
|
||||
@@ -117,10 +129,11 @@ 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, notes: String, x: Float, y: Float) {
|
||||
commandRunner.run(
|
||||
CreateRepetitionCommand(habitList, habit, timestamp, value, notes)
|
||||
)
|
||||
if (value == YES_MANUAL) screen.showConfetti(habit.color, x, y)
|
||||
}
|
||||
|
||||
enum class Message {
|
||||
@@ -144,12 +157,22 @@ open class ListHabitsBehavior @Inject constructor(
|
||||
}
|
||||
|
||||
fun interface NumberPickerCallback {
|
||||
fun onNumberPicked(newValue: Double, notes: String)
|
||||
fun onNumberPicked(
|
||||
newValue: Double,
|
||||
notes: String,
|
||||
x: Float,
|
||||
y: Float
|
||||
)
|
||||
fun onNumberPickerDismissed() {}
|
||||
}
|
||||
|
||||
fun interface CheckMarkDialogCallback {
|
||||
fun onNotesSaved(value: Int, notes: String)
|
||||
fun onNotesSaved(
|
||||
value: Int,
|
||||
notes: String,
|
||||
x: Float,
|
||||
y: Float
|
||||
)
|
||||
fun onNotesDismissed() {}
|
||||
}
|
||||
|
||||
@@ -170,5 +193,6 @@ open class ListHabitsBehavior @Inject constructor(
|
||||
)
|
||||
fun showSendBugReportToDeveloperScreen(log: String)
|
||||
fun showSendFileScreen(filename: String)
|
||||
fun showConfetti(color: PaletteColor, x: Float, y: Float)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ class HistoryCardPresenter(
|
||||
entry.value,
|
||||
entry.notes,
|
||||
habit.color
|
||||
) { newValue, newNotes ->
|
||||
) { newValue, newNotes, _: Float, _: Float ->
|
||||
commandRunner.run(
|
||||
CreateRepetitionCommand(
|
||||
habitList,
|
||||
@@ -135,7 +135,7 @@ class HistoryCardPresenter(
|
||||
screen.showNumberPopup(
|
||||
value = oldValue / 1000.0,
|
||||
notes = entry.notes
|
||||
) { newValue: Double, newNotes: String ->
|
||||
) { newValue: Double, newNotes: String, _: Float, _: Float ->
|
||||
val thousands = (newValue * 1000).roundToInt()
|
||||
commandRunner.run(
|
||||
CreateRepetitionCommand(
|
||||
|
||||
@@ -84,7 +84,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() {
|
||||
eq(""),
|
||||
picker.capture()
|
||||
)
|
||||
picker.lastValue.onNumberPicked(100.0, "")
|
||||
picker.lastValue.onNumberPicked(100.0, "", 0f, 0f)
|
||||
val today = getTodayWithOffset()
|
||||
assertThat(habit2.computedEntries.get(today).value, equalTo(100000))
|
||||
}
|
||||
@@ -168,7 +168,9 @@ class ListHabitsBehaviorTest : BaseUnitTest() {
|
||||
habit = habit1,
|
||||
timestamp = getToday(),
|
||||
value = Entry.NO,
|
||||
notes = ""
|
||||
notes = "",
|
||||
x = 0f,
|
||||
y = 0f
|
||||
)
|
||||
assertFalse(habit1.isCompletedToday())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user