Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement numerical habits with AT_MOST target type #1101

Merged
merged 12 commits into from
Sep 29, 2021
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.test.filters.MediumTest
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
import org.isoron.uhabits.BaseViewTest
import org.isoron.uhabits.core.models.NumericalHabitType
import org.isoron.uhabits.utils.PaletteUtils
import org.junit.Before
import org.junit.Test
Expand All @@ -42,6 +43,7 @@ class NumberButtonViewTest : BaseViewTest() {
super.setUp()
view = component.getNumberButtonViewFactory().create().apply {
units = "steps"
targetType = NumericalHabitType.AT_LEAST
threshold = 100.0
color = PaletteUtils.getAndroidTestColor(8)
onEdit = { edited = true }
Expand Down Expand Up @@ -74,10 +76,10 @@ class NumberButtonViewTest : BaseViewTest() {
}

@Test
fun testRender_emptyUnits() {
fun testRender_atMostAboveThreshold() {
view.value = 500.0
view.units = ""
assertRenders(view, "$PATH/render_unitless.png")
view.targetType = NumericalHabitType.AT_MOST
assertRenders(view, "$PATH/render_at_most_above.png")
}

@Test
Expand All @@ -86,12 +88,33 @@ class NumberButtonViewTest : BaseViewTest() {
assertRenders(view, "$PATH/render_below.png")
}

@Test
fun testRender_atMostBetweenThresholds() {
view.value = 110.0
view.targetType = NumericalHabitType.AT_MOST
assertRenders(view, "$PATH/render_at_most_between.png")
}

@Test
fun testRender_zero() {
view.value = 0.0
assertRenders(view, "$PATH/render_zero.png")
}

@Test
fun testRender_atMostBelowThreshold() {
view.value = 0.0
view.targetType = NumericalHabitType.AT_MOST
assertRenders(view, "$PATH/render_at_most_below.png")
}

@Test
fun testRender_emptyUnits() {
view.value = 500.0
view.units = ""
assertRenders(view, "$PATH/render_unitless.png")
}

@Test
fun testClick_shortToggleDisabled() {
prefs.isShortToggleEnabled = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.test.filters.MediumTest
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
import org.isoron.uhabits.BaseViewTest
import org.isoron.uhabits.core.models.NumericalHabitType
import org.isoron.uhabits.core.models.Timestamp
import org.isoron.uhabits.utils.PaletteUtils
import org.junit.After
Expand Down Expand Up @@ -55,6 +56,7 @@ class NumberPanelViewTest : BaseViewTest() {
buttonCount = 4
color = PaletteUtils.getAndroidTestColor(7)
units = "steps"
targetType = NumericalHabitType.AT_LEAST
threshold = 5000.0
}
view.onAttachedToWindow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ class SubtitleCardViewTest : BaseViewTest() {
isNumerical = false,
question = "Did you meditate this morning?",
reminder = Reminder(8, 30, EVERY_DAY),
unit = "",
targetValue = 0.0,
theme = LightTheme(),
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener {
firstWeekday = preferences.firstWeekday,
paletteColor = habit.color,
series = emptyList(),
defaultSquare = HistoryChart.Square.OFF,
theme = themeSwitcher.currentTheme,
today = DateUtils.getTodayWithOffset().toLocalDate(),
onDateClickedListener = onDateClickedListener ?: OnDateClickedListener { },
Expand Down Expand Up @@ -101,6 +102,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener {
theme = LightTheme()
)
chart?.series = model.series
chart?.defaultSquare = model.defaultSquare
dataView.postInvalidate()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class EditHabitActivity : AppCompatActivity() {
var reminderHour = -1
var reminderMin = -1
var reminderDays: WeekdayList = WeekdayList.EVERY_DAY
var targetType = NumericalHabitType.AT_LEAST

override fun onCreate(state: Bundle?) {
super.onCreate(state)
Expand All @@ -107,6 +108,7 @@ class EditHabitActivity : AppCompatActivity() {
color = habit.color
freqNum = habit.frequency.numerator
freqDen = habit.frequency.denominator
targetType = habit.targetType
habit.reminder?.let {
reminderHour = it.hour
reminderMin = it.minute
Expand Down Expand Up @@ -138,6 +140,7 @@ class EditHabitActivity : AppCompatActivity() {
HabitType.YES_NO -> {
binding.unitOuterBox.visibility = View.GONE
binding.targetOuterBox.visibility = View.GONE
binding.targetTypeOuterBox.visibility = View.GONE
}
HabitType.NUMERICAL -> {
binding.nameInput.hint = getString(R.string.measurable_short_example)
Expand Down Expand Up @@ -172,6 +175,23 @@ class EditHabitActivity : AppCompatActivity() {
dialog.show(supportFragmentManager, "frequencyPicker")
}

populateTargetType()
binding.targetTypePicker.setOnClickListener {
val builder = AlertDialog.Builder(this)
val arrayAdapter = ArrayAdapter<String>(this, android.R.layout.select_dialog_item)
arrayAdapter.add(getString(R.string.target_type_at_least))
arrayAdapter.add(getString(R.string.target_type_at_most))
builder.setAdapter(arrayAdapter) { dialog, which ->
targetType = when (which) {
0 -> NumericalHabitType.AT_LEAST
else -> NumericalHabitType.AT_MOST
}
populateTargetType()
dialog.dismiss()
}
builder.show()
}

binding.numericalFrequencyPicker.setOnClickListener {
val builder = AlertDialog.Builder(this)
val arrayAdapter = ArrayAdapter<String>(this, android.R.layout.select_dialog_item)
Expand Down Expand Up @@ -262,7 +282,7 @@ class EditHabitActivity : AppCompatActivity() {
habit.frequency = Frequency(freqNum, freqDen)
if (habitType == HabitType.NUMERICAL) {
habit.targetValue = targetInput.text.toString().toDouble()
habit.targetType = NumericalHabitType.AT_LEAST
habit.targetType = targetType
habit.unit = unitInput.text.trim().toString()
}
habit.type = habitType
Expand Down Expand Up @@ -324,6 +344,13 @@ class EditHabitActivity : AppCompatActivity() {
}
}

private fun populateTargetType() {
binding.targetTypePicker.text = when (targetType) {
NumericalHabitType.AT_MOST -> getString(R.string.target_type_at_most)
else -> getString(R.string.target_type_at_least)
}
}

private fun updateColors() {
androidColor = themeSwitcher.currentTheme.color(color).toInt()
binding.colorButton.backgroundTintList = ColorStateList.valueOf(androidColor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ class HabitCardView(
numberPanel.apply {
color = c
units = h.unit
targetType = h.targetType
threshold = h.targetValue
visibility = when (h.isNumerical) {
true -> View.VISIBLE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ import android.view.View
import android.view.View.OnClickListener
import android.view.View.OnLongClickListener
import org.isoron.uhabits.R
import org.isoron.uhabits.core.models.NumericalHabitType
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.inject.ActivityContext
import org.isoron.uhabits.utils.InterfaceUtils.getDimension
import org.isoron.uhabits.utils.StyledResources
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 java.lang.Double.max
import java.text.DecimalFormat
import javax.inject.Inject

Expand Down Expand Up @@ -88,6 +90,12 @@ class NumberButtonView(
invalidate()
}

var targetType = NumericalHabitType.AT_LEAST
set(value) {
field = value
invalidate()
}

var units = ""
set(value) {
field = value
Expand Down Expand Up @@ -127,7 +135,6 @@ class NumberButtonView(

private val em: Float
private val rect: RectF = RectF()
private val sr = StyledResources(context)

private val lowContrast: Int
private val mediumContrast: Int
Expand All @@ -148,15 +155,23 @@ class NumberButtonView(

init {
em = pNumber.measureText("m")
lowContrast = sr.getColor(R.attr.contrast40)
mediumContrast = sr.getColor(R.attr.contrast60)
lowContrast = sres.getColor(R.attr.contrast40)
mediumContrast = sres.getColor(R.attr.contrast60)
}

fun draw(canvas: Canvas) {
val activeColor = when {
value <= 0.0 -> lowContrast
value < threshold -> mediumContrast
else -> color
var activeColor = if (targetType == NumericalHabitType.AT_LEAST) {
when {
value < 0.0 && preferences.areQuestionMarksEnabled -> lowContrast
max(0.0, value) >= threshold -> color
else -> mediumContrast
}
} else {
when {
value < 0.0 && preferences.areQuestionMarksEnabled -> lowContrast
value <= threshold -> color
else -> mediumContrast
}
}

val label: String
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.uhabits.core.models.NumericalHabitType
import org.isoron.uhabits.core.models.Timestamp
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.utils.DateUtils
Expand Down Expand Up @@ -47,6 +48,12 @@ class NumberPanelView(
setupButtons()
}

var targetType = NumericalHabitType.AT_LEAST
set(value) {
field = value
setupButtons()
}

var threshold = 0.0
set(value) {
field = value
Expand Down Expand Up @@ -84,6 +91,7 @@ class NumberPanelView(
else -> 0.0
}
button.color = color
button.targetType = targetType
button.threshold = threshold
button.units = units
button.onEdit = { onEdit(timestamp) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class HistoryCardView(context: Context, attrs: AttributeSet) : LinearLayout(cont
theme = state.theme,
dateFormatter = JavaLocalDateFormatter(Locale.getDefault()),
series = state.series,
defaultSquare = state.defaultSquare,
firstWeekday = state.firstWeekday,
)
binding.chart.postInvalidate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import org.isoron.platform.gui.toInt
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.habits.edit.formatFrequency
import org.isoron.uhabits.activities.habits.list.views.toShortString
import org.isoron.uhabits.core.models.NumericalHabitType
import org.isoron.uhabits.core.ui.screens.habits.show.views.SubtitleCardState
import org.isoron.uhabits.databinding.ShowHabitSubtitleBinding
import org.isoron.uhabits.utils.InterfaceUtils
Expand Down Expand Up @@ -65,7 +66,12 @@ class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(con
binding.questionLabel.visibility = View.VISIBLE
binding.targetIcon.visibility = View.VISIBLE
binding.targetText.visibility = View.VISIBLE
if (!state.isNumerical) {
if (state.isNumerical) {
binding.targetIcon.text = when (state.targetType) {
NumericalHabitType.AT_LEAST -> resources.getString(R.string.fa_arrow_circle_up)
else -> resources.getString(R.string.fa_arrow_circle_down)
}
} else {
binding.targetIcon.visibility = View.GONE
binding.targetText.visibility = View.GONE
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ class HistoryWidget(
theme = WidgetTheme(),
)
(widgetView.dataView as AndroidDataView).apply {
(this.view as HistoryChart).series = model.series
val historyChart = (this.view as HistoryChart)
historyChart.series = model.series
historyChart.defaultSquare = model.defaultSquare
}
}

Expand All @@ -71,6 +73,7 @@ class HistoryWidget(
dateFormatter = JavaLocalDateFormatter(Locale.getDefault()),
firstWeekday = prefs.firstWeekday,
series = listOf(),
defaultSquare = HistoryChart.Square.OFF,
)
}
).apply {
Expand Down
17 changes: 17 additions & 0 deletions uhabits-android/src/main/res/layout/activity_edit_habit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
android:hint="@string/measurable_units_example"/>
</LinearLayout>
</FrameLayout>

<LinearLayout
android:id="@+id/targetOuterBox"
android:layout_width="match_parent"
Expand Down Expand Up @@ -207,6 +208,22 @@
</FrameLayout>
</LinearLayout>

<FrameLayout
android:id="@+id/targetTypeOuterBox"
style="@style/FormOuterBox">
<LinearLayout style="@style/FormInnerBox">
<TextView
style="@style/FormLabel"
android:text="@string/target_type" />
<TextView
style="@style/FormDropdown"
android:id="@+id/targetTypePicker"
android:textColor="?attr/contrast100"
/>
</LinearLayout>
</FrameLayout>


<!-- Reminder -->
<FrameLayout style="@style/FormOuterBox">
<LinearLayout style="@style/FormInnerBox">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
android:id="@+id/targetIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/fa_arrow_circle_up"
android:textColor="?attr/contrast60"
android:textSize="16sp" />

Expand Down
2 changes: 1 addition & 1 deletion uhabits-android/src/main/res/values/fontawesome.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<resources>
<string translatable="false" name="fa_star_half_o">&#xf5c0;</string>
<string translatable="false" name="fa_arrow_circle_up">&#xf0aa;</string>
<string translatable="false" name="fa_arrow_circle_down">&#xf0ab;</string>
<string translatable="false" name="fa_check">&#xf00c;</string>
<string translatable="false" name="fa_times">&#xf00d;</string>
<string translatable="false" name="fa_skipped">&#xf068;</string>
Expand Down Expand Up @@ -181,7 +182,6 @@
<!--<string translatable="false" name="fa_hand_o_down">&#xf0a7;</string>-->
<!--<string translatable="false" name="fa_arrow_circle_left">&#xf0a8;</string>-->
<!--<string translatable="false" name="fa_arrow_circle_right">&#xf0a9;</string>-->
<!--<string translatable="false" name="fa_arrow_circle_down">&#xf0ab;</string>-->
<!--<string translatable="false" name="fa_globe">&#xf0ac;</string>-->
<!--<string translatable="false" name="fa_wrench">&#xf0ad;</string>-->
<!--<string translatable="false" name="fa_tasks">&#xf0ae;</string>-->
Expand Down
3 changes: 3 additions & 0 deletions uhabits-android/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@
<string name="change_value">Change value</string>
<string name="calendar">Calendar</string>
<string name="unit">Unit</string>
<string name="target_type">Target Type</string>
<string name="target_type_at_least">At least</string>
<string name="target_type_at_most">At most</string>
<string name="example_question_boolean">e.g. Did you exercise today?</string>
<string name="question">Question</string>
<string name="target">Target</string>
Expand Down
Loading