From f88f1cfb54991fcaf3c0d4593b921831fdb923c1 Mon Sep 17 00:00:00 2001 From: Quentin Hibon Date: Sun, 22 Aug 2021 19:23:13 +0200 Subject: [PATCH 001/132] Improve NumberPicker usage in numerical habits --- .../common/dialogs/NumberPickerFactory.kt | 16 +++++++++------- .../src/main/res/layout/number_picker_dialog.xml | 3 +-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt index c531e758b..54b5700aa 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt @@ -33,6 +33,7 @@ import org.isoron.uhabits.R import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior import org.isoron.uhabits.inject.ActivityContext import org.isoron.uhabits.utils.InterfaceUtils +import java.text.DecimalFormatSymbols import javax.inject.Inject import kotlin.math.roundToLong @@ -51,7 +52,10 @@ class NumberPickerFactory val picker = view.findViewById(R.id.picker) val picker2 = view.findViewById(R.id.picker2) - val tvUnit = view.findViewById(R.id.tvUnit) + + view.findViewById(R.id.tvUnit).text = unit + view.findViewById(R.id.tvSeparator).text = + DecimalFormatSymbols.getInstance().decimalSeparator.toString() val intValue = (value * 100).roundToLong().toInt() @@ -61,19 +65,17 @@ class NumberPickerFactory picker.wrapSelectorWheel = false picker2.minValue = 0 - picker2.maxValue = 19 - picker2.setFormatter { v -> String.format("%02d", 5 * v) } - picker2.value = intValue % 100 / 5 + picker2.maxValue = 99 + picker2.setFormatter { v -> String.format("%02d", v) } + picker2.value = intValue % 100 refreshInitialValue(picker2) - tvUnit.text = unit - val dialog = AlertDialog.Builder(context) .setView(view) .setTitle(R.string.change_value) .setPositiveButton(android.R.string.ok) { _, _ -> picker.clearFocus() - val v = picker.value + 0.05 * picker2.value + val v = picker.value + 0.01 * picker2.value callback.onNumberPicked(v) } .setOnDismissListener { diff --git a/uhabits-android/src/main/res/layout/number_picker_dialog.xml b/uhabits-android/src/main/res/layout/number_picker_dialog.xml index 585a86a25..4a9ffb4ee 100644 --- a/uhabits-android/src/main/res/layout/number_picker_dialog.xml +++ b/uhabits-android/src/main/res/layout/number_picker_dialog.xml @@ -34,14 +34,13 @@ android:id="@+id/tvSeparator" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="."/> + /> Date: Sat, 4 Sep 2021 16:10:02 +0200 Subject: [PATCH 002/132] Focus fractional part after entering a decimal separator --- .../common/dialogs/NumberPickerFactory.kt | 53 ++++++++++++++++--- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt index 54b5700aa..1ca119a77 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt @@ -19,9 +19,11 @@ package org.isoron.uhabits.activities.common.dialogs +import android.annotation.SuppressLint import android.content.Context import android.content.DialogInterface import android.text.InputFilter +import android.text.Spanned import android.view.LayoutInflater import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE import android.view.inputmethod.EditorInfo @@ -41,18 +43,24 @@ class NumberPickerFactory @Inject constructor( @ActivityContext private val context: Context ) { + fun create( value: Double, unit: String, callback: ListHabitsBehavior.NumberPickerCallback ): AlertDialog { - val inflater = LayoutInflater.from(context) val view = inflater.inflate(R.layout.number_picker_dialog, null) val picker = view.findViewById(R.id.picker) val picker2 = view.findViewById(R.id.picker2) + val watcherFilter: InputFilter = SeparatorWatcherInputFilter(picker2) + val numberPickerInputText = getNumberPickerInputText(picker) + + // watch the unfiltered input before the filters remove a possible separator from it + numberPickerInputText.filters = arrayOf(watcherFilter).plus(numberPickerInputText.filters) + view.findViewById(R.id.tvUnit).text = unit view.findViewById(R.id.tvSeparator).text = DecimalFormatSymbols.getInstance().decimalSeparator.toString() @@ -68,7 +76,6 @@ class NumberPickerFactory picker2.maxValue = 99 picker2.setFormatter { v -> String.format("%02d", v) } picker2.value = intValue % 100 - refreshInitialValue(picker2) val dialog = AlertDialog.Builder(context) .setView(view) @@ -91,20 +98,50 @@ class NumberPickerFactory InterfaceUtils.setupEditorAction( picker ) { _, actionId, _ -> - if (actionId == EditorInfo.IME_ACTION_DONE) + if (actionId == EditorInfo.IME_ACTION_DONE) { + dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick() + } + false + } + + InterfaceUtils.setupEditorAction( + picker2 + ) { _, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_DONE) { dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick() + } false } return dialog } - private fun refreshInitialValue(picker: NumberPicker) { - // Workaround for Android bug: - // https://code.google.com/p/android/issues/detail?id=35482 + @SuppressLint("DiscouragedPrivateApi") + private fun getNumberPickerInputText(picker: NumberPicker): EditText { val f = NumberPicker::class.java.getDeclaredField("mInputText") f.isAccessible = true - val inputText = f.get(picker) as EditText - inputText.filters = arrayOfNulls(0) + return f.get(picker) as EditText + } +} + +class SeparatorWatcherInputFilter(private val nextPicker: NumberPicker) : InputFilter { + override fun filter( + source: CharSequence?, + start: Int, + end: Int, + dest: Spanned?, + dstart: Int, + dend: Int + ): CharSequence { + if (source == null || source.isEmpty()) { + return "" + } + for (c in source) { + if (c == DecimalFormatSymbols.getInstance().decimalSeparator || c == '.' || c == ',') { + nextPicker.performLongClick() + break + } + } + return source } } From de9ad6d4a461de988c829f43f728a16eeb8c772a Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Mon, 6 Sep 2021 21:47:10 +0200 Subject: [PATCH 003/132] Deleted some old .png icons --- .../main/res/drawable-hdpi/ic_action_add_dark.png | Bin 155 -> 0 bytes .../res/drawable-hdpi/ic_action_archive_dark.png | Bin 338 -> 0 bytes .../main/res/drawable-hdpi/ic_action_cancel.png | Bin 266 -> 0 bytes .../main/res/drawable-mdpi/ic_action_add_dark.png | Bin 111 -> 0 bytes .../res/drawable-mdpi/ic_action_archive_dark.png | Bin 214 -> 0 bytes .../main/res/drawable-mdpi/ic_action_cancel.png | Bin 198 -> 0 bytes .../res/drawable-xhdpi/ic_action_add_dark.png | Bin 140 -> 0 bytes .../res/drawable-xhdpi/ic_action_archive_dark.png | Bin 338 -> 0 bytes .../main/res/drawable-xhdpi/ic_action_cancel.png | Bin 323 -> 0 bytes .../res/drawable-xxhdpi/ic_action_add_dark.png | Bin 181 -> 0 bytes .../drawable-xxhdpi/ic_action_archive_dark.png | Bin 593 -> 0 bytes .../main/res/drawable-xxhdpi/ic_action_cancel.png | Bin 531 -> 0 bytes 12 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_add_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_archive_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_cancel.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_add_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_archive_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_cancel.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_add_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_archive_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_cancel.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_add_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_archive_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_cancel.png diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_action_add_dark.png b/uhabits-android/src/main/res/drawable-hdpi/ic_action_add_dark.png deleted file mode 100644 index fb70e738fee9dcde9649d2049e52f03e0b7c433d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUtBu^K|kcwMxuOH-WFc5G(_+^W2 zuK&xE^AGXiKxPgM3s-QSP88GrZc*J?U6FfcMb%wu*e19ezSn1uVJj|4Md-2bJ1yA6Zv_?l<`Yw2i^j)z4*}Q$iB}C?z=S diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_action_archive_dark.png b/uhabits-android/src/main/res/drawable-hdpi/ic_action_archive_dark.png deleted file mode 100644 index 4d25429bc060d78826110b2346cca7661f57dea7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 338 zcmV-Y0j>UtP)wdAb70#le3)R_UzmN0Q6q0t&9QBuhSYHQEr?y1tr#BVmb zHcZfb`&5&u3MGA;ip&)Khi=lP$DkIi|Im@3g3v$FC$HCRTW9Haxm`W diff --git a/uhabits-android/src/main/res/drawable-mdpi/ic_action_archive_dark.png b/uhabits-android/src/main/res/drawable-mdpi/ic_action_archive_dark.png deleted file mode 100644 index 1083759eaa6ed9e4f3103bd00a8cce9faf2d13e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJxt=bLAr-fh6C_v{Cy4Nrefa;s zK2_l!(~)$KBeNZ=G`GeubeJ<1>UI8-Xxt&xVcv9R!4XE`6CW(C-Yq}ExO~NfhTtg{ z4|q&JtYFS~#Nc&>FOt3C6tkw%7Z1m)msD6jSTW6hx}}3@P2Yi3%e9vnx|Bae`kl_% z!I@OHp@ammd5!K5dX1VahO+0asTPU*P*_oB5vBm}WXRV9e@lNt#qQ&!hJcnIX yGRjU|o;A%yXrAcdyRENl-ZULq_x|DWuS~1%wLOY;eRUD&Fa}RoKbLh*2~7aLE>hqC diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_add_dark.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_add_dark.png deleted file mode 100644 index 454cd4f440eb333b42b462299c4516be649ed464..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=!JaOTAr-gYUfIaYV8Frb_-%gg z+&N~cvjP@apJe{P8VXdxV4&oAU)X_xkwpMTl*xRlX5vt2P}gW+0MSqar1-#M=1tp# U>keN1x&g%XboFyt=akR{09iyNH2?qr diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_archive_dark.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_archive_dark.png deleted file mode 100644 index 9f0623bdc66d119957f2629b182b5f5e46bcda9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 338 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV3hQ9aSW-r^>(H=*C7W1*3cu_ zKP)@lC+hrSt70mB`rIR_Wa&N4Zw@UJmZmJ*y^!nPwRhpiS_~Hp0!;vd1Mw!l#+Toi zl%G{EzSNUD>*dlv5yd(Id*(aOdh6(LH8N{*c=K!vDFrqV-m%SUtywr@n1}ov9KFW zxW5!1Sy;C0q$NHnc1Vd|dd|DzClPzYro;|)@f_JnOT6U_fRYOveMxbCPl$^zW)d8! zQq2Tso>wtJ&5xY%U?Fx4IStfQXUM#k**s}}2Y$^i)0000W#~uA} Vg-Jr&F;D;i002ovPDHLkV1iV3P23aSW-r^>&V-_u&8$H|4d? zvMjPXJ9dbcXq9Z7ZL!Px6@P)K%+Wv=*^-TVUC!*{;i7>n!>)X@zxw-uXp=(jr6ni# zTC(r^yRZ6^K4%LXBhX}I@FLAX;*6J>s`#Y7CG$7$n0ZcBdeWw?Pp7LyPr5Fn_b)&0 z&l**4rdgA!Sx?I!J9}%(ra!x$=#}g+KUsDzO~<=Wb^b!jyJt$@o{paq)5>>s>KpH8 z#TKtOJ#qOYI_vt`eG5u|ik@s-B5pNd_sP&=tM@%Au0@iwwm&}~aBU!=R| zRX(PqD}j@?HaB#XPAPe-px`9CG|-wuVsqc6RkAESf$o{t_?XXP)NLv1@zA{!f}MHcyUcGLxzT z0000000000006)PA;eRnb?a1XFWKZ)#zn?U0yzg6XBlg%ayBwP#UHnrl9ZfIt$mg8 zO!4GAss1$c2fVV|AX|<7_K{1m_^*<*I)}fU5RwdX zI(Bj_?<6Zp7INB(GluLoTTB}2oZoDf!^^8v31E}Tb9%#HB#CXE6G2j=>YOr8j$?Mq zCzS`1RJI%kN#)5INV?C+;a}$jeDRFdbfYR~E|mxGC*>liJV_QsV9dzH3;Zf-AS?MR;)^ZR6{*BlGNufA1Q`ns2O From 736bb8a75ef09d9f517a19d1118ea2ed7c68645d Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Mon, 6 Sep 2021 21:47:38 +0200 Subject: [PATCH 004/132] Added new .svg icons --- .../main/res/drawable/ic_action_add_dark.xml | 34 +++++++++++++++++++ .../main/res/drawable/ic_action_archive.xml | 34 +++++++++++++++++++ .../main/res/drawable/ic_action_cancel.xml | 29 ++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 uhabits-android/src/main/res/drawable/ic_action_add_dark.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_action_archive.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_action_cancel.xml diff --git a/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml b/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml new file mode 100644 index 000000000..beced5cdf --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_action_archive.xml b/uhabits-android/src/main/res/drawable/ic_action_archive.xml new file mode 100644 index 000000000..1e9f5f90e --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_archive.xml @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_action_cancel.xml b/uhabits-android/src/main/res/drawable/ic_action_cancel.xml new file mode 100644 index 000000000..8576a3abc --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_cancel.xml @@ -0,0 +1,29 @@ + + + + + + From f16f919e271816926a6103021be533d0c1ffbc7a Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Mon, 6 Sep 2021 21:54:10 +0200 Subject: [PATCH 005/132] Resolved naming issue --- .../{ic_action_archive.xml => ic_action_archive_dark.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename uhabits-android/src/main/res/drawable/{ic_action_archive.xml => ic_action_archive_dark.xml} (100%) diff --git a/uhabits-android/src/main/res/drawable/ic_action_archive.xml b/uhabits-android/src/main/res/drawable/ic_action_archive_dark.xml similarity index 100% rename from uhabits-android/src/main/res/drawable/ic_action_archive.xml rename to uhabits-android/src/main/res/drawable/ic_action_archive_dark.xml From 5f8187ef6d0dbbedf4414065551719e693c3d6d4 Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Mon, 6 Sep 2021 22:26:08 +0200 Subject: [PATCH 006/132] Replaced some more .png icons with vector assets --- .../main/res/drawable-hdpi/ic_action_check.png | Bin 432 -> 0 bytes .../res/drawable-hdpi/ic_action_color_dark.png | Bin 492 -> 0 bytes .../res/drawable-hdpi/ic_action_color_light.png | Bin 563 -> 0 bytes .../drawable-hdpi/ic_action_download_dark.png | Bin 249 -> 0 bytes .../main/res/drawable-mdpi/ic_action_check.png | Bin 337 -> 0 bytes .../res/drawable-mdpi/ic_action_color_dark.png | Bin 289 -> 0 bytes .../res/drawable-mdpi/ic_action_color_light.png | Bin 319 -> 0 bytes .../drawable-mdpi/ic_action_download_dark.png | Bin 198 -> 0 bytes .../main/res/drawable-xhdpi/ic_action_check.png | Bin 488 -> 0 bytes .../res/drawable-xhdpi/ic_action_color_dark.png | Bin 541 -> 0 bytes .../res/drawable-xhdpi/ic_action_color_light.png | Bin 602 -> 0 bytes .../drawable-xhdpi/ic_action_download_dark.png | Bin 279 -> 0 bytes .../main/res/drawable-xxhdpi/ic_action_check.png | Bin 761 -> 0 bytes .../res/drawable-xxhdpi/ic_action_color_dark.png | Bin 922 -> 0 bytes .../drawable-xxhdpi/ic_action_color_light.png | Bin 1034 -> 0 bytes .../drawable-xxhdpi/ic_action_download_dark.png | Bin 366 -> 0 bytes .../src/main/res/drawable/ic_action_check.xml | 5 +++++ .../main/res/drawable/ic_action_color_dark.xml | 14 ++++++++++++++ .../main/res/drawable/ic_action_color_light.xml | 14 ++++++++++++++ .../res/drawable/ic_action_download_dark.xml | 14 ++++++++++++++ 20 files changed, 47 insertions(+) delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_check.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_color_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_color_light.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_download_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_check.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_color_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_color_light.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_download_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_check.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_color_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_color_light.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_download_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_check.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_color_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_color_light.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_download_dark.png create mode 100644 uhabits-android/src/main/res/drawable/ic_action_check.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_action_color_dark.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_action_color_light.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_action_download_dark.xml diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_action_check.png b/uhabits-android/src/main/res/drawable-hdpi/ic_action_check.png deleted file mode 100644 index 329ea2fc3a3b2b46cbccb6396825fae4be0f8e02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 432 zcmV;h0Z;ykP)vdK@qPad*E?1rRQaM@*L`&y$7dlA z@o`9BtMaH-7V?&5O+faF%={XgnP)8z**0mL4Yu<5Zk>gEnxEdj%R;+pFGb;f*?3o<#Dgwfo!-U1ZM784Ur_t3=8=R47x-^{A48xdHnB;$nOp7 z#9XE!!Z4isP9DEIRpqgV_J@7!e+Yrk4|O55l&^ruA`O9>CvDRrZF8X2Nm_<@q9N+! zQHNT-4%Dp#ecF`r4MSJxN~nb}M_S8QK(vVvUDET%EaXXuY9&rs$*Uo>?|DHG1VIpl a&%6VVpVT3c6vqz$0000fllb|9k|qxMo%asUXt9!QH{yV!u;- z4o(P1?z{xw^epcKKPY(&iXnnOa||)pMSI1uIpJ`EibcE#-@u|=0!pCofZuCOD^RI$O7 zTKg0Y_ytqtH%zH@MA1OEM5>rDrPe8R_7_Q&X^GSdt6ID$_yTR}Aw81fW7E&z0&G@!bR3j0D~xW7bA$^=$c|<^ZDQB8Lwr;) z*Ed{iKpZKr3N&%%;-{3F{3mRNlh`7!x%y40V>z+go~x4SbRgG>yv6PjEd9q%i;>)E iHa!-L#bU8obEt3dzPR_xMOJVC0000$)3Di+YeA6D7Ky<2X-fhcSeQ z!I(#LmGAG(W^->DaL znj4c=->p__JFA?ZLeNG4ZCRMQ@8mn69k6CJgHlA>kGO5a(rd2J->Q(9vP;OePifIM3 zs)ahaP2GXuY-6P=NoG*32UhL3QI&)h(5jZ2UaXrJhar__sDTsK6k?XqFW>jqIV7}{ zkpm9fMJ4I1pHlktSkDpaMwYUTs?}S1*cvb;JD79dPSkJ%$U z50Iy)amQ(co#*NXZ?h+mt|PzqbN31XV$T*U@R-Y|6!lVXD%eh^vzyBYp`a#=h0St2 z$nat7W0~(iwtEF#PD;wtqN`qh1OkCTAP}q){sA!3QK&=iw{HLd002ovPDHLkV1nM^ B{>A_R diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_action_download_dark.png b/uhabits-android/src/main/res/drawable-hdpi/ic_action_download_dark.png deleted file mode 100644 index cd22795b4b6ac0f8d0ca9c20492a1701d2224199..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUt1D-C9Ar-gYPP64YC5$sci(csUt?djGXZBrDHz&ne=| zIC{E6myt!lfq^lV{Y1yr+?-bnI3(`H?Ebns50I5=-`ds w^aCe9_oHujZ)x*yPDuFx(Pgg&ebxsLQ0FZEG;s5{u diff --git a/uhabits-android/src/main/res/drawable-mdpi/ic_action_check.png b/uhabits-android/src/main/res/drawable-mdpi/ic_action_check.png deleted file mode 100644 index 700d076edc51e22c9551f0163b811532d046eef4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 337 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEVFiLp3IEGZ*N=}eqU7R4&!y+Ih zbt)$*Daj&XnzW?kQf66$%QtS^n7D45xrvDZqi$Q|z3hw(4cG9~jduR6k?WQ(S9b=o zr!8yHVYgb8@1SdLYC3gk`5g5|9rj0c33EkG`R6N zaawdlghoKpPIZ%~(=0433MM33PMGI0@u@;WTACV<$r{mDvyGVg5?EGsHb?UL6nKSn z`bbMlJ0{d@6DVL&zHmrl##4tiK37Fr-*7B=_%x%BL3KyQtjInP?<|nVTCEb2GpVt$ zQOozU*aarW6n6zy>$ke@#V*1oz74wUYGJ0kuH`s*|8(qQIQBP1VXdJ;sr3oL67Fw- f23&58dl?v1EwdcL|M2SqgNnh^)z4*}Q$iB}LhX7k diff --git a/uhabits-android/src/main/res/drawable-mdpi/ic_action_color_dark.png b/uhabits-android/src/main/res/drawable-mdpi/ic_action_color_dark.png deleted file mode 100644 index 6f814532b04a4d26872e0b2939c7e933cca0e55c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ7oIMTAr-fh6C_v{Cy4NoNpU8j4NoqbD+fpo~6-UbN{_WP}L}G5EU%+<9HtUs3Fa! zu!no`>R8uKW;4N#gQJ-Z z6IWSRjo$(VtLCK}3>T#GcEpJ+eth%GiZu6{1-oD!MpnxUfflh*|15*{p zS6$y7UJa+uWvy!1tE4OF!8Adzq{xM3?;gcN<&*b!aNK=5mBa3*b4&X4biw;4Eb}cH w*@fH%Hz>p%JmMp0z@$CN@!tfaoA1jR-xRe*7=P-x0(2OIr>mdKI;Vst0O`I-6aWAK diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_check.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_check.png deleted file mode 100644 index cf32c2a532bb95571c433d458e2b3f3b0dae46c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 488 zcmVP)t4mYR$?_13IregwDt-)8VYH5cuRqqPN1Fe{Q9GoguJ1pWTJ$O!%zdg+fIPf%*@$ zmoE!}`aa7-&_-Ta7*F~7xk?CpNy#_0LTFRI+3j-OKKv~NZRM+kpuK#B5FP~iSFPmB zLJ*3aS&}5%+MeabT6|7N7Tdg8MH00000 e0001hR`Cs@rE6*lhD6T*00007@V;!tpK5_IzeI0%A*QwQk>Xa+YC92^9p;-X{0#nDkJ7VO|3Ea*@{>Qc1! zJJny{3L(Vya!vYP(%%EmQjU=KZQgq?cTtKELI@#*5JCt^jlp2B20d7VP523W+75h# z*YFT-!1+7`y#UMb4)$Z(h9__(tHJNUXN$nYe#3LPl$F32;bj7Why8%Nt_Qyi8=)KT z!U`;EEBd#-#kgO11m|20KI)OLM2z(&80TAc@v(3GbF;;W@x=+o4Lxuv0i$X@tpxb( zbJK<3x5rFgX_UawS6Gnl^W$1wR|hhj+`JK!pvkzf`;rMLr_k==`X;t&v|Qn(;g;0e z-lpHj)#SRT5()4Un8Zvpx$dn*0%{YsF;h*h+m=W`)1d_XNF?CXp%UmyB%qg2AMYoy zj%c}%07_LT$lu45ih-iaSmZX-!o&&+3NpEvY245B5I>!yvg=)T}TwqGC z!+y_i`K`{M?L{|0EH^|J_%Ko2Xr}HSR~*};3<&D4x67`uWff31A4SXW=5coun#`FXfguE9KonZ82lGU_?<6&Uf8z1RY>D;^M^3vEw14Kj`)GD5J4M-FkIL5 zHQexZTEhbz@r`IOls4XRoK4*9v+u^ol>3cFW1ZyHfpLI=q3e)Nzt9=})RL0M2ZcNt z;$KVOC0*yqRW9uPJ3kferhh$smvr4!rfHri@ePqwKs$%L1Oun`9=vwapJ9ASq;uZuLefHsr7@Yq0bPY0FyZL`165LhY63?DOjId?__@#S0A}5= zrvS5T_9DnR2{xO}74|mBI0afXw zr&dSRo~7WWIS`4VJHs$`l|1oHb0ijVm)}{Bw$g%X+)n9$^FluZq+@Z^gQtacz`O?| z3y}h|PDl|6u2u%Tr$p@pQ83cV1X`LNCne}539W2+bAl6bVsy1KgI2jc^NP&N%qucO oGG3_(PY?t_5ClOG1VJb{|AfpAF4@wNt^fc407*qoM6N<$g8PaPNdN!< diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_download_dark.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_download_dark.png deleted file mode 100644 index 6700e66946c5e60318dde184e9b49b6809ecc1b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=_dH!3Ln>~)ongy$$U(p@cxA?P zWtNXDO{sYa$@#AXFD?BLb1!qQljD*7cXu3q^QQX4*2eEQbQFD=fqH?Ul0$LJrr;-0 z{)|>PRf}X9IUE?61R5Av6c`ve65;Lcz{yAOW z5zzmqo8#+A`&#uYn*0x5$KE^1_B2W2BsUF8z#z5-Tv$wE5vagkGP`! VqOLq!%CrF_;OXk;vd$@?2>^3;Yaajr diff --git a/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_check.png b/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_check.png deleted file mode 100644 index 99266ebb9759d1ef5f96ccf6bab3e52f61eb3ab5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 761 zcmVO&A=0FibUF=Dd&K47=s}1m$jG={MG({(72}E^a~WL!TVFvU zVVu-!nN(Lg`93HbW^(BI-m71CRWdgR00000000000000000000@RxSGeKrik1QQ+* z@uwS&#+r&v>m3)BFt3m*q#X)cA8_4BTfEP z#*VEBd9H*sP4|f0XG-VanhE)N$5FXl-i`b%#L-q_LF@c}k!Mr>|HP48ZxTEH_ zF7h+31d+U&HIC?fk8#w0;3D5w9EtqT$^-Wv@*T#J()ml~t57VCCyrK;?{~9iPBUL* zkuRUSk9-FtNwQbs=(&>l%gA?Jgi$L&{{ARU(;Zmy5J%GakIgSIu;U?)Oy?utUlA6G r9RL6T000000000000000fTHsUR-EqJ9$r<)00000NkvXXu0mjfwh?RW diff --git a/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_color_dark.png b/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_color_dark.png deleted file mode 100644 index ae50bcdf826f655f9177d19ef4760f7595b92de8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 922 zcmV;L17-Y)P)OV000000000000000 z00000dXrA4bA&9D_sAN#Og6|(vMut@pUC&*b8?!zOb(L=5XJOCA0o%e1#+GIMFuJT zLvE1o$ou4JvViDD2mX*;>8ldJz@k6MSL7J(ik*Q!NZyfQB*?)P@&ei4>w)hlOJrTf z@*qcl$`E(5mxDh+e#<%V-L8?BdM)^a-z2A`iYdsS75VqLfSMf3=kb6X=#>hm z7BR_kphiND9f=8KmSZ^yPk27^{mQS!T)~x?&v@wQ*sUZy^Kx>QF@GjOc{v>OIYmdu zZugN_rRuf`H%X;ai21AmN5^(oNY{KyKq*DFvmfpN_A`0Pmqk`R#eY0*9G`Y{>~1cp zpATe(n`V&}RmqHIsDeflma*NF@aR)8sz48lrOj`mL9Q1i?nf4sosv35(jks>PS7S5yCg<>2Qv%8% z+lX0vH8wOohb14XADb&xQ%%p|gQf)39QSInXnGDCni8<=;T`Z>Qvw<}^=e$q0b%FR z(v*PBoO(63tDvZJ_^K%Z?HqeGK~BA<6<-pd)vBfheD^H)d_i6DVG`CVuj-HbP=;!? zqOB1(=TY$a$+_d$h}k>!JslCzjMF6VWz1^biW~}QM{5fHB6(QzhWxzZ1k9=qzTz#( zHE*7XQ?x1Hmf^CZuG&#r4YjzjCa)<~d4;QLk(Dw5rVnOi3GP$!4Bm+RpM={vHRt$u zOyUj5oeAKFbKm5UfR~7NcoNb)o^I+@L^?bH{DQ_!heHv6ZW)n|Pej$>+5mSzf&>gY z?3BJhgp)7O<{aD!JPch&gp=P1RR?ndKgE0k5l)_n8xE?YNkleXbySjdf~~t@3XwHi ztlhG-hcJPNW=q7~3}4uUIlyA2bY3=f8VR>ITVB20zR!|zR_+WgU*D1+<>9ZbFYJ3w woXyspZ5jJwdt$?4vG@x=%lJ{ocQS6u??03=Td7no$SLNjVn{NX%t;Y^ zSwvhHQFq0Ditzhk433d;AjiIypYK(x)l0oz?-d_42Idp^wAT$1o2)~8(JPGj+Og`@imbgZvaeijS&*$^E zMT9R&3h&{F9T{)UT4u8#!awnw^~Ncy$YKyUG0N|@f;cP6u_oT!Z@1gWXClKvI_Vc= zA(V)A!|Pc5J2IP5;zvCelR=ilHN>M-&wP{1k6IF1qs}2BKZxVlgF8X&Sz3ehJeHkt z>7^;2e8K<6aqJ;`l(w4TPrwb5>5Tisu};Tv?BNVamZNfN)JLirG}}2McL3~@IO1X| ziY(;$A=1LB#Q=|(@Irk&Fct1F#2-DCEXXe?n~GWW?2po37+|(y$-uge(ahdK%*Xy` zuIs)=_NI01Uzui=YpHL9cK1z{1sA%S+8tnQL*wjUw%t;mV!!CK<2Yxu1>beseIAR; zN~miv6G>0Q4%>)c!Pj<{5>@;t*C2)DV>J%I9 z*C3Ajpeg_F#@VZx#3s0gff@(k(UBD10Ygo9KtG9IO_DJH9a2pW*h`{UlVlczT0oNn zhDr5mB3kHczyn@sae&sIP)Gd|q`4u7XHC@yVa2_m-Fm%#T74R-*a0nV8!_D!iN8~= zR?l)HW=iG?>h=QsnsM3!uZ(Ldw<7)8(aOZ%a2)4^+6{TX4H+f2rdoWhTapO4D%X6? zoATzV2fT;YQkU&$%!bg_L}Sgoyw^d6tE$KfSr05G8H^#Wj8C)K>{Y%I`PT`JB${*h z3_O87#~1HB?}Dua9PpfK`#a%s+|T{UXB4TlKX@Ir9@kQY^NL-k%;Sr*PK>odfeMdr zQ7pvODP;@@QJ{@_O?8rGNX7~k4tOVEIkFuSOo4Td3I~q~HQU*dsRc;T>Q71rk8)jGNymNv`?J!1{)`0 zUrhy!FYkM$@=ZoU2qA07*qoM6N<$ Eg7kCgfdBvi diff --git a/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_download_dark.png b/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_download_dark.png deleted file mode 100644 index 4c09750f4ae78a066944a88c51b1baf3cb1458a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>U^Mk~aSW-r_4byvA5)-6Lt@y1 zgKayQ%p6=F%4O)hxZ9+vUBLcHAjR@c<{p)xj6@a5XLpW&S6!}V`9CJD%|MC~Xc7<{ zIIwHo>}8ejGnbiF)iy-V3idbN9LUJxz`!Wrz`!EFfM70YZMCb@|GIzk8^Z&iPMx23 zMdE?t*?q^C-pjg{`7Ya*^*Kj-&-DFk%YL%D+z8qKr$>3q=07~jIkThd+{~YqZa)2A z^x@^H_pf6;%s5V)B1>i_XWSL`(x#Q=-j8r?>N`}Iq;pu-?~vfG5Keq z`oT}k$`N%Bu1|c*K99xx&Vk7f+P5|;%j`{g`f+pX^feDSrtvd8`FrHklxIsP%)Bm< z5PIOhlm2I|1_mY$g$4#w)(XGRVJCEKwlhKe$`G(Y|B&9KbJdc(dqE + + diff --git a/uhabits-android/src/main/res/drawable/ic_action_color_dark.xml b/uhabits-android/src/main/res/drawable/ic_action_color_dark.xml new file mode 100644 index 000000000..9fb24ac55 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_color_dark.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_action_color_light.xml b/uhabits-android/src/main/res/drawable/ic_action_color_light.xml new file mode 100644 index 000000000..d7690da08 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_color_light.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_action_download_dark.xml b/uhabits-android/src/main/res/drawable/ic_action_download_dark.xml new file mode 100644 index 000000000..82c77be4c --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_download_dark.xml @@ -0,0 +1,14 @@ + + + + + From 576ad040646e388bd716b04aae6489ad4cf0f162 Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Wed, 8 Sep 2021 17:43:04 +0200 Subject: [PATCH 007/132] Deleted edit icon --- .../res/drawable-hdpi/ic_action_edit_dark.png | Bin 304 -> 0 bytes .../res/drawable-mdpi/ic_action_edit_dark.png | Bin 183 -> 0 bytes .../res/drawable-xhdpi/ic_action_edit_dark.png | Bin 267 -> 0 bytes .../res/drawable-xxhdpi/ic_action_edit_dark.png | Bin 493 -> 0 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_edit_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_edit_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_edit_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_edit_dark.png diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_action_edit_dark.png b/uhabits-android/src/main/res/drawable-hdpi/ic_action_edit_dark.png deleted file mode 100644 index cd5af349df7cf2b32441ab07d60006d79f1bcda6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUt@18D>Ar-gYPB-K_2`VGJ9Yj;mjaTH*26i8Y2a#x;r zOvja^pRylSY(6R&Wj~G9yZ>3~o7k!Kox3&cWhQ3IZ%|n`k#Voz%CKCmq=Wkpclf6q ziH!cq9Dl>SkV~2Ee~Zk+j^1n6kA3d2S`@tF#?Eg*=F00%%V%% hXlD>RXTYOnzLw>!*q!fzAAl}l@O1TaS?83{1OSGNMxp=! diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_edit_dark.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_edit_dark.png deleted file mode 100644 index ac1f3fa8f8dd199f5071dad2a1e23c98c24bb045..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=mpok@Ln>~)oqC%0kOL2^@-Bs5 zmqj8P3bIQWq#PHuTwr?S;xDaSctZ8aJ>lOr%6pm8w#;A04Ack&KfJv(_rA@mzNvOw zarU3X-{RiRQaaRD)5l@`>6f6-n@!5|l@7h=G0>F#y-?{;@XK@c`*sBz9P)j8u-j!u zuKUsJ_k}7cuTR^&$ApepIjGgTk~n0%%{bhf8Y(6Fal&gGln`c7! zKWT;aHK`1;Kf4&BJ{@GJ`qaoU>(e=gU7z|GZheBd>4F9K^vgE;jvLr1g9JQX{an^L HB{Ts5%Jpzm diff --git a/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_edit_dark.png b/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_edit_dark.png deleted file mode 100644 index a1647d87943eb6fea6f59f080bc536dbddc40207..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 493 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>VBF&A;uunK>+KC|FK0)Y){h+# zw*wBga@W3cE?)UUpfB^BWqZ=6_`93(ZZfel`(Qhef2cd{^S-iqL4D8NS1eeZ{`Ohz+nRH3FRm|H?9DrU zcZz7f?O!e{tz&!qZeA|>=^Z92EBaJEW9Kc^)oc3R&G}PxudJxl#oBcL+b6F&%A_i8 z|6JeaH|Nj()A{LH>e22i;;kdC4!u|3zou;3%NGHMS6}S&z9yA%Tva>5S}$^ov-OtE zPoDH=sIU9Oeyj8HxsEb3f9vmlc5g56Wwe($Sc4T5-jclJx2Eh?RNuvO0Y5k1dYL)1 z>{=PaEl#dy3#1+X)-Z-fs$9BR R=X4Gv?CI*~vd$@?2>`*_)nxzx From 27e76c7243a5c79aae0548ef1e0b8e2e4b554193 Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Wed, 8 Sep 2021 17:43:25 +0200 Subject: [PATCH 008/132] New edit icon --- .../src/main/res/drawable/ic_action_edit_dark.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 uhabits-android/src/main/res/drawable/ic_action_edit_dark.xml diff --git a/uhabits-android/src/main/res/drawable/ic_action_edit_dark.xml b/uhabits-android/src/main/res/drawable/ic_action_edit_dark.xml new file mode 100644 index 000000000..f0ad2c9e3 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_edit_dark.xml @@ -0,0 +1,14 @@ + + + + + From 5cb241475d9dac2f039bb7b19bac78acaa9a49df Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Wed, 8 Sep 2021 17:47:50 +0200 Subject: [PATCH 009/132] Corrected the dark theme icon color --- .../src/main/res/drawable/ic_action_add_dark.xml | 2 +- .../main/res/drawable/ic_action_archive_dark.xml | 2 +- .../src/main/res/drawable/ic_action_check.xml | 13 +++++++++---- .../src/main/res/drawable/ic_action_color_dark.xml | 2 +- .../main/res/drawable/ic_action_download_dark.xml | 2 +- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml b/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml index beced5cdf..799ee9e75 100644 --- a/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml +++ b/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml @@ -21,7 +21,7 @@ - + + diff --git a/uhabits-android/src/main/res/drawable/ic_action_color_dark.xml b/uhabits-android/src/main/res/drawable/ic_action_color_dark.xml index 9fb24ac55..fd0860d2b 100644 --- a/uhabits-android/src/main/res/drawable/ic_action_color_dark.xml +++ b/uhabits-android/src/main/res/drawable/ic_action_color_dark.xml @@ -1,7 +1,7 @@ Date: Wed, 8 Sep 2021 17:49:42 +0200 Subject: [PATCH 010/132] Added copyright notice --- .../main/res/drawable/ic_action_add_dark.xml | 32 ++++++++----------- .../res/drawable/ic_action_archive_dark.xml | 32 ++++++++----------- .../main/res/drawable/ic_action_cancel.xml | 32 ++++++++----------- .../src/main/res/drawable/ic_action_check.xml | 16 ++++++++++ .../res/drawable/ic_action_color_dark.xml | 16 ++++++++++ .../res/drawable/ic_action_color_light.xml | 16 ++++++++++ .../res/drawable/ic_action_download_dark.xml | 16 ++++++++++ .../main/res/drawable/ic_action_edit_dark.xml | 16 ++++++++++ 8 files changed, 122 insertions(+), 54 deletions(-) diff --git a/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml b/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml index 799ee9e75..b82a35857 100644 --- a/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml +++ b/uhabits-android/src/main/res/drawable/ic_action_add_dark.xml @@ -1,22 +1,18 @@ - + - + - + + + + + + + + + + + Date: Wed, 8 Sep 2021 18:09:04 +0200 Subject: [PATCH 011/132] Removed .png icons --- .../res/drawable-anydpi/ic_arrow_down_dark.xml | 11 ----------- .../res/drawable-anydpi/ic_arrow_down_light.xml | 11 ----------- .../res/drawable-hdpi/ic_action_edit_light.png | Bin 354 -> 0 bytes .../res/drawable-hdpi/ic_action_filter_dark.png | Bin 111 -> 0 bytes .../main/res/drawable-hdpi/ic_action_snooze.png | Bin 1036 -> 0 bytes .../drawable-hdpi/ic_action_unarchive_dark.png | Bin 337 -> 0 bytes .../res/drawable-hdpi/ic_arrow_down_dark.png | Bin 240 -> 0 bytes .../res/drawable-hdpi/ic_arrow_down_light.png | Bin 237 -> 0 bytes .../res/drawable-mdpi/ic_action_edit_light.png | Bin 196 -> 0 bytes .../res/drawable-mdpi/ic_action_filter_dark.png | Bin 90 -> 0 bytes .../main/res/drawable-mdpi/ic_action_snooze.png | Bin 694 -> 0 bytes .../drawable-mdpi/ic_action_unarchive_dark.png | Bin 207 -> 0 bytes .../res/drawable-mdpi/ic_arrow_down_dark.png | Bin 180 -> 0 bytes .../res/drawable-mdpi/ic_arrow_down_light.png | Bin 182 -> 0 bytes .../res/drawable-xhdpi/ic_action_edit_light.png | Bin 296 -> 0 bytes .../res/drawable-xhdpi/ic_action_filter_dark.png | Bin 103 -> 0 bytes .../main/res/drawable-xhdpi/ic_action_snooze.png | Bin 1381 -> 0 bytes .../drawable-xhdpi/ic_action_unarchive_dark.png | Bin 337 -> 0 bytes .../res/drawable-xhdpi/ic_arrow_down_dark.png | Bin 317 -> 0 bytes .../res/drawable-xhdpi/ic_arrow_down_light.png | Bin 294 -> 0 bytes .../res/drawable-xxhdpi/ic_action_edit_light.png | Bin 547 -> 0 bytes .../drawable-xxhdpi/ic_action_filter_dark.png | Bin 107 -> 0 bytes .../res/drawable-xxhdpi/ic_action_snooze.png | Bin 2119 -> 0 bytes .../drawable-xxhdpi/ic_action_unarchive_dark.png | Bin 575 -> 0 bytes .../res/drawable-xxhdpi/ic_arrow_down_dark.png | Bin 574 -> 0 bytes .../res/drawable-xxhdpi/ic_arrow_down_light.png | Bin 526 -> 0 bytes .../drawable-xxxhdpi/ic_action_filter_dark.png | Bin 106 -> 0 bytes 27 files changed, 22 deletions(-) delete mode 100644 uhabits-android/src/main/res/drawable-anydpi/ic_arrow_down_dark.xml delete mode 100644 uhabits-android/src/main/res/drawable-anydpi/ic_arrow_down_light.xml delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_edit_light.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_filter_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_snooze.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_action_unarchive_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_arrow_down_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_arrow_down_light.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_edit_light.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_filter_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_snooze.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_action_unarchive_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_arrow_down_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_arrow_down_light.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_edit_light.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_filter_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_snooze.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_action_unarchive_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_down_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_down_light.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_edit_light.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_filter_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_snooze.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_action_unarchive_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_arrow_down_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_arrow_down_light.png delete mode 100644 uhabits-android/src/main/res/drawable-xxxhdpi/ic_action_filter_dark.png diff --git a/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_down_dark.xml b/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_down_dark.xml deleted file mode 100644 index 665d5d593..000000000 --- a/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_down_dark.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_down_light.xml b/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_down_light.xml deleted file mode 100644 index 856e1d1e0..000000000 --- a/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_down_light.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_action_edit_light.png b/uhabits-android/src/main/res/drawable-hdpi/ic_action_edit_light.png deleted file mode 100644 index 70cb75e1fbf89de91037d303e164cae0a0bad5cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 354 zcmV-o0iFJdP)l({mDMQQ;|&%L7ZFHLVku&?jM*Py@Xd z`L|k0wldT1B8K;nWu|mh)3t!ix)W=3^qiZ*WF;tEkY@>mu^^=m1Sw6L_vo3*vuYARAOrVw|$?S z1BXF(XT}-rhdFSW-I;sO`Ofp6d+X{ViYTIpB8tdA#frt^0l$me+uQe7DwQppf;^ke zCNi1Kn~si-DZf0hejH<_v$Hd`VZf8g}Ef-=EXzbe5rH=aovOZ2)u#-y}8 z`M}r|fino1T~#)^v{<&QnjD55E0@Tb#qaInguP-_oF+4Vo~*W( z$u4tyT!d<)Rv^qjFB@h({8)jEwvsL=n)x{fh#~D0;t!e!lPo%Pj1VgCO$(c3=cdNKz(lJYaJIr6K>iJ z%c8&;*V}5!ohM*jbvJUGn z2=DID4)t;vd8egrtya1k@fZoP_qCH1o-Z}O{P6TdjDL-1mezG1`(p6KkaoE2J~!lU zh!x2s91k`1UU|?1So?Uj$4A^Hk9JO+5E3v|Bj88=ag1D$a{6 z1AG?aCNBp5>pOQ|(z06d;){bJ#mlX_h$4z8qKG02nEnButF$FzY&yjN00008T$&8Ku4}Y1TdF9il zi6RJsAP9m2Q(e~?c}6y#?6NYg;ZyRFeDiFVnMw~oCGU7c<0*4O-f-sL?I8)U=8aC| zrN;`b$Y;*3q=wJQSApuZ?e@qe02T_vKRlNJFp2;M008(AfCD>7085V9HZ%Y?aMDj}d!3`Wr`kkPtE)`*tr99^J0xhhzYen^%Av6>&cASjL>hb~K1RX4A-w(-3CZ1_FB z0(lk4t3X}_;zw3oJC+LK2Z-l6LY)Ei`*vIp)ep-`bQwlcP(Oe72y{6{8lf!EG>l}SG|+U6q@fU$hLIH1%lJJXBPl3t2+vK;K@sjx q$v_eAOASzj-~Uoa5w2HNb;my7p0Wdy`^b0z0000u+&pye3ULupVL25D5C_uzXy26a$B6NW(+Djb7) nsM9d0MV*d8g1QWbG3N9IYPZg!9Y$Dy00000NkvXXu0mjfO~qrO diff --git a/uhabits-android/src/main/res/drawable-mdpi/ic_action_edit_light.png b/uhabits-android/src/main/res/drawable-mdpi/ic_action_edit_light.png deleted file mode 100644 index 7807f449f9b3729841880bd7f7abff5eb8e6a15e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJZci7-kcwMxr&x0}7znsLuGA6w zl=+3NY3YNtTRawSFIA4#5xULUQfn|_!Xsb1BNDEGRfnUj+XVbhxm{+|>o-h0b@t{$ zRgWDUKc($BPn>&hZwwPr<+=e^PKjV&AgNHTr0e? vzUZINt&=+)tbh75&e;>hpdBv4dX)Js`-B(8ywQ_^&SLO%^>bP0l+XkK&nZmq diff --git a/uhabits-android/src/main/res/drawable-mdpi/ic_action_filter_dark.png b/uhabits-android/src/main/res/drawable-mdpi/ic_action_filter_dark.png deleted file mode 100644 index 59a2ec755e90e6be335d3d6c79ede6d85a7ed488..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1MNb#U5R22v2@&Hr5(PMPpn nt`GJgTe~DWM4fp6nTa diff --git a/uhabits-android/src/main/res/drawable-mdpi/ic_action_snooze.png b/uhabits-android/src/main/res/drawable-mdpi/ic_action_snooze.png deleted file mode 100644 index 63b4274f8bcfd4a0ef17b5e0dea0a50790f1dc7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 694 zcmV;n0!jUeP)w=@y0j@G6l`4{ME$pZ zU-H}Lk@yRG zS4%h+iwz}{$#a|;ck8e*Y8YLG!doc(mC0m=%lE?Ja6d`e`M>b}3i1a!^Bw0q8Zo{H zB{!hOd_Mn>sRi#d=#YFGk)a##e&T%w4s@1Er3d()75|95y3>w>D^!q5r9O~>XOv|S zuRvodE%2uBy(MSQ@Sf%w$XjxBi%z+=jsv5LY*BUnsAzt`-k>dq@0X!a=y6&72jtu> zGay~l%G4)U#;Fj8Pg!%OJ)KTR6xlLL&{pAS39=*QJVpvfzA1o=vbhJkbXAIIH2Q`p z2E|nKQ$}8CTp9Qii9|w`d|_aldV;}VH@gS#`|J>(%RZ(tKhvhvzjl%X{{l*rPJ5PR zy}LK%dZT zRl&+r0d3CUKv+%=*6jdl``qLJ5skeo0ui0kYjU6(hHAE>YCKa-28Q1f>8vwA*W-}I zF*@M1=e7)opq(0-8ekSA+fi|z_sB^jT`77{}HlFJK)1MI87mu<=)2}>b`1ztd=&cXhsWEXtR zT)KA8G@3U!fOt`nbX%^e=9i}F*wA9{bMU~(Z~JG&CblAm)0c*8UXL^E4ib>x)%tC3 ct$Vxf0Oz&ZMTg_U5dZ)H07*qoM6N<$f*c(`=Kufz diff --git a/uhabits-android/src/main/res/drawable-mdpi/ic_action_unarchive_dark.png b/uhabits-android/src/main/res/drawable-mdpi/ic_action_unarchive_dark.png deleted file mode 100644 index 95e085c1c0323ccf0efca5a0f8558b1e0d3905e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJX`U{QAr-fh6C_v{Cy4Nrefa;s zURB{9&yjSGBMP>srbOv69FcCcn9j3zYQSEmDHaRn^UPoTxXw$apo@#o!nKq6TmUnF zHhWIfBgR686G@sH_gwPX8+6@++OG>k>7Tg7BhVoXp00i_>zopr0A<`o(*OVf diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_edit_light.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_edit_light.png deleted file mode 100644 index 472959624cbfd4655a3e2b4036e918c6e2d27272..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=?>$`{Ln>~)oo2|_E>6hTHb=JBkUb|<^dNxN`k=JeJ`Fl&gFBN<< zul>wCfA_hbvR+CzjKfzphD$uW_x*2J-mP@E3scVbEYP(VKe+7Q#nwMDEasmsbIf;N zB3&6?Emvv!^UJ3b%JDWI-JeW!m#YL3KTZGN|2@@z$F%>d4O40|87zNJVwm)4Cu7Rf nVkVE%`m7VCvx6PmVE>%=-79O;DeoeefCM~U{an^LB{Ts5UOs(R diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_filter_dark.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_filter_dark.png deleted file mode 100644 index 9416c70ec0a0a230648075ebc449e2000f239d72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}tJx>?Mkcif|mkfCs7&s0X{F%+h z&%)%Mop4@>VctnaroRklqT+)Y_}1iWG8C+2XgDPM|LJEjE1*sWPgg&ebxsLQ0G~@6 Ar~m)} diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_snooze.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_snooze.png deleted file mode 100644 index 951ebdab8ef865ce6147fe32d6fbb8d3955670a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1381 zcmV-r1)BPaP)gwtPAaELEgM^x~ z;8CzM5ngE4J&c-X4ReR#;o%)1W?2~DG`sZ+1><84;QuBLKeXY+Oqr)Tf{;IyFcAAE zo*k^mJfBx8l^5{dKFlBH!2A1gzq4AcZmZ`5@c#(LHEXS#@D2MjVIGV3W2{>QeU;DW zpNx684@|xbW|u89*|g^0#aO}hhfw=nHlBfjfro)(&YE)vzs1ydp3)a}ypQ`S?o^EP zy1@VIG2Lj;v=C7WF#@fqASpNq>_A#Ozg^YdEdD=_Pc6XnGjU8&7#P3Nqhp+fkj~P^ zF)q`=)e!{$@6$EP$DKwigbjdyR4g_e{Vn|VCXBp_oK?lbS zFj|j!g_@x{Xl&BgKGnYrApCqgcc4>rQhNxNqd_UlM zwNNNL;oT2RPEI}z#1DzY&kG@E5}MVTnLF_8>S+*+;npa}1hV;R0j z9dqgp5Qd?MfVc{<5ilKYmv}?Nx+@Lss(+s_aLqBRjOO2HBQ^g%!oy@N%`T9tUt$|( z(^O1gqYVLk?rMhZ7Da>F1aX)@pjjJzf+HQr1y8kW1ORn?-Kr{UT_ph8n-IU~kV8C* zdA~QR@LKdmpGg`%o|*ud^a$ZsT(e3r@Ux`}ZzUAKlFZ$gY8Z?X8D@ixx;!mpbW2um zvC=9H+Lvs#2=f^Vmxb_AS3E3p*%#FI8QWq>{0Qb;O+6Dt`Z+BE__9rO?EBX=G_tqY zWCLna7SE+F0QvzbhVHUB^3Zp9M{us!I}l}G0Pp-Q0?TJo5wf){M11P0`7##O`#fce z>lxzN`?Bt8&N`3CBpmu|Mw%YuO@sHSWqLe;zMV<009C72oNAZfH?REttivcrjWjk00000NkvXXu0mjf+&`hh diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_unarchive_dark.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_unarchive_dark.png deleted file mode 100644 index bc6c288ada13d2509d3f34f77620f49c61014ec2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 337 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEV3hE5aSW-r^>*e#-@^_9uFfqh z4lfjN(Nt`|&$v?IiP-j*M+IGXCeNH|HYrt6q-pNW*!}8%U;mk#F0b=Gi4kZF5EKZ< zUbl_hHf{0JxfTl_+mRJGDX^{ux9s<-EZAIkb!6?_%ej+!r`(PlYzPy$Q-= zGI5;W^@H!jtZtwg4gVQA92l6~L<_t;9E`v3KG@veaO%^{1D_u9Oua5zIia9nms)<( f_Vb@0UYcNd|3n^BL`!VRPLP17tDnm{r-UW|jrNJ< diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_down_dark.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_down_dark.png deleted file mode 100644 index 7bd939f54d2e1c5bb923316c1efec417d5e404d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 317 zcmV-D0mA-?P)7bP$uU3g3ff7Fdk>5Ny?_v_ZR+GeD z0feu0Tp}I0F--YrRf2CgpOSBtoBYSP+l6;XaG&!^zEN)RzH#>uzEgs`oM-aea)Wn` zyQkngB)B&-|84k+H%f2^vzYJ|Z;;@8(vJ;a@eK*iN^gwt65mn@;>!{(J>$I) zd|qO!jCVrWDPep+1dS5LcSEruVcZ{*1qtKc&_KdC{|kzQu`h%WLY&11Z!cjC1p3d7 P00000NkvXXu0mjfZ}Nsy diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_down_light.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_down_light.png deleted file mode 100644 index e9253415fd4b115059d304980205aa6d12acca9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmV+>0oneEP)|nZe~}-2Ek)j?5-kGuw*6uI_9y2}xbm1H ziCO_)9&?C9e&o(&N+kFW=bp9lhY1)h61>kjIK4cmmEc{@jmye|8VTOx{POakRDySW z7FHgVNO11%#+C=aBsg2{^idw{N$`1h<-wLj$ys=LupzNK-IND465W*tB@*412YV9T smj`PS!;}YJVz~0aB!(?7gb-o~zK|qYN5qOj!2kdN07*qoM6N<$f_m|PmH+?% diff --git a/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_edit_light.png b/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_edit_light.png deleted file mode 100644 index f8e12dda3b45ce35020cb311f7fee1680b780884..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 547 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>V0`82;uunK>+Oxbe$tK-t%*WQ z7kNx+;a;%FYxB0J@+VvK8B{JUeW1@Ods6jC?UEUXSa(M6bBt~fX12cf)#KV{uf@8@ zu38$ePfyF|2O0_k3w(e5{nvglq2Su+_J!BU{wrGA&@PnpuF7oo-pL{E50C%&Isd`@o)D+K!Y@`Nzg;6;vc>i7 z8r{aeD5WMDch2p+hn6p%R(_z4rE*T>q2|6<%35ZcicK~rZ?bOf^ILl3z|Y4Ye-zlw z-yb{ITlLACmXgHDIn9^-dg2A|Ous5rR4TInzwTYO<#T`BTPoCc_+g;8)i1S&d%UkH zP2JGgH!U=DZok{&??LDGq~tDIJY#nUlf8Fkvv=6KzNB}@PUSz$Rd;qjz2#Hu{d>3l zlw~jande)tzZBRraq52_%{gtiGS?_?Su=N;)uCBa=dYeSy=2NfU6nnuZ~qjZEV^}b zQ(4R=uI%Hg-DMf=WpUTeslJ_Z`5gZ(O@~WPdp~8SPu~(8D*E;U-`j?=4E8O~)+lK6 z?hAg28R^Hl7R)VTz2J9}DPws8!Pe>*wzS7yfgAL_J;oT-G@yGywoGr2dHj diff --git a/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_filter_dark.png b/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_filter_dark.png deleted file mode 100644 index 1263ae82e71dfbfd5aba9a11483442542e74ce15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^9w5vJBp7O^^}Pa8OeH~n!3+##lh0ZJc`BYRjv*C{ z$r6(m{IloyqulHooWQ^35x=C46!WwH>?aa9)4kR*{W|XsGR4!?&t;ucLK6Tv CS{)|< diff --git a/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_snooze.png b/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_snooze.png deleted file mode 100644 index c1b201ceae6a392c854941438860defa793e5280..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2119 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 diff --git a/uhabits-android/src/main/res/drawable-xxhdpi/ic_arrow_down_light.png b/uhabits-android/src/main/res/drawable-xxhdpi/ic_arrow_down_light.png deleted file mode 100644 index 6bf117145e43bed1cbf1bb59f4ad9dafb2ecf110..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 526 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2V7%(-;uum9_xAc(ufq-!tq<3g zKE6NKL|0_j3#}a&S|8|YeihmiozAqp<@!tiNtvE%&s+Hoe@-&#&)XGY@qAA4Im_pB zW~YXR{$18qy}8$b&8fvuK&huuAd#nqBU!;kf?4s91c%@;hYkW#np_z>WA1&7xXv+| zd&Rof)pENt8JF|vZ{oL)uUO~Za*}b&?YDA=p8twle_h_DeDa~@`%(Iv`S;rwKflCb zEaG9Y>-^b?hn($y8aYo8`u>X7MaK6}bJ2IL(9AiG9-Y6xFj=)Nj$9kIevex9L&f(s z2Fr|t9?6|8cpvh-;L(xu=U%T1%3E^eD^MU}@u5J=i9*-S4(|uo_Z=wPUHhc;ZAEWe^;@;Z#cfK3@rP|qHDyd$I(JLGJ8Cxj?Byo~A@M5jGIxj< z9{MQ%Zfp7$i&gwWo@zH~xQ^DU2KmO(9secFVdQ&MBb@0QRWp%m4rY diff --git a/uhabits-android/src/main/res/drawable-xxxhdpi/ic_action_filter_dark.png b/uhabits-android/src/main/res/drawable-xxxhdpi/ic_action_filter_dark.png deleted file mode 100644 index cb2207f11fb53879554df5541522fa4ee564e975..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^2_Vb}Bp6OT_L>T$m`Z~Df*BafCZDwc@{~PY978G? zlNE$}nEw3__|Q0Q&OttfcS{V@Ia-)>EuS<8GB8}PYOf6O+;0yu#M9N!Wt~$(6988y B9v1)r From 3e20fc4d1d886a6e1caa432c1276b39b623130b5 Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Wed, 8 Sep 2021 18:09:26 +0200 Subject: [PATCH 012/132] Added new .svg icons --- .../res/drawable/ic_action_edit_light.xml | 29 +++++++++++++++++++ .../res/drawable/ic_action_filter_dark.xml | 25 ++++++++++++++++ .../main/res/drawable/ic_action_snooze.xml | 29 +++++++++++++++++++ .../res/drawable/ic_action_unarchive_dark.xml | 29 +++++++++++++++++++ .../main/res/drawable/ic_arrow_down_dark.xml | 25 ++++++++++++++++ .../main/res/drawable/ic_arrow_down_light.xml | 25 ++++++++++++++++ 6 files changed, 162 insertions(+) create mode 100644 uhabits-android/src/main/res/drawable/ic_action_edit_light.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_action_filter_dark.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_action_snooze.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_action_unarchive_dark.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_arrow_down_dark.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_arrow_down_light.xml diff --git a/uhabits-android/src/main/res/drawable/ic_action_edit_light.xml b/uhabits-android/src/main/res/drawable/ic_action_edit_light.xml new file mode 100644 index 000000000..77e5f58ce --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_edit_light.xml @@ -0,0 +1,29 @@ + + + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_action_filter_dark.xml b/uhabits-android/src/main/res/drawable/ic_action_filter_dark.xml new file mode 100644 index 000000000..f31c712ac --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_filter_dark.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_action_snooze.xml b/uhabits-android/src/main/res/drawable/ic_action_snooze.xml new file mode 100644 index 000000000..99a56248b --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_snooze.xml @@ -0,0 +1,29 @@ + + + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_action_unarchive_dark.xml b/uhabits-android/src/main/res/drawable/ic_action_unarchive_dark.xml new file mode 100644 index 000000000..ba1430de5 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_action_unarchive_dark.xml @@ -0,0 +1,29 @@ + + + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_arrow_down_dark.xml b/uhabits-android/src/main/res/drawable/ic_arrow_down_dark.xml new file mode 100644 index 000000000..a0b5f9083 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_arrow_down_dark.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_arrow_down_light.xml b/uhabits-android/src/main/res/drawable/ic_arrow_down_light.xml new file mode 100644 index 000000000..d653deaca --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_arrow_down_light.xml @@ -0,0 +1,25 @@ + + + + + From 42f6125d5ea903830d15ec8c8e24077fa4864e55 Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Wed, 8 Sep 2021 19:39:34 +0200 Subject: [PATCH 013/132] Removed last .png icons --- .../res/drawable-anydpi/ic_arrow_up_dark.xml | 11 ----------- .../res/drawable-anydpi/ic_arrow_up_light.xml | 11 ----------- .../main/res/drawable-hdpi/ic_arrow_up_dark.png | Bin 234 -> 0 bytes .../main/res/drawable-hdpi/ic_arrow_up_light.png | Bin 246 -> 0 bytes .../ic_colorpicker_swatch_selected.png | Bin 2414 -> 0 bytes .../main/res/drawable-hdpi/ic_notification.png | Bin 618 -> 0 bytes .../main/res/drawable-mdpi/ic_arrow_up_dark.png | Bin 177 -> 0 bytes .../main/res/drawable-mdpi/ic_arrow_up_light.png | Bin 182 -> 0 bytes .../ic_colorpicker_swatch_selected.png | Bin 1662 -> 0 bytes .../main/res/drawable-mdpi/ic_notification.png | Bin 435 -> 0 bytes .../main/res/drawable-xhdpi/ic_arrow_up_dark.png | Bin 299 -> 0 bytes .../res/drawable-xhdpi/ic_arrow_up_light.png | Bin 279 -> 0 bytes .../ic_colorpicker_swatch_selected.png | Bin 3241 -> 0 bytes .../main/res/drawable-xhdpi/ic_notification.png | Bin 816 -> 0 bytes .../res/drawable-xxhdpi/ic_arrow_up_dark.png | Bin 551 -> 0 bytes .../res/drawable-xxhdpi/ic_arrow_up_light.png | Bin 475 -> 0 bytes .../main/res/drawable-xxhdpi/ic_notification.png | Bin 1285 -> 0 bytes 17 files changed, 22 deletions(-) delete mode 100644 uhabits-android/src/main/res/drawable-anydpi/ic_arrow_up_dark.xml delete mode 100644 uhabits-android/src/main/res/drawable-anydpi/ic_arrow_up_light.xml delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_arrow_up_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_arrow_up_light.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_colorpicker_swatch_selected.png delete mode 100644 uhabits-android/src/main/res/drawable-hdpi/ic_notification.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_arrow_up_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_arrow_up_light.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_colorpicker_swatch_selected.png delete mode 100644 uhabits-android/src/main/res/drawable-mdpi/ic_notification.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_up_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_up_light.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_colorpicker_swatch_selected.png delete mode 100644 uhabits-android/src/main/res/drawable-xhdpi/ic_notification.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_arrow_up_dark.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_arrow_up_light.png delete mode 100644 uhabits-android/src/main/res/drawable-xxhdpi/ic_notification.png diff --git a/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_up_dark.xml b/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_up_dark.xml deleted file mode 100644 index 088d70f19..000000000 --- a/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_up_dark.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_up_light.xml b/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_up_light.xml deleted file mode 100644 index 5703c0c96..000000000 --- a/uhabits-android/src/main/res/drawable-anydpi/ic_arrow_up_light.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_arrow_up_dark.png b/uhabits-android/src/main/res/drawable-hdpi/ic_arrow_up_dark.png deleted file mode 100644 index ecaca87de6c80645720f08ceecc87c0020bb9d75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234 zcmViv{} zd1B_G6lN}}ftiDHFz2ES%%kx=9%W!snXUSlZ`qAUSs3g;K-k@eqFNZ-EYPLQeF*9Z zgZmDIeSegP!5b5VTR&6;BOQTo?}JjHr0?%MkYu1%{U#JpN$=|-AgMxqhlv&iofbh} k1bGqUMUdCeff!>>FW$_wrY40zBLDyZ07*qoM6N<$f($2Lvj6}9 diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_arrow_up_light.png b/uhabits-android/src/main/res/drawable-hdpi/ic_arrow_up_light.png deleted file mode 100644 index a7f677ab3c342c9f032f5b7613dd7861eb5dda2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmVZK zz{D8u7}HTTW;#m4OhZ|i;V6j-A>6d*At;H#2lH5~_Z4$;kG!W#8m7#@fH0T;)TZt2 z))A(xX`oXc*P}BZWns$t4urmf@-StO3PN2`Ef{2hP&ZT!vM%sINTP7J+|v{eS{T#< wLQmA&nATcB!y?FwATNTv2=e+l5M#{g0i-a_=zIy7BLDyZ07*qoM6N<$g4VWa7XSbN diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_colorpicker_swatch_selected.png b/uhabits-android/src/main/res/drawable-hdpi/ic_colorpicker_swatch_selected.png deleted file mode 100644 index 3cbfe1a840d085dc922421217f0fc590d4681b5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2414 zcmZ`*Yg7{07Cs;#VG>S=MoN0~5sn&aK2pb^RG`K}e57T*0=0ahkq@vUA2n*BX@i>M zql_`l@sXM~YHCG}i&1NQXOU)VKFGRCrRI2Pe%!V0kGs#>=R0Sg{jG1Wb$;xf&Nxg} zN8wQb0ChUenW;qDH%B6ryO+G4ssval#f<_$U6$I{Ah_}lIm4vx2i3hgv&xI!NgC4) z0G<&5f>Z!jl_9}90M3#Cmwrdk z8DaZMZTuE@^j-u}FXs-{-K7+0!LDJ`QK_G{VtM@;YU4R}t%jpLxQacyAcZ3d3w5D~ zclT~Cwtg#_+{QmOv-@h5UGbUXrNWuLGkbTd*u}p6n14}><{-e zOq0wO3#$;Gs)4#bRKKelU3Lrn4%er)-b0awdIa)zp9?3cG&5t(KQkS7#mV-Wki$Fu z+Hf2}@E?OIQ{KeyQH>~ul}}085K?Han{#x{!Q<3LKQUa8=85$BGj^{qrEAi6f%2{_ z1Swg*6(T@p97t>&$25&yO>!z(T1h%IS~KRom28jESRi^y_zA_vm6es@Lsgx!Hoooc z{@E*f$jnB{V8l}1h@U2T75O~Xq$gdOm8=KIyuiS5TWS_zeeCLX+qm1zinnuvcjraT z){NjYi3;z)`Yq&Iynt)h&9bz%vH7GJ`t5l8ySceHLp1>#QjVQt;`*vW)v2V0BAQ|z z-{lh}QaP@9$D|bF(;GDZhh)i7!{wSmZg*N;UER*-VarmbNTp++N7I;GRvYxVx2Mo{ zUrXZB^zGsK-#oCA1P6HLcPPEcU(eU;KTVM|o#_9mi36kPr8@@)ak_Z-Y=@T{bC{<`C-%?Om1cPM)8o+d{J zMj1DtAJZlfWc&}~ogAA&x0Ut3<5ywDGwH7vjnkdqD5j)&7q(|g&TkO9e^cM`TVs$&>*~W#y{=eULYYRSEP7J`F z9T7ndGJ>@PXUmV2$aZ9Xs|$W0r2_KTz~Ad@Cqc5Zl5!&>qbqtBK)LcOwZMx5HyIB& zT=I?r2+JlH*WsG>S%|#O+?DZ&n2{r^5AB;~>>5CeV&+qzs^pI=Nj=wSZ)cQVW_J93 zk}mr4sS_t&jX9};lAe&zOP4OKA`pm&ThjJF%-bDM-Oy)|p;CCd)n-yXWB_I3euArb zCXYLF&oq?B<2?xaY`22mJ*488Op1q9X zxww{!pav#{^T6+Yz)Ww^{9TN&u1GC#EtI`CZ4@)v@hE~mwUlUrOrD?ZFE2=NJb$;T zDLxZX!GKm^d+R4ACLW&b5}q4=`O=T5qf3L5Wt)Ain4LJOs4YOm{zmK0HI9Ds@rzv7 zAx;6swZZqVS~eb>9yE!GimGPXtvZ^j=hB14EqLiA-%SRe%cxm@ z<>ux#-H#l*?}e2#+8Z3Kh*k0)*ZC|IibNtKwQ(R(wavnt=646`Dl%s5>~E*1r!Nl- z49JU%i;pNPJVZ2m*?wVzwg?ik4rJh)qct=7& zenG(sKR!O5#pA688+^ACuCx!5Of8gHWM-wIei&`!f&ZSlh|V7w{gB}3caxDl_Tt5t zqc#4-j9bl?1)Cc&Xw~~MU#fEUSB?1gq+AVSS1@)l@}!bOIWW*F;ehGE4aofDX*6x0 z|50x>O_z(6mD%iVxW^Nny=q>qtwDpbB!nbalP!-O8Mk&E=}gn|#)eJJ3OD-%ymgI4 zTfE~~g5pVP!q>E9UH^Xz5CFyt8gG9_H|x5XWw$5L#-6vYccL39Xdb;W1BwSYCeXvQ|*3TAy2?VyB<9=Kkr_|83cbb*=K6RO6NB z(T2*g!jS9Y!(|0=+4d)6*-8MGBnvAulBJo2rKcsyo@8ZjX>CTbvnP?9@RvsZhY%Uf zIu(-m{|QH^PAny1+cyP|=n!svP%IlzSkb|3J$htND4WR+VkO3Ov%k$ffbMeGxq5$K G@_zuE;6>m7 diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_notification.png b/uhabits-android/src/main/res/drawable-hdpi/ic_notification.png deleted file mode 100644 index 7732cf993a260b4d30e9004153b78d935e7a02fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 618 zcmV-w0+s!VP)dWkp$tjU_RJ z6*goh&+~nC)#;jd-o5Y5(_1+8X_}dH?)%QY=bn4+R8;(12xi;10g@mMOt1xV;?)$N zJKq~&3uyxxkhj$=FZ|oeEhGW5pkVv6f{0I)L(G82jHt}mKoBu0P_)Zy&Uh)mVk|ox zv$RBsWh&a?T2X2FL;}k>^98oSMhSKU=2XH2#6Su#gd1Bn}Do{^RXnT+!^@oOiEzXH0!8xw1i*jn(a zv}r`^;AUNlxlqcUK{bg#aPixc1?8AQzN3H23@oO$VIn^0*s&pmsJMtl@kHjyj z&JdSFjfzX_X00TCQ#FUUT{cMkCN#xdO3yh}-DO-IS|olk&4z7)#5RLZ)jGsg>PM;S z4uKB^F*&J#&MH@Gg|loy@*M^b%tlyu>JIU50WZpDnZjxRtD(aCdN2w0#j$V#)RfzK3$_h~&L2k~h~#-t8m#??+_+ANmXX2G60ouhTT@IRF3v07*qoM6N<$ Eg5bsj&VVTl>qE%Ec^YmfWu*w-N`;Ok$ zer|WLb;i}rh3nUU;8-oQh3WC!Yn9^bWi~MQcxN@7Zd7I1+v9oe=L5+PEC){eToi8E h!0LQWJg4pdMK>dJ@SVjy&a6~)+sYn1A zSpaOwQj9qO5@lUJUj)GJ4giSQ@^%kfXko{mALtT}t z#Ia`~L)yT~I?cj?kf7X?`zD-8fSbR~H@yMGn>n9a@NjAm0ANJI2#1)ANIQD_-X2^L;uHnACDs#2lO&}Uto>8 zu?nYDPiZlXdcUsF4KtyqKocUh2R-{iE&*%<^nB{7K?AGZ!W^1`ZWX#Q6bzK7?rhAf z1am*FzS$U;T#zmO_@ygk2o|7o*}^1|kfUzHz=IL*gUm5htsG8Sy@Hv0nU|d$77X4- z#F_Z*Gk`AZ2WG_`H#`f23|}FH4H(VIVilcIzkQ2p9TCG8DFHmHsix6L`0+fsp928O_3k&Og7s|@Ywzgj7!3&6o z_wLz)m)oGzXf$%vL7&B1Whi%ScUf9GFi*27P-7XZ_n;zbNbwT2*^K4E?-7WuUu0Tj zsk>b{-3eA?V`EeQa9Av`#(UO|98M14J*UcF&P1vo>eXfne;4P#5B=SVq}?_#kyMll7p>@zH09ehMxBNsc{{=_|rzRobXE~h1r^4r0& z(7UD{)=R3reSCOtXDtWAnv$(b|49YF?~Rnm#8f&kBN%%S7f5` zE6MA zA4b0kJ?~H;ef(5A+U003-W_N?&i5^xHqgj3U0)Cg95SREsmPnhs;PdeA1fv88Ihr( zGw>dif6+?s4ZRavi89KjmMv9O=zg&!G^ORrn^yKsz%d}V#AW{2xdMx5t(+D%n@!bv zJ>ibDs;iAuWt@Q-vX9W0o=Z2DrUf~*=K{a5!8<@*06!`T4h(*VfkbYe=7!hS6}S?`tVl9XiVPX0?U871lKtMv zzwmeiEoz!2A;-jS@20FD7%h6=zp2sGS+|`0WM+KdRKBSS6g2;5Z}ZUT{n3dP!f{L? zyE)>wd>ib0KmH9D?nG)wGk2nAO!C)+c&F;+B&}mf-!^sbUans19Bc>bF15`tY(6cJ zomi6uXWxX-pahCtNIXRbz!GI)Wrngev#=ytqU=ysc9zy=C|f%e%3*)b=>G_4F`?A3 zl>aX{i**Q<3ADdW@QevdNDhjp0LRdnV2Xh&EhwBqqy&Yg#Pw0W{Q=dW4<@VnH-DZ_(5|0^*CJc67ESUS5c5Li z7DIze1Bkz%sRQ|f8>((In%r7s3yz{m9)gPV0`V^b5gG2rH~^|f8i>E+Or|(8+Dni|sGKkmcLDJwAifR6%YoPsD#rxGTkvKy97P2PTnAzm zJY^RrG#L{vD)1C`ptRos#JWJt3{@uu#OXkMhv>qN$m04pmarzixTbl9LzgO($Vz`L d#g#s_007PCcJn8Um978)002ovPDHLkV1l=Zv4a2r diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_up_dark.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_arrow_up_dark.png deleted file mode 100644 index f07abec9e341f898f8330053915dac3eb00f9a54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 299 zcmV+`0o4A9P)_2vx^&w#w<#DqS zz&uyN0_AbHD}Y^&gaymv_D}%(|4LXvd53R#@Az9}aBf=(D=hEuJ?|Gh16iEkM#3t} zJN$vuEXRk4x?m3K-79Fk~LegP7p@=lF_1Btff xYp50I1_@*%fovp@jRdlhKsFK(LI@!Oya0n;U;REggaQBn002ovPDHLkV1k=feU<V#QhvFJn*1^mXY$iWSmdXTXpx^Tq9z|g*ez%75x?Y*^9P^fY^sPedCYnCy)#F| zKY76O;;wImMIP`@IdhA!$^+ix`Rx%c@_=`F4sMHRl?S}f^UUyw9(llbcwRCzf&(n_ zfMs~j)FSXU?{$$Qtn#2W0F)7z$!G9Gt32ol0C?ka`5t-$ra=MTD8L&9c%uMs6yS{l dgb+dq10UB8SW1hJ06_o%002ovPDHLkV1gD&c>VwY diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_colorpicker_swatch_selected.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_colorpicker_swatch_selected.png deleted file mode 100644 index 812ff2c39cef6c2cf6a1f9a240731138de7835f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3241 zcmZ`+c|6ox8~@oRYvI~6D3Ua4ELnya!;F1ICYfT8LCKQr#8?WsS)=S@x|whhk}P9M znlxc7-LW*bxn(C??jYXj{qOy}@B5t3InU>L&gVJL^7)+ab580dw1tSEoFD)IB372> zjvVg(Yx09Q>+I8TeGcRGF|{)VfVvE!eGfj4%yrk%0s++Y%P(*Qr5l!xb^s8i3IK#8 z0NCZI2=f3C3I%{gcL0Dr1pw)wq80}u&IZWS#=;yp{56Oaat=o$5M=3cm%}apJyE@W z#sDA`X=QHe6fwS1eC@UbLza5zkYK=YP@jubJrM?hQ;7S!6G+I~}+a zl4&sh=2Tcc&<5yl?m&R|`_W){PuoYp`r8_KO1TI^kcLYGlWqFLZnSUDUmwSG$Pp2L z_f-Mv4_QG40580=tp$#RR@R^<>TASb@VjgV+YSUh1RyVlm5J!nMD&pV%R#^nbEOao z=mBcpd*B`cZeA`+q8JXm5;o!8c+-^+V3^*YmnoJY@O@NdHllT zN(e*Vlz6muu{_&G6F!{9wX4e1!k!}JIwul&YHmy#9q$w`^K#RWt;LS9 z#L7x`et!PN3a7;iyFy)mv}(>=x}r&Jb8BlML#MigFavnG-v}C8c>%~v{gkJQIY?yn zc{g?^A6v6|?ih`CsoC1v`d;N+J1L*m(_aD$T{N@GPKq&(BbQ8bxxQ@h5AO@$@&san zK1|cCKnl=|E0bE%{cPiSAU zU6(0!IgNd&=0OU3{Y&x<;3|Z&VTB#g&>(*jwR#w)}@Ra?J z?9DlxjGP>7h{;?zFCmC}?&yqd$~%3#S0PNmJvUp2k;0(;y~$3fti&n@RtR^Cnu-$D ztOJ6BH`X~(cUOME-I6|$1YHQ(JES-i6ndrdPQPSD7; zZZ0+qubF5HoO0H&qk*{N4N>`2)`{4TQniO9G#YJetfjT_JB0Q^jNRfPvwL4iI<_r< z*^=+8qwcLG%hJ6(fEA?^{p9R(Oad{|5kY>>P0dnBAG{h|wg)W~?E=Q?@s(uq>6hMp z1r{YS8@(Nt*%JH94Fl>reqXFZ|F*ZaUABDgXiuyE)8b^-qB!bmm>A+Io6Sx%Gcy~` zR$)sbHPv%JS`U|hZIv|9qsJ&TC=4BI37C9&qU=&ipLfIfU)9%G$1ZNsLyQy-gX7{l z?DM|XQa$TB`uh80=}e}EZ$TJsD-S<5pd9Dv>ACm*(ectWD(jC2o1uV8G5RnhC@9D= zTP034r)ze0)*4JDtUkW!TR%5(2HxGEq`lFYtQdQBvL$qB#!G9AF)>lq0P*8bn6_8V zDU6Pa>Mt>h+~Bdw{wKyb5YXA+i3cQ*y^kI}@>c|dFN$VR#Zt{H{SmnrKke`D+ax9? zc4VpameRf!+-VOzW+9-Yt4Q;Spn&gKrn9J-y}1%M9{#45o&=G-7mbYXVSPYrf zJGZ&`V`ZWv$NG7D=ngadd_AP~OA;Y|>^Je$cg~4j(_;)=+`R*OnVBKV!UFdgpP!{t zF@AK~`_B2h>$5$$qr$@bF!`eslI+jEL<;c?*D_XLh-==om>Vk0Q!*zou$ikj8Nuq@ z-CpXL+m1T>0xT*CEPt+YHi?=m4oB~7Z5jQ=U{KAUIr!bLm*WANLl%Z;9Avp*mCcL6 zI6$OULX5e-3(QZ#hegKX0e6hDN#`B;Gf!wR!ba;_``%kRogPkct4$wYQw0GewO0j3 zqWlo%_1g4(XAlS!D=B#29D^wY2l=hrk6zODdIBf_escZ;bDLr%bB{QcdOT2MaQAyj z^eS7IdZ%eg;Iq$>JVTPXl$4a4or-uZC$JMwXk%dZ=bc?cLXY?H`X#$jm^>pB=pYs#?{Dzve&BQd`kU{2jur1nKd`Nh=^e{PaULEsjpirUt)Vg!TKTqBMfRV3LPuf= zn753e4E0=VSU1#`gQRPeoyobOg)PN3rMJO5-sf=bMtPPhZt19JF%?d?FymYSXjA{2 zQ~e^cHiQQv+R@xL{2nM2s>F&s9H;h#ww>~lpTPcyl@TYMLB$CscOz7DPK2I2TgzMJ zx+H8meC7+9>(6Jzv$qnyM!R$YsZSrnVA{#+_!HBPR~v|0WS;6 zi>Er`4sTG?!L4rUx%x;4tjj@w$U)@jRY{LDDf3h(ddbjyhE)2AFHkQmGahWiHc(BftDaybU+^p}DA zHBu5w-?73e#FcRYa3!e)`-d3Ae{P*0y(;E2Sb1_>+;;&beOvAFNGLc-R6Nx@!j+NQ zs5z`EbBT)cL$azN%3BHLCnwBRliZsrGg1ink%J66$zJx=My6Yjj`1id`W27gSo1>Y zA@)^E`cy&o?hG+|8|J}vov(QN)s|{CipRCa&Ed0ovb(7X{%#{!@759Z7yRH_#cCc< z2zklcFyOELXXXZ*vFKF+Vc)--df4#2fnb-~b)$fGJJ<|78Q&fEsmecO7FrB~>2DHm zRt!_Ru%55+ITQz2Xh9usLAE~qln|(x?IjDx)gOqoJe~|IqW@%O{4fAOPAO2|j3AS1 zW2Vtq_RJMNo$b)5FU>uc|Wc%!kg0C zaJALA>1hsr|2H|B9P-u6OR9=ocChBW#!rPHuZDPegy3N}g7F*%XhAi#HK1A=np#d; zP#9DjrgcFBstxXaE2J diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_notification.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_notification.png deleted file mode 100644 index 99411ad4e1d954da500a987e5d9e7adf0a14311e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 816 zcmV-01JC@4P)HKLC7CtrxxKfR88N4&xi0$hgFORkdHLR(par z({hnXn^YN;Z5{xdfuRuW2mW}@PPr(DR9K$BAk_0dhI1kx1+dz|fg8;4cL_Is zC2UbiN&FYs=C}u*0_z#hxTF*hYepn;hvANDL=2&qK(E1B2P_C|$Z`(kg%0d6czwWU z%1)yZ)95Y6jsh_ejuijiWE=rju~3iK@jTPzYuk#nFVAl@`Mo%HlwWWvzd zMGqoON-4{~?zF+#?%{BH&e-y*38!r9z)^#9(1QbC8CxFNI3Nk3!v^P&2M4}0wmh^6 zA;~5_Zg7S@IPjLSrE0T@C291k!Rev8$VF~5_1J<<8kHPm&luiaM+b6-zO7aVnXr^t zGDm~d+$>re|Cq7iyj3X?p_seG@XlBm{{^4o-71jL$Xz-<%p6VN3a6P6qHhsj0t41ArOe9&i@e6u?;nJaKL* zg-v~9UvSLB4wz`aD>DBC%uu0000BjzF<&YlxDw=dy-`X>02i{o3G6=KVzG>6NN|`kvo!Pi%2K`oU7Y=#}(3&4shRsU|uYmYkb8=U3lrFPGTelMH4^ zn7N-~T(qs_wZj$-PUcR(Ca{?_L z_Gmw}QoE+Z*?ZK$Qv4+2qg>AGnn}HrE(GvQEZ!)iaBq6SU4e~io*62$p8HH>>c%9JMwxYrhhq?pXYS_MXTl+3Ue~p=_STV2Tg5QrD&(CT(8smK- zEx}OCWrGB_QbZ4{pw6)-4zXlMmhO!TO-CaH4kqbz5GQQ}j4NP-&8Yp%o{~Ca@ro^` R)xZS6;OXk;vd$@?2>^qivyl7UHJL9?KRRF9tePG2^iM(Nid~-N^`TGa6rZzvKBxHIm94qI z7e3s%x~_26vY*!^IC~3wT9y^`e7P=j?&ZX359Wwv@}7G+VcUZ_Y?=IiA3Zb+lDeF| zI)#IIE}72Rwa&hB+Y`UZwwHwF?0Y}ILhf?u-OnF>9{v0=rF)Br`|ds67h@-SWEY6M zPkyvdW64&FE^EWbbCrOmX}mjHpr5^Dtwq;v!#lx|N^cJa-syiBH%0VPoXpYmq#fpZ z+)G3(y3QXh=$Dn!6zzMo+3?QnR}(xm3q|JlKfG5j%cW`B_sANk@Ot8eXAM9D_o=s4 zUyo||axOjZ(g$a~Kc9eRzwdf@Z&KQXxSiFPk9kxVTsboTCeISJ3GcdvIWzV9l+MH{ znEqKOuE;w-f6wl0=5xyDuer?-amYGQ`5Pi$+k^z-~ zcEB(*C&OGP>Q0VFV$uPPfIenl`nj$2co|0ZfI;THpv{Ju9e#X%>1ELu^r0e_h?xrr z0mfPE2>NmfeTz0Z1%PfAyMn$IM2nmX235EpDW!E)UII&lk7V!4lzvjuN3IntKoOMo26YR!QO0nk}h@7)v8elNL39C zsq&t(BDf^ztZcr3|IG({B>G>j;%rcZpjwIEG|}otn1il5khG8Je^7;>E~4@t2d8gv zq!?Ponk2U70NxUGcB&9GKqTm(MCatma~erRf^ad|Cb4;ppfjveE1w`J9sw*6=*-{& z9TSlRf4?T)lsBS@6|QFk{t!sdlo3=+bo7Bl=TX6TZt>mxIn9`>PGb8hL0_?qpa9Xy z6B3<0miJPRB(^UQ^aW%D)exNw2=wK9u-P0F4GXxwhoG-UMo=Bm$pV4CT90<*TLkt? zOb%Hcg3<;0j(bGVeu4cw(*#k5*tjGBZ1RYp!vgzRriU11lE$Sm%|cY}Mh*$==a`

aK98S$h5qSgN3Z zJ>WKTE*s-YbrY~!L1z)8Rao7Xo;8{m{>ux%JViVBMD4(MhCf*y7+3Ld10&%KMLmm% zPd%-9fzbXkEz_s^;|w%;EoAf-!FsP6sAdwZR%BZyXPHI_q1Qk)>5z)fIg9~Wc}CN> zU4XAdzw}%1COHz)T$(3%Y?WiMCHan~Pa%_c%2XRLHgaEKyswAg$2#_}LF>1sA7ESAexvh&Q`Sv2#FF-`KMtiZ z-24M|4kYC>|461%2oQ^hdP6MQhk9p-xcy_{3VS#I#R7_{693f{ikV6OW~clG#qv`W1S@3j00000NkvXXu0mjf%Y#jZ From 056f5f6fceedffabdeca396875b5b43f05fd63e8 Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Wed, 8 Sep 2021 19:39:59 +0200 Subject: [PATCH 014/132] Added last .svg icons --- .../main/res/drawable/ic_arrow_up_dark.xml | 25 +++++++++++++++ .../main/res/drawable/ic_arrow_up_light.xml | 25 +++++++++++++++ .../ic_colorpicker_swatch_selected.xml | 17 ++++++++++ .../src/main/res/drawable/ic_notification.xml | 31 +++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 uhabits-android/src/main/res/drawable/ic_arrow_up_dark.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_arrow_up_light.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml create mode 100644 uhabits-android/src/main/res/drawable/ic_notification.xml diff --git a/uhabits-android/src/main/res/drawable/ic_arrow_up_dark.xml b/uhabits-android/src/main/res/drawable/ic_arrow_up_dark.xml new file mode 100644 index 000000000..80f922f0c --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_arrow_up_dark.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_arrow_up_light.xml b/uhabits-android/src/main/res/drawable/ic_arrow_up_light.xml new file mode 100644 index 000000000..8f5c3fad1 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_arrow_up_light.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml b/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml new file mode 100644 index 000000000..1c8ef0b04 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/uhabits-android/src/main/res/drawable/ic_notification.xml b/uhabits-android/src/main/res/drawable/ic_notification.xml new file mode 100644 index 000000000..fccfd645f --- /dev/null +++ b/uhabits-android/src/main/res/drawable/ic_notification.xml @@ -0,0 +1,31 @@ + + + + + + + From f119cbf8e71c219fbba72ee6398ea7f80a97818b Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Wed, 8 Sep 2021 19:41:13 +0200 Subject: [PATCH 015/132] Added copyright notice --- .../drawable/ic_colorpicker_swatch_selected.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml b/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml index 1c8ef0b04..fa75de075 100644 --- a/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml +++ b/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml @@ -1,3 +1,18 @@ + + Date: Sat, 11 Sep 2021 14:03:06 +0200 Subject: [PATCH 016/132] Dialog's positive button has bigger font size now (#1096) --- uhabits-android/src/main/res/values/styles.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/uhabits-android/src/main/res/values/styles.xml b/uhabits-android/src/main/res/values/styles.xml index 9bba46775..0a3e9da10 100644 --- a/uhabits-android/src/main/res/values/styles.xml +++ b/uhabits-android/src/main/res/values/styles.xml @@ -169,6 +169,7 @@ From a55f4673392551f2dc56aabc61d2b3ccdc2158f1 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Sat, 11 Sep 2021 07:21:45 -0500 Subject: [PATCH 017/132] Minor changes to ic_colorpicker_swatch_selected --- .../main/res/drawable/ic_colorpicker_swatch_selected.xml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml b/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml index fa75de075..4d50dde76 100644 --- a/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml +++ b/uhabits-android/src/main/res/drawable/ic_colorpicker_swatch_selected.xml @@ -21,12 +21,9 @@ - - From 804edfa64e15b8d2aa3ba19de9b8c260d8063801 Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Sat, 11 Sep 2021 23:23:52 +0300 Subject: [PATCH 018/132] Implement numerical habits with AT_MOST target type --- .../habits/edit/EditHabitActivity.kt | 10 ++++- .../habits/list/views/HabitCardListView.kt | 9 ++++- .../habits/list/views/HabitCardView.kt | 16 ++++++-- .../habits/list/views/NumberButtonView.kt | 40 ++++++++++++++----- .../habits/list/views/NumberPanelView.kt | 19 ++++++++- .../main/res/layout/activity_edit_habit.xml | 23 +++++++++++ .../src/main/res/values/strings.xml | 3 ++ .../org/isoron/uhabits/core/models/Habit.kt | 11 +++-- .../isoron/uhabits/core/models/ScoreList.kt | 32 ++++++++++++--- .../screens/habits/show/views/HistoryCard.kt | 22 +++++++--- .../uhabits/core/models/ScoreListTest.kt | 4 ++ 11 files changed, 155 insertions(+), 34 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt index 1a02d8845..8bd84b98c 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt @@ -117,6 +117,10 @@ class EditHabitActivity : AppCompatActivity() { binding.notesInput.setText(habit.description) binding.unitInput.setText(habit.unit) binding.targetInput.setText(habit.targetValue.toString()) + if (habit.targetType == NumericalHabitType.AT_MOST) { + binding.targetTypeAtMost.isChecked = true + binding.targetTypeAtLeast.isChecked = false + } } else { habitType = HabitType.fromInt(intent.getIntExtra("habitType", HabitType.YES_NO.value)) } @@ -138,6 +142,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) @@ -262,7 +267,10 @@ class EditHabitActivity : AppCompatActivity() { habit.frequency = Frequency(freqNum, freqDen) if (habitType == HabitType.NUMERICAL) { habit.targetValue = targetInput.text.toString().toDouble() - habit.targetType = NumericalHabitType.AT_LEAST + if (binding.targetTypeAtLeast.isChecked) + habit.targetType = NumericalHabitType.AT_LEAST + else + habit.targetType = NumericalHabitType.AT_MOST habit.unit = unitInput.text.trim().toString() } habit.type = habitType diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt index 58ee2b36a..c1935be75 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt @@ -36,6 +36,7 @@ import dagger.Lazy import org.isoron.uhabits.R import org.isoron.uhabits.activities.common.views.BundleSavedState import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.NumericalHabitType import org.isoron.uhabits.inject.ActivityContext import javax.inject.Inject @@ -97,7 +98,13 @@ class HabitCardListView( cardView.dataOffset = dataOffset cardView.score = score cardView.unit = habit.unit - cardView.threshold = habit.targetValue / habit.frequency.denominator + if (habit.targetType == NumericalHabitType.AT_LEAST) { + cardView.higherThreshold = habit.targetValue / habit.frequency.denominator + cardView.lowerThreshold = 0.0 + } else { + cardView.higherThreshold = (habit.targetValue * 2) / habit.frequency.denominator + cardView.lowerThreshold = habit.targetValue / habit.frequency.denominator + } val detector = GestureDetector(context, CardViewGestureDetector(holder)) cardView.setOnTouchListener { _, ev -> diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt index c59b61ec1..4fca5befa 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt @@ -109,10 +109,16 @@ class HabitCardView( numberPanel.values = values.map { it / 1000.0 }.toDoubleArray() } - var threshold: Double - get() = numberPanel.threshold + var lowerThreshold: Double + get() = numberPanel.lowerThreshold set(value) { - numberPanel.threshold = value + numberPanel.lowerThreshold = value + } + + var higherThreshold: Double + get() = numberPanel.higherThreshold + set(value) { + numberPanel.higherThreshold = value } var checkmarkPanel: CheckmarkPanelView @@ -236,7 +242,9 @@ class HabitCardView( numberPanel.apply { color = c units = h.unit - threshold = h.targetValue + targetType = h.targetType + lowerThreshold = 0.0 + higherThreshold = h.targetValue visibility = when (h.isNumerical) { true -> View.VISIBLE false -> View.GONE diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt index 3e48ed1a6..1d474a22f 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt @@ -29,13 +29,14 @@ 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.text.DecimalFormat import javax.inject.Inject @@ -82,7 +83,19 @@ class NumberButtonView( invalidate() } - var threshold = 0.0 + var lowerThreshold = 0.0 + set(value) { + field = value + invalidate() + } + + var higherThreshold = 0.0 + set(value) { + field = value + invalidate() + } + + var targetType = NumericalHabitType.AT_LEAST set(value) { field = value invalidate() @@ -127,7 +140,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 @@ -148,15 +160,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 <= lowerThreshold -> lowContrast + value < higherThreshold -> mediumContrast + else -> color + } + } else { + when { + value >= higherThreshold || value < 0 -> lowContrast + value > lowerThreshold -> mediumContrast + else -> color + } } val label: String @@ -175,7 +195,7 @@ class NumberButtonView( textSize = dim(R.dimen.smallerTextSize) } else -> { - label = "0" + label = if (targetType == NumericalHabitType.AT_LEAST) "0" else "inf" typeface = BOLD_TYPEFACE textSize = dim(R.dimen.smallTextSize) } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt index 491656a77..94980dfac 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt @@ -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 @@ -47,7 +48,19 @@ class NumberPanelView( setupButtons() } - var threshold = 0.0 + var targetType = NumericalHabitType.AT_LEAST + set(value) { + field = value + setupButtons() + } + + var lowerThreshold = 0.0 + set(value) { + field = value + setupButtons() + } + + var higherThreshold = 0.0 set(value) { field = value setupButtons() @@ -84,7 +97,9 @@ class NumberPanelView( else -> 0.0 } button.color = color - button.threshold = threshold + button.targetType = targetType + button.lowerThreshold = lowerThreshold + button.higherThreshold = higherThreshold button.units = units button.onEdit = { onEdit(timestamp) } } diff --git a/uhabits-android/src/main/res/layout/activity_edit_habit.xml b/uhabits-android/src/main/res/layout/activity_edit_habit.xml index b3a33c373..e30490bfb 100644 --- a/uhabits-android/src/main/res/layout/activity_edit_habit.xml +++ b/uhabits-android/src/main/res/layout/activity_edit_habit.xml @@ -167,6 +167,29 @@ android:hint="@string/measurable_units_example"/> + + + + + + + + + Change value Calendar Unit + Target Type + At Least + At Most e.g. Did you exercise today? Question Target diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt index 2d354e7b8..a2dd13846 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt @@ -59,9 +59,10 @@ data class Habit( val today = DateUtils.getTodayWithOffset() val value = computedEntries.get(today).value return if (isNumerical) { + val targetValuePerDay = (targetValue / frequency.denominator) when (targetType) { - NumericalHabitType.AT_LEAST -> value / 1000.0 >= targetValue - NumericalHabitType.AT_MOST -> value / 1000.0 <= targetValue + NumericalHabitType.AT_LEAST -> value / 1000.0 >= targetValuePerDay + NumericalHabitType.AT_MOST -> value / 1000.0 <= targetValuePerDay } } else { value != Entry.NO && value != Entry.UNKNOWN @@ -72,9 +73,10 @@ data class Habit( val today = DateUtils.getTodayWithOffset() val value = computedEntries.get(today).value return if (isNumerical) { + val targetValuePerDay = (targetValue / frequency.denominator) when (targetType) { - NumericalHabitType.AT_LEAST -> value / 1000.0 < targetValue - NumericalHabitType.AT_MOST -> value / 1000.0 > targetValue + NumericalHabitType.AT_LEAST -> value / 1000.0 < targetValuePerDay + NumericalHabitType.AT_MOST -> value / 1000.0 > targetValuePerDay } } else { value == Entry.NO @@ -96,6 +98,7 @@ data class Habit( scores.recompute( frequency = frequency, isNumerical = isNumerical, + numericalHabitType = targetType, targetValue = targetValue, computedEntries = computedEntries, from = from, diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt index b5dff17de..037721d82 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt @@ -68,6 +68,7 @@ class ScoreList { fun recompute( frequency: Frequency, isNumerical: Boolean, + numericalHabitType: NumericalHabitType, targetValue: Double, computedEntries: EntryList, from: Timestamp, @@ -91,18 +92,37 @@ class ScoreList { } var previousValue = 0.0 + val numericalUnknownDayValue = (targetValue * 2 * 1000) / denominator for (i in values.indices) { val offset = values.size - i - 1 if (isNumerical) { - rollingSum += max(0, values[offset]) + if (values[offset] >= 0) + rollingSum += values[offset] + else if (numericalHabitType == NumericalHabitType.AT_MOST) + rollingSum += numericalUnknownDayValue if (offset + denominator < values.size) { - rollingSum -= values[offset + denominator] + if (values[offset + denominator] >= 0) { + rollingSum -= values[offset + denominator] + } else if (numericalHabitType == NumericalHabitType.AT_MOST) { + rollingSum -= numericalUnknownDayValue + } } - val percentageCompleted = if (targetValue > 0) { - min(1.0, rollingSum / 1000 / targetValue) - } else { - 1.0 + + var percentageCompleted = 0.0 + val normalizedRollingSum = rollingSum / 1000 + if (numericalHabitType == NumericalHabitType.AT_LEAST) { + percentageCompleted = if (targetValue > 0) + min(1.0, normalizedRollingSum / targetValue) + else + 1.0 + } else if (numericalHabitType == NumericalHabitType.AT_MOST) { + percentageCompleted = if (targetValue > 0 && normalizedRollingSum > targetValue) + max( + 0.0, 1 - ((normalizedRollingSum - targetValue) / targetValue) + ) + else if (normalizedRollingSum <= targetValue) 1.0 else 0.0 } + previousValue = compute(freq, previousValue, percentageCompleted) } else { if (values[offset] == Entry.YES_MANUAL) { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index bd201e0c5..f1c05861c 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -29,6 +29,7 @@ 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.models.Habit import org.isoron.uhabits.core.models.HabitList +import org.isoron.uhabits.core.models.NumericalHabitType import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.Timestamp import org.isoron.uhabits.core.preferences.Preferences @@ -105,12 +106,21 @@ class HistoryCardPresenter( val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today val entries = habit.computedEntries.getByInterval(oldest, today) val series = if (habit.isNumerical) { - entries.map { - Entry(it.timestamp, max(0, it.value)) - }.map { - when (it.value) { - 0 -> HistoryChart.Square.OFF - else -> HistoryChart.Square.ON + if (habit.targetType == NumericalHabitType.AT_LEAST) { + entries.map { + when (max(0, it.value)) { + 0 -> HistoryChart.Square.OFF + else -> HistoryChart.Square.ON + } + } + } else { + entries.map { + if (it.value < 0) habit.targetValue * 2.0 * 1000.0 else it.value / 1000.0 + }.map { + when { + it <= habit.targetValue -> HistoryChart.Square.ON + else -> HistoryChart.Square.OFF + } } } } else { diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/ScoreListTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/ScoreListTest.kt index f78af6d21..ae2a8eedb 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/ScoreListTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/ScoreListTest.kt @@ -128,6 +128,10 @@ class ScoreListTest : BaseUnitTest() { habit.targetValue = 0.0 habit.recompute() assertTrue(habit.scores[today].value.isFinite()) + + habit.targetType = NumericalHabitType.AT_MOST + habit.recompute() + assertTrue(habit.scores[today].value.isFinite()) } @Test From 697fffbc9935ff689d768797e333c7d4ed179fb6 Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Sun, 12 Sep 2021 13:50:27 +0300 Subject: [PATCH 019/132] fix tests --- .../activities/habits/list/views/NumberButtonViewTest.kt | 5 ++++- .../activities/habits/list/views/NumberPanelViewTest.kt | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt index 6f1923aaa..c06aa5fb3 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt @@ -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 @@ -42,7 +43,9 @@ class NumberButtonViewTest : BaseViewTest() { super.setUp() view = component.getNumberButtonViewFactory().create().apply { units = "steps" - threshold = 100.0 + targetType = NumericalHabitType.AT_LEAST + lowerThreshold = 0.0 + higherThreshold = 100.0 color = PaletteUtils.getAndroidTestColor(8) onEdit = { edited = true } } diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt index bd046acc7..f5d992f62 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt @@ -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 @@ -55,7 +56,9 @@ class NumberPanelViewTest : BaseViewTest() { buttonCount = 4 color = PaletteUtils.getAndroidTestColor(7) units = "steps" - threshold = 5000.0 + targetType = NumericalHabitType.AT_LEAST + lowerThreshold = 0.0 + higherThreshold = 5000.0 } view.onAttachedToWindow() measureView(view, dpToPixels(200), dpToPixels(200)) From 1a56260757b19dfc7c20cf193b10737a2e4ce6c8 Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Sun, 12 Sep 2021 14:32:59 +0300 Subject: [PATCH 020/132] add more tests for AT_MOST --- .../NumberButtonView/render_at_most_above.png | Bin 0 -> 2294 bytes .../NumberButtonView/render_at_most_below.png | Bin 0 -> 1838 bytes .../render_at_most_between.png | Bin 0 -> 1986 bytes .../list/NumberButtonView/render_below.png | Bin 1958 -> 1856 bytes .../list/NumberButtonView/render_between.png | Bin 0 -> 1958 bytes .../list/NumberButtonView/render_zero.png | Bin 1856 -> 0 bytes .../habits/list/views/NumberButtonViewTest.kt | 37 ++++++++++++++---- 7 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_above.png create mode 100644 uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_below.png create mode 100644 uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_between.png create mode 100644 uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_between.png delete mode 100644 uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_zero.png diff --git a/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_above.png b/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_above.png new file mode 100644 index 0000000000000000000000000000000000000000..5bd20a34f244dd23221010487efa7e8ee62530e4 GIT binary patch literal 2294 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 literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_between.png b/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_between.png new file mode 100644 index 0000000000000000000000000000000000000000..b407ccd6264a4dfce901652485f8725f1d0af0d2 GIT binary patch literal 1986 zcmaJ?X;71C5`IG>L?FPxsGI`sCkSc)N5Unip!o;}2f4(cXyh2eAw)zFB;qXN!3e~Q z8)qOW5g8#wu1SE2fEfm&*#L_mB8MC?2^$bZ3~b!me_OR(-EUX-kEhu^5ujn*W2dnVyQemc%@n<8 zj>4ZsYHDhpz0oy+1L06Kl2)a6Yw|-Zh0<2ZVzG>)N#8L_$~>OT5;C%3T@JHC6YCKwR}c#Whygh8oS-Vpv63= zxtb7&#D|4(5^~dOW8YQ|tl{elV@bLY69Gt}oHMzrha-!o3g$EE*qi2cbGie7?)Nd> zxvczq_UGUu|I$8UkKL?HLV3Zz5#}8U!-F;5J3W6j^bk_*OA?rS@;@+#9WGxuk*GwR z_uf-R-1wD*m4W;lxOh#T4xMN~Cdnn0QE;N)e{hfu!*K|YQ+@A$hT7o4b=H?lOl1X+ zlygFNKz@3IYAa_R-=G*L_1$}9js~QmOoFi3Rx{)_Y4d|F{Y5n2$G&G>(EZI&+;s{7 z*RX}Ih8zG+>#sjzzNq)JSnO$@D7H#E_|iMu>=TaW9~}RA?rhzR$jG5gcNlp=I_gx( z;V1%N6R2H%y!UP=Scpet9e(}_qLY&VZoliR{dGdUPQ5CKc=AB$`7e!?06=7wJ-d8dL#xy%8Cr8NR z@lGJl(@QnRQ@|SZM!L3+1}M*SmV65I1X@J^0l3(gR9fPYIQGStQJ3M?9w1DG_F5cQ zS%|Z~+xoYXzU{Sl=EUMP`lKVbN)6(`@;0zl#gQnF{=3&Z>DbswD%T0;%e&OEu&`hQ zCm^4q0Thmi*iGwEQ&ZcWw;8MU)Z(+;{09S?JtM&CSdAq*J5irp4i+}iCG__y|2&Gl zU-4Q=1^daY{7I5(#9sahyqljq44B@sNF24#TK`fZDk2};--!6b_KPOpXlI$xU~l;|0@B{{GV-y36(~YwZ~1VDJdqH>~R^i zO`q(B7;j+~9@7hCYj>o)($S;b`WPF7#HZ&^tsqFTxoPH_yl^s^yt1^kRO%>TVo`uz zf#EI4iv@TD&F+0RHE6<-=&8HV-?AxbI`n>ymM2%1r%$fCecqja0W`528^2W+n;H>e zM(tN0!+n>&p-vlNo`Pl&v?>Fcu1mlEF(u?=B>As;EXG~^&*@~#%(tn>YD9M(7g1F8 z4u_jv6P;Wxchl|KL&{yU6;zbW`pD;~K>=w2VM3Sp=;wFH;nfm9$In;9{WFU$xpwX5 zX-<3@Vz%7-;&kX2AHkwUx=MP(dmove!p+aVr*(g$8p_jF2h~||)l9#_aK2SafU?lJ zripnjy?d7LS1Nj|3x)LA%;quU$-$SZW~&zbF6a`oDJ068Xxk)q2l>7XEVE|jT}-{D zv!(vFoOgp}=yllv+SJ3VW}jjrUD4SL`rx6p%cl}=B~fM>*K9Ry5a)o$A>kq@zjb;4 z5Pk=LpnS&lq?IYEGY?KcEEv)hP-05>3Zt{LQ#3m}dm9Af4ZDi2>-WG|#8Z+m37D>A zW~CqPQyuR4wa?K@UIL512&)p3KN6!)OH_?Z&&sNrkm0fCW4nk%i{TW=>=X=5$3uhv5o*GRSaG8ui{^ZP1Mz%qFY(XnL@(tX2Cxs&yUr^j```OY Bv8Mn4 literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_below.png b/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_below.png index e5a98fc8987e73c6edc7c3de02ed3801638066bc..5f6bf8c65cf649ef2b9f437feaea7fed323ec774 100644 GIT binary patch delta 1826 zcmaJ?dpy$%8~?G*B^|6obSlbuOO&CxmAlUrHd$Ci3r((_h<7}USbIPz7n*>po(qXtIv5x_@M(EgR1|3a3bGtlTB z7pWs{fRzdF2!`jF^_*Y_wZeQrL(vPv-QKP6){tMA4Vfj640`PABA0lz^-S*ty%}1h z;m^}A^zvedOgpw_FNNaQKhi_{I1h|Y$R>5o{hw6lXVVD@d$Ya0{q*%~%lv_bkb&n~ zGD%5EL*Lw;)V*OqxubvoR+}o|0o*vd7)c;;`8#WO>b7GJ-qRc^#4`%^{$LQ5f^%65 zAyZecT&aku3_P6^FN60>nt#(d!IX4$uVTl~oHtFg^l`HY;UCDj7UfhBbp>oLf82T= z&?%TuobaX;en}fPV4`GndOyDX{!ES+Rg8{0EA{)YYMY-kv55J7l>u%J3v7Wfpylk3 zqPm0Q{#kynVK?aeH%nyab$pLO}_Q(Iz7?`={`^m^mfR6aool-S=mweg&NC{{*J3uvF zdv*Yy%K`&NAD)^UYAE$>sEA=9>*H{UrI zJ(C?<72xHq3H03A2!my}Dn^Oh$RTlfPBe~1`5tEm7n*xl%h)+lZn*RW$CZ*{*V#Br z`GT)aXa7qV*`HqJrAl@2Y(2GV``mVu;@#4QL4AmItq%Xb&E>=xj`C(PB!6B^SU(g((q zL5I2?*uPT-zg7uceRE1mCC}IN_%q>LLmm2D0kAJU@8j#+R5pN^?+kq(s)L{0#STwE zvF(y97HjX0rzZ#MssG?YYDwQ?U31pb)+($ZKo)7PXgy+sya~Hm*|Fl7mE7?`tyET+%hrW9#9;eLQAb!UPgU-pNQtIcsKl7P0kQjMqVH`GH#|>vZIel04)$ z+K-YVQ)x-d2jFIs8|6NAoa-QN*d4s5B;jZj1owg?b0nvdgSN?kX6(Wq@sV~)23%RH+m}cLURJ=Z% zGc}pps4j;bRt_Ys`aToVwD@~wwq|Hpwzia&a$;C0u+#5wH*Ny0luv+g4IPpi2vKb~lD zadD@(yB~fJm#*YjkV9lhaGcw3Yb&Jnyz^3CgQ%2m41Y7=UF8Uwy4j$s6k5J9yLlpv z1_4|0B5|xj3rMYA1<(kpN$u~Vn6s3(9&!{pAV&HksS=07)stI5+ls{9v6Bp?1U`93 z9W!m#SMau;8KF(oNLyf}F|hum2z{7=DLz&eO}R174xn)po>|H}!xmjMvm`|9*)v*2 zP?M9pmp7SArXm~;&$mXH3{^FzkLPPyAmW#H_kEG&qXD?be3KwD`dpdPw}|SI4V8Zg zz#{&a;{$W$)*f2C2p0PScew)$4(GfyW(S@AACo!$!*hTGNre|95ZaMBE+7h9>uU(A ImFMq&1BSkpqW}N^ delta 1929 zcmV;42X^?t4yF%~Gk*tNNklK&Q zShO`^MJN`k?cIgm?d<#b$L^M4xyrH3-cHH;NjA6hzVGwibAR*B%)T=_b6{DPWm%SG zS(as4mStI%Wm%SGS(as4mStI%Wm%RL8)208P^Vp z9Dw2B;q=7B#AXp$3tU_)J}x5Ly1Tm{?Ca~R#2MF49qmq_(eUtadUA4dkBBU6sJcv5 z3*+PCH>v6>5r5G*;@Zt=cLI&dnFHBub`S7)q}>&xqocRQ z5Z88z8UR&Y6kRsPJQt~ZHd-elOV2kh2@*8`z~#{eV}H!Q>hDG5aI{WUua6LxC29af(;GZsZ{DZRh=gyUkAP#sXpG-)qk}q&bW3;}@tld(w(eu20XAQUjB+Nbc-`*}F_d1TVTSRUFK1_Ac9`5Ps`Dv3m zwnR$@AP9ob0$&E+bX|A8=XqBdW99)zfJI|tV_AS)F84Xl^E!Z+0E{trc%Ijh&wuA% z0`Pr*o`^gOltpBv=XsZu%jJtz^$DQ6QmJg7;@95-e5X_@rBbO>8hD^qes>TApFGzb zTcxD~psKgl-aePfWc~(_&*xuN)yIH0MdYUG^dll!phH!Mvf1n}0R{#J%3&DZNA=F= zshj=^o&D-am{n%YnZD3sm(RRJX!Is(NSR zAEv551`bl4cHU`>xd@=Iudgy|)~ppk0CcMA%Gy9JR@JA0rBht9*#+ztksPp!>dODU zh(zz0KIa_cHe=rh6pO{Hfh)r>Jlx;kfB3!H6$*up-rn9D!+$WG$mjE~H2!y!p`oGf zFbwB8jw2Hj6Neh->-9ZARezq#S(as4mStI%Wm%SGS(as4XY)Tye(;%j8fQBI P0000idhs^$HtVU7NLQK4ykspC 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 d9u{C{jQjny?I)zahlzX8SIl?ng= diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt index c06aa5fb3..83609c9a0 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt @@ -44,7 +44,7 @@ class NumberButtonViewTest : BaseViewTest() { view = component.getNumberButtonViewFactory().create().apply { units = "steps" targetType = NumericalHabitType.AT_LEAST - lowerThreshold = 0.0 + lowerThreshold = 50.0 higherThreshold = 100.0 color = PaletteUtils.getAndroidTestColor(8) onEdit = { edited = true } @@ -71,28 +71,49 @@ class NumberButtonViewTest : BaseViewTest() { } @Test - fun testRender_aboveThreshold() { + fun testRender_aboveHigherThreshold() { view.value = 500.0 assertRenders(view, "$PATH/render_above.png") } @Test - fun testRender_emptyUnits() { + fun testRender_atMostAboveHigherThreshold() { 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 - fun testRender_belowThreshold() { + fun testRender_betweenThresholds() { view.value = 99.0 + assertRenders(view, "$PATH/render_between.png") + } + + @Test + fun testRender_atMostBetweenThresholds() { + view.value = 99.0 + view.targetType = NumericalHabitType.AT_MOST + assertRenders(view, "$PATH/render_at_most_between.png") + } + + @Test + fun testRender_belowLowerThreshold() { + view.value = 0.0 assertRenders(view, "$PATH/render_below.png") } @Test - fun testRender_zero() { + fun testRender_atMostBelowLowerThreshold() { view.value = 0.0 - assertRenders(view, "$PATH/render_zero.png") + 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 From 113a5028af7e705c8a5bd164e3d98c65a46d6175 Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Sun, 12 Sep 2021 15:27:03 +0300 Subject: [PATCH 021/132] Simplify the code --- .../render_at_most_between.png | Bin 1986 -> 2045 bytes .../list/NumberButtonView/render_below.png | Bin 1856 -> 1958 bytes .../list/NumberButtonView/render_between.png | Bin 1958 -> 0 bytes .../list/NumberButtonView/render_zero.png | Bin 0 -> 1856 bytes .../habits/list/views/NumberButtonViewTest.kt | 19 +++++++-------- .../habits/list/views/NumberPanelViewTest.kt | 3 +-- .../habits/list/views/HabitCardListView.kt | 9 +------ .../habits/list/views/HabitCardView.kt | 15 +++--------- .../habits/list/views/NumberButtonView.kt | 23 +++++++----------- .../habits/list/views/NumberPanelView.kt | 11 ++------- .../isoron/uhabits/core/models/ScoreList.kt | 12 ++------- .../screens/habits/show/views/HistoryCard.kt | 4 +-- 12 files changed, 29 insertions(+), 67 deletions(-) delete mode 100644 uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_between.png create mode 100644 uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_zero.png diff --git a/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_between.png b/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_between.png index b407ccd6264a4dfce901652485f8725f1d0af0d2..12063c42596410137b13f2f924fdc5ef517f9075 100644 GIT binary patch delta 2002 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 delta 1943 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 ImFMq&1BSkpqW}N^ diff --git a/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_between.png b/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_between.png deleted file mode 100644 index e5a98fc8987e73c6edc7c3de02ed3801638066bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1958 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 d9u{C{jQjny?I)zahlzX8SIl?ng= literal 0 HcmV?d00001 diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt index 83609c9a0..75166bfab 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt @@ -44,8 +44,7 @@ class NumberButtonViewTest : BaseViewTest() { view = component.getNumberButtonViewFactory().create().apply { units = "steps" targetType = NumericalHabitType.AT_LEAST - lowerThreshold = 50.0 - higherThreshold = 100.0 + threshold = 100.0 color = PaletteUtils.getAndroidTestColor(8) onEdit = { edited = true } } @@ -71,39 +70,39 @@ class NumberButtonViewTest : BaseViewTest() { } @Test - fun testRender_aboveHigherThreshold() { + fun testRender_aboveThreshold() { view.value = 500.0 assertRenders(view, "$PATH/render_above.png") } @Test - fun testRender_atMostAboveHigherThreshold() { + fun testRender_atMostAboveThreshold() { view.value = 500.0 view.targetType = NumericalHabitType.AT_MOST assertRenders(view, "$PATH/render_at_most_above.png") } @Test - fun testRender_betweenThresholds() { + fun testRender_belowThreshold() { view.value = 99.0 - assertRenders(view, "$PATH/render_between.png") + assertRenders(view, "$PATH/render_below.png") } @Test fun testRender_atMostBetweenThresholds() { - view.value = 99.0 + view.value = 110.0 view.targetType = NumericalHabitType.AT_MOST assertRenders(view, "$PATH/render_at_most_between.png") } @Test - fun testRender_belowLowerThreshold() { + fun testRender_zero() { view.value = 0.0 - assertRenders(view, "$PATH/render_below.png") + assertRenders(view, "$PATH/render_zero.png") } @Test - fun testRender_atMostBelowLowerThreshold() { + fun testRender_atMostBelowThreshold() { view.value = 0.0 view.targetType = NumericalHabitType.AT_MOST assertRenders(view, "$PATH/render_at_most_below.png") diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt index f5d992f62..da0a2eb8a 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelViewTest.kt @@ -57,8 +57,7 @@ class NumberPanelViewTest : BaseViewTest() { color = PaletteUtils.getAndroidTestColor(7) units = "steps" targetType = NumericalHabitType.AT_LEAST - lowerThreshold = 0.0 - higherThreshold = 5000.0 + threshold = 5000.0 } view.onAttachedToWindow() measureView(view, dpToPixels(200), dpToPixels(200)) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt index c1935be75..58ee2b36a 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt @@ -36,7 +36,6 @@ import dagger.Lazy import org.isoron.uhabits.R import org.isoron.uhabits.activities.common.views.BundleSavedState import org.isoron.uhabits.core.models.Habit -import org.isoron.uhabits.core.models.NumericalHabitType import org.isoron.uhabits.inject.ActivityContext import javax.inject.Inject @@ -98,13 +97,7 @@ class HabitCardListView( cardView.dataOffset = dataOffset cardView.score = score cardView.unit = habit.unit - if (habit.targetType == NumericalHabitType.AT_LEAST) { - cardView.higherThreshold = habit.targetValue / habit.frequency.denominator - cardView.lowerThreshold = 0.0 - } else { - cardView.higherThreshold = (habit.targetValue * 2) / habit.frequency.denominator - cardView.lowerThreshold = habit.targetValue / habit.frequency.denominator - } + cardView.threshold = habit.targetValue / habit.frequency.denominator val detector = GestureDetector(context, CardViewGestureDetector(holder)) cardView.setOnTouchListener { _, ev -> diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt index 4fca5befa..d6e7a2ad3 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt @@ -109,16 +109,10 @@ class HabitCardView( numberPanel.values = values.map { it / 1000.0 }.toDoubleArray() } - var lowerThreshold: Double - get() = numberPanel.lowerThreshold + var threshold: Double + get() = numberPanel.threshold set(value) { - numberPanel.lowerThreshold = value - } - - var higherThreshold: Double - get() = numberPanel.higherThreshold - set(value) { - numberPanel.higherThreshold = value + numberPanel.threshold = value } var checkmarkPanel: CheckmarkPanelView @@ -243,8 +237,7 @@ class HabitCardView( color = c units = h.unit targetType = h.targetType - lowerThreshold = 0.0 - higherThreshold = h.targetValue + threshold = h.targetValue visibility = when (h.isNumerical) { true -> View.VISIBLE false -> View.GONE diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt index 1d474a22f..08685026d 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt @@ -37,6 +37,7 @@ 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 @@ -83,13 +84,7 @@ class NumberButtonView( invalidate() } - var lowerThreshold = 0.0 - set(value) { - field = value - invalidate() - } - - var higherThreshold = 0.0 + var threshold = 0.0 set(value) { field = value invalidate() @@ -167,15 +162,15 @@ class NumberButtonView( fun draw(canvas: Canvas) { var activeColor = if (targetType == NumericalHabitType.AT_LEAST) { when { - value <= lowerThreshold -> lowContrast - value < higherThreshold -> mediumContrast - else -> color + max(0.0, value) >= threshold -> color + value <= 0 -> lowContrast + else -> mediumContrast } } else { when { - value >= higherThreshold || value < 0 -> lowContrast - value > lowerThreshold -> mediumContrast - else -> color + value <= threshold -> color + value >= 2 * threshold -> lowContrast + else -> mediumContrast } } @@ -195,7 +190,7 @@ class NumberButtonView( textSize = dim(R.dimen.smallerTextSize) } else -> { - label = if (targetType == NumericalHabitType.AT_LEAST) "0" else "inf" + label = "0" typeface = BOLD_TYPEFACE textSize = dim(R.dimen.smallTextSize) } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt index 94980dfac..0a5339ce0 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt @@ -54,13 +54,7 @@ class NumberPanelView( setupButtons() } - var lowerThreshold = 0.0 - set(value) { - field = value - setupButtons() - } - - var higherThreshold = 0.0 + var threshold = 0.0 set(value) { field = value setupButtons() @@ -98,8 +92,7 @@ class NumberPanelView( } button.color = color button.targetType = targetType - button.lowerThreshold = lowerThreshold - button.higherThreshold = higherThreshold + button.threshold = threshold button.units = units button.onEdit = { onEdit(timestamp) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt index 037721d82..f96d7857e 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt @@ -92,20 +92,12 @@ class ScoreList { } var previousValue = 0.0 - val numericalUnknownDayValue = (targetValue * 2 * 1000) / denominator for (i in values.indices) { val offset = values.size - i - 1 if (isNumerical) { - if (values[offset] >= 0) - rollingSum += values[offset] - else if (numericalHabitType == NumericalHabitType.AT_MOST) - rollingSum += numericalUnknownDayValue + rollingSum += max(0, values[offset]) if (offset + denominator < values.size) { - if (values[offset + denominator] >= 0) { - rollingSum -= values[offset + denominator] - } else if (numericalHabitType == NumericalHabitType.AT_MOST) { - rollingSum -= numericalUnknownDayValue - } + rollingSum -= max(0, values[offset + denominator]) } var percentageCompleted = 0.0 diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index f1c05861c..7c97cbc72 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -115,10 +115,8 @@ class HistoryCardPresenter( } } else { entries.map { - if (it.value < 0) habit.targetValue * 2.0 * 1000.0 else it.value / 1000.0 - }.map { when { - it <= habit.targetValue -> HistoryChart.Square.ON + max(0, it.value) < 2 * habit.targetValue -> HistoryChart.Square.ON else -> HistoryChart.Square.OFF } } From fe1d5c66cbafd889dfc494124ee4288cae1f4615 Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Sun, 12 Sep 2021 16:23:42 +0300 Subject: [PATCH 022/132] fix bug in history card --- .../uhabits/core/ui/screens/habits/show/views/HistoryCard.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index 7c97cbc72..8798f027d 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -116,7 +116,7 @@ class HistoryCardPresenter( } else { entries.map { when { - max(0, it.value) < 2 * habit.targetValue -> HistoryChart.Square.ON + max(0.0, it.value / 1000.0) < 2 * habit.targetValue -> HistoryChart.Square.ON else -> HistoryChart.Square.OFF } } From 65d237254c945f8f02b6c921dc0ae3df1d01ee62 Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Sun, 12 Sep 2021 16:56:08 +0300 Subject: [PATCH 023/132] simplify scoring code --- .../org/isoron/uhabits/core/models/ScoreList.kt | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt index f96d7857e..a062f7ede 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt @@ -100,19 +100,18 @@ class ScoreList { rollingSum -= max(0, values[offset + denominator]) } - var percentageCompleted = 0.0 val normalizedRollingSum = rollingSum / 1000 - if (numericalHabitType == NumericalHabitType.AT_LEAST) { - percentageCompleted = if (targetValue > 0) + val percentageCompleted = if (numericalHabitType == NumericalHabitType.AT_LEAST) { + if (targetValue > 0) min(1.0, normalizedRollingSum / targetValue) else 1.0 - } else if (numericalHabitType == NumericalHabitType.AT_MOST) { - percentageCompleted = if (targetValue > 0 && normalizedRollingSum > targetValue) - max( - 0.0, 1 - ((normalizedRollingSum - targetValue) / targetValue) - ) - else if (normalizedRollingSum <= targetValue) 1.0 else 0.0 + } else { + if (targetValue > 0) { + (1 - ((normalizedRollingSum - targetValue) / targetValue)).coerceIn(0.0, 1.0) + } else { + if (normalizedRollingSum > 0) 0.0 else 1.0 + } } previousValue = compute(freq, previousValue, percentageCompleted) From 9d3c63cf62822331185a847f34f288adb433888d Mon Sep 17 00:00:00 2001 From: sgallese Date: Sat, 18 Sep 2021 23:05:48 -0700 Subject: [PATCH 024/132] Removes JVM dependencies from StringUtils See Issue #1075 --- .../org/isoron/uhabits/widgets/StackWidget.kt | 2 +- .../uhabits/widgets/StackWidgetService.kt | 2 +- .../org/isoron/platform/utils/StringUtils.kt | 30 ++++++++ .../isoron/platform/utils/StringUtilsTest.kt | 39 +++++++++++ .../isoron/uhabits/core/models/WeekdayList.kt | 8 +-- .../uhabits/core/preferences/Preferences.kt | 4 +- .../isoron/uhabits/core/utils/StringUtils.kt | 68 ------------------- .../uhabits/core/models/WeekdayListTest.kt | 14 ++++ 8 files changed, 88 insertions(+), 79 deletions(-) create mode 100644 uhabits-core/src/commonMain/kotlin/org/isoron/platform/utils/StringUtils.kt create mode 100644 uhabits-core/src/commonTest/kotlin/org/isoron/platform/utils/StringUtilsTest.kt delete mode 100644 uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/StringUtils.kt diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt index deed570ac..fa6452a0e 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt @@ -26,8 +26,8 @@ import android.content.Intent import android.net.Uri import android.view.View import android.widget.RemoteViews +import org.isoron.platform.utils.StringUtils import org.isoron.uhabits.core.models.Habit -import org.isoron.uhabits.core.utils.StringUtils class StackWidget( context: Context, diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt index 0e60914e5..dc86b9b66 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.kt @@ -27,11 +27,11 @@ import android.util.Log import android.widget.RemoteViews import android.widget.RemoteViewsService import android.widget.RemoteViewsService.RemoteViewsFactory +import org.isoron.platform.utils.StringUtils.Companion.splitLongs import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.HabitNotFoundException import org.isoron.uhabits.core.preferences.Preferences -import org.isoron.uhabits.core.utils.StringUtils.Companion.splitLongs import org.isoron.uhabits.utils.InterfaceUtils.dpToPixels import java.util.ArrayList diff --git a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/utils/StringUtils.kt b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/utils/StringUtils.kt new file mode 100644 index 000000000..8f3cf62d0 --- /dev/null +++ b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/utils/StringUtils.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016-2021 Álinson Santos Xavier + * + * 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 . + */ + +package org.isoron.platform.utils + +class StringUtils { + + companion object { + + fun joinLongs(values: LongArray): String = values.joinToString(separator = ",") + + fun splitLongs(str: String): LongArray = str.split(",").map { it.toLong() }.toLongArray() + } +} diff --git a/uhabits-core/src/commonTest/kotlin/org/isoron/platform/utils/StringUtilsTest.kt b/uhabits-core/src/commonTest/kotlin/org/isoron/platform/utils/StringUtilsTest.kt new file mode 100644 index 000000000..a92219f5f --- /dev/null +++ b/uhabits-core/src/commonTest/kotlin/org/isoron/platform/utils/StringUtilsTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016-2021 Álinson Santos Xavier + * + * 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 . + */ + +package org.isoron.platform.utils + +import kotlin.test.Test +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals + +class StringUtilsTest { + + @Test + fun testJoinLongs() { + val string = StringUtils.joinLongs(longArrayOf(0, 1, 2)) + assertEquals(string, "0,1,2") + } + + @Test + fun testSplitLongs() { + val longArray = StringUtils.splitLongs("0,1,2") + assertContentEquals(longArray, longArrayOf(0, 1, 2)) + } +} diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/WeekdayList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/WeekdayList.kt index f104cb32b..55dfa3b9b 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/WeekdayList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/WeekdayList.kt @@ -20,8 +20,6 @@ package org.isoron.uhabits.core.models import org.apache.commons.lang3.builder.EqualsBuilder import org.apache.commons.lang3.builder.HashCodeBuilder -import org.apache.commons.lang3.builder.ToStringBuilder -import org.isoron.uhabits.core.utils.StringUtils.Companion.defaultToStringStyle import java.util.Arrays class WeekdayList { @@ -71,11 +69,7 @@ class WeekdayList { return HashCodeBuilder(17, 37).append(weekdays).toHashCode() } - override fun toString(): String { - return ToStringBuilder(this, defaultToStringStyle()) - .append("weekdays", weekdays) - .toString() - } + override fun toString() = "{weekdays: [${weekdays.joinToString(separator = ",")}]}" companion object { val EVERY_DAY = WeekdayList(127) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/preferences/Preferences.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/preferences/Preferences.kt index 66d255d3c..6e6f6f85a 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/preferences/Preferences.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/preferences/Preferences.kt @@ -19,12 +19,12 @@ package org.isoron.uhabits.core.preferences import org.isoron.platform.time.DayOfWeek +import org.isoron.platform.utils.StringUtils.Companion.joinLongs +import org.isoron.platform.utils.StringUtils.Companion.splitLongs import org.isoron.uhabits.core.models.HabitList import org.isoron.uhabits.core.models.Timestamp import org.isoron.uhabits.core.ui.ThemeSwitcher import org.isoron.uhabits.core.utils.DateUtils.Companion.getFirstWeekdayNumberAccordingToLocale -import org.isoron.uhabits.core.utils.StringUtils.Companion.joinLongs -import org.isoron.uhabits.core.utils.StringUtils.Companion.splitLongs import java.util.LinkedList import kotlin.math.max import kotlin.math.min diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/StringUtils.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/StringUtils.kt deleted file mode 100644 index a65cf4241..000000000 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/StringUtils.kt +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2016-2021 Álinson Santos Xavier - * - * 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 . - */ - -package org.isoron.uhabits.core.utils - -import org.apache.commons.lang3.builder.StandardToStringStyle -import org.apache.commons.lang3.builder.ToStringStyle -import java.math.BigInteger -import java.util.Random - -class StringUtils { - - companion object { - private lateinit var toStringStyle: StandardToStringStyle - - @JvmStatic - fun getRandomId(): String { - return BigInteger(260, Random()).toString(32).subSequence(0, 32).toString() - } - - @JvmStatic - fun defaultToStringStyle(): ToStringStyle { - toStringStyle = StandardToStringStyle() - toStringStyle.apply { - fieldSeparator = ", " - isUseClassName = false - isUseIdentityHashCode = false - contentStart = "{" - contentEnd = "}" - fieldNameValueSeparator = ": " - arrayStart = "[" - arrayEnd = "]" - } - - return toStringStyle - } - - @JvmStatic - fun joinLongs(values: LongArray): String { - return org.apache.commons.lang3.StringUtils.join(values, ',') - } - - @JvmStatic - fun splitLongs(str: String): LongArray { - val parts: Array = org.apache.commons.lang3.StringUtils.split(str, ',') - return LongArray(parts.size) { - i -> - parts[i].toLong() - } - } - } -} diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/WeekdayListTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/WeekdayListTest.kt index 8bcde06fb..9d622d540 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/WeekdayListTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/WeekdayListTest.kt @@ -44,4 +44,18 @@ class WeekdayListTest : BaseUnitTest() { assertTrue(list.isEmpty) assertFalse(WeekdayList.EVERY_DAY.isEmpty) } + + @Test + fun testWeekdayList_IntConstructor_toString() { + val string = WeekdayList(0).toString() + assertThat(string, equalTo("{weekdays: [false,false,false,false,false,false,false]}")) + } + + @Test + fun testWeekdayList_BooleanArrayConstructor_toString() { + val string = WeekdayList( + booleanArrayOf(false, false, true, true, true, true, true) + ).toString() + assertThat(string, equalTo("{weekdays: [false,false,true,true,true,true,true]}")) + } } From b2951a3475e1484fdf9d9399dd38e952bebd3c9f Mon Sep 17 00:00:00 2001 From: sgallese Date: Sun, 19 Sep 2021 06:48:01 -0700 Subject: [PATCH 025/132] Place MidnightTimer under test --- .../uhabits/core/utils/MidnightTimer.kt | 6 +-- .../org/isoron/uhabits/core/BaseUnitTest.kt | 8 ++-- .../core/reminders/ReminderSchedulerTest.kt | 2 +- .../uhabits/core/utils/MidnightTimerTest.kt | 45 +++++++++++++++++++ 4 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt index e0661ba77..3dbba72c5 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt @@ -39,11 +39,11 @@ open class MidnightTimer @Inject constructor() { @Synchronized fun onPause(): MutableList? = executor.shutdownNow() - @Synchronized fun onResume() { - executor = Executors.newSingleThreadScheduledExecutor() + @Synchronized fun onResume(delayOffsetInMillis: Long = DateUtils.MINUTE_LENGTH, testExecutor: ScheduledExecutorService? = null) { + executor = testExecutor ?: Executors.newSingleThreadScheduledExecutor() executor.scheduleAtFixedRate( { notifyListeners() }, - DateUtils.millisecondsUntilTomorrowWithOffset() + 1000, + DateUtils.millisecondsUntilTomorrowWithOffset() + delayOffsetInMillis, DateUtils.DAY_LENGTH, TimeUnit.MILLISECONDS ) diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/BaseUnitTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/BaseUnitTest.kt index f97991b6d..4079600ab 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/BaseUnitTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/BaseUnitTest.kt @@ -95,15 +95,13 @@ open class BaseUnitTest { } fun unixTime(year: Int, month: Int, day: Int): Long { - val cal = getStartOfTodayCalendar() - cal.set(year, month, day, 0, 0, 0) - return cal.timeInMillis + return unixTime(year, month, day, 0, 0) } - open fun unixTime(year: Int, month: Int, day: Int, hour: Int, minute: Int): Long { + open fun unixTime(year: Int, month: Int, day: Int, hour: Int, minute: Int, milliseconds: Long = 0): Long { val cal = getStartOfTodayCalendar() cal.set(year, month, day, hour, minute) - return cal.timeInMillis + return cal.timeInMillis + milliseconds } fun timestamp(year: Int, month: Int, day: Int): Timestamp { diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.kt index d354e81f0..cf81fbe9a 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.kt @@ -138,7 +138,7 @@ class ReminderSchedulerTest : BaseUnitTest() { reminderScheduler.schedule(habit) } - override fun unixTime(year: Int, month: Int, day: Int, hour: Int, minute: Int): Long { + override fun unixTime(year: Int, month: Int, day: Int, hour: Int, minute: Int, milliseconds: Long): Long { val cal: Calendar = getStartOfTodayCalendar() cal[year, month, day, hour] = minute return cal.timeInMillis diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt new file mode 100644 index 000000000..80a90edb9 --- /dev/null +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt @@ -0,0 +1,45 @@ +package org.isoron.uhabits.core.utils + +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext +import org.isoron.uhabits.core.BaseUnitTest +import org.junit.Test +import java.util.Calendar +import java.util.TimeZone +import java.util.concurrent.Executors +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine +import kotlin.test.assertEquals + +class MidnightTimerTest : BaseUnitTest() { + + @Test + fun testMidnightTimer_notifyListener_atMidnight() = runBlocking { + // Given + val executor = Executors.newSingleThreadScheduledExecutor() + val dispatcher = executor.asCoroutineDispatcher() + + withContext(dispatcher) { + DateUtils.setFixedTimeZone(TimeZone.getTimeZone("GMT")) + DateUtils.setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 1, 23, 59, DateUtils.MINUTE_LENGTH - 1)) + + val suspendedListener = suspendCoroutine { continuation -> + val listener = object : MidnightTimer.MidnightListener { + override fun atMidnight() { + continuation.resume(true) + } + } + + MidnightTimer().apply { + addListener(listener) + // When + onResume(1, executor) + } + } + + // Then + assertEquals(true, suspendedListener) + } + } +} From 3e6a9181d6d836a85984bf166a57e676438ef3f0 Mon Sep 17 00:00:00 2001 From: sgallese Date: Tue, 21 Sep 2021 19:16:00 -0700 Subject: [PATCH 026/132] Code review- keep timer offset to one second --- .../java/org/isoron/uhabits/core/utils/DateUtils.kt | 7 ++++++- .../java/org/isoron/uhabits/core/utils/MidnightTimer.kt | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/DateUtils.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/DateUtils.kt index fd7929b87..8af545504 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/DateUtils.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/DateUtils.kt @@ -36,10 +36,15 @@ abstract class DateUtils { private var startDayHourOffset: Int = 0 private var startDayMinuteOffset: Int = 0 + /** + * Number of milliseconds in one second. + */ + const val SECOND_LENGTH: Long = 1000 + /** * Number of milliseconds in one minute. */ - const val MINUTE_LENGTH: Long = 60 * 1000 + const val MINUTE_LENGTH: Long = 60 * SECOND_LENGTH /** * Number of milliseconds in one hour. diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt index 3dbba72c5..5ae0b6ad7 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt @@ -39,7 +39,7 @@ open class MidnightTimer @Inject constructor() { @Synchronized fun onPause(): MutableList? = executor.shutdownNow() - @Synchronized fun onResume(delayOffsetInMillis: Long = DateUtils.MINUTE_LENGTH, testExecutor: ScheduledExecutorService? = null) { + @Synchronized fun onResume(delayOffsetInMillis: Long = DateUtils.SECOND_LENGTH, testExecutor: ScheduledExecutorService? = null) { executor = testExecutor ?: Executors.newSingleThreadScheduledExecutor() executor.scheduleAtFixedRate( { notifyListeners() }, From a29943e783b0f727b19414d69e559451694bbc52 Mon Sep 17 00:00:00 2001 From: sgallese Date: Tue, 21 Sep 2021 19:20:54 -0700 Subject: [PATCH 027/132] Simplify midnight timer interface for testing --- .../java/org/isoron/uhabits/core/utils/MidnightTimer.kt | 2 +- .../org/isoron/uhabits/core/utils/MidnightTimerTest.kt | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt index 5ae0b6ad7..49c088ca7 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt @@ -57,7 +57,7 @@ open class MidnightTimer @Inject constructor() { } } - interface MidnightListener { + fun interface MidnightListener { fun atMidnight() } } diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt index 80a90edb9..6e80ca0b4 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt @@ -25,14 +25,8 @@ class MidnightTimerTest : BaseUnitTest() { DateUtils.setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 1, 23, 59, DateUtils.MINUTE_LENGTH - 1)) val suspendedListener = suspendCoroutine { continuation -> - val listener = object : MidnightTimer.MidnightListener { - override fun atMidnight() { - continuation.resume(true) - } - } - MidnightTimer().apply { - addListener(listener) + addListener { continuation.resume(true) } // When onResume(1, executor) } From 508200abeb70266bd8286dbc543de64b73a1c2fc Mon Sep 17 00:00:00 2001 From: sgallese Date: Tue, 21 Sep 2021 19:25:21 -0700 Subject: [PATCH 028/132] Format classes with ktlint --- .../isoron/uhabits/core/utils/MidnightTimer.kt | 18 +++++++++++++----- .../uhabits/core/utils/MidnightTimerTest.kt | 11 ++++++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt index 49c088ca7..903099293 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/MidnightTimer.kt @@ -33,13 +33,19 @@ open class MidnightTimer @Inject constructor() { private val listeners: MutableList = LinkedList() private lateinit var executor: ScheduledExecutorService - @Synchronized fun addListener(listener: MidnightListener) { + @Synchronized + fun addListener(listener: MidnightListener) { this.listeners.add(listener) } - @Synchronized fun onPause(): MutableList? = executor.shutdownNow() + @Synchronized + fun onPause(): MutableList? = executor.shutdownNow() - @Synchronized fun onResume(delayOffsetInMillis: Long = DateUtils.SECOND_LENGTH, testExecutor: ScheduledExecutorService? = null) { + @Synchronized + fun onResume( + delayOffsetInMillis: Long = DateUtils.SECOND_LENGTH, + testExecutor: ScheduledExecutorService? = null + ) { executor = testExecutor ?: Executors.newSingleThreadScheduledExecutor() executor.scheduleAtFixedRate( { notifyListeners() }, @@ -49,9 +55,11 @@ open class MidnightTimer @Inject constructor() { ) } - @Synchronized fun removeListener(listener: MidnightListener) = this.listeners.remove(listener) + @Synchronized + fun removeListener(listener: MidnightListener) = this.listeners.remove(listener) - @Synchronized private fun notifyListeners() { + @Synchronized + private fun notifyListeners() { for (l in listeners) { l.atMidnight() } diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt index 6e80ca0b4..b92507da0 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/utils/MidnightTimerTest.kt @@ -22,7 +22,16 @@ class MidnightTimerTest : BaseUnitTest() { withContext(dispatcher) { DateUtils.setFixedTimeZone(TimeZone.getTimeZone("GMT")) - DateUtils.setFixedLocalTime(unixTime(2017, Calendar.JANUARY, 1, 23, 59, DateUtils.MINUTE_LENGTH - 1)) + DateUtils.setFixedLocalTime( + unixTime( + 2017, + Calendar.JANUARY, + 1, + 23, + 59, + DateUtils.MINUTE_LENGTH - 1 + ) + ) val suspendedListener = suspendCoroutine { continuation -> MidnightTimer().apply { From 4355fb4d687e7fed734b2a0635f274e0e86c1098 Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Wed, 22 Sep 2021 15:49:51 +0300 Subject: [PATCH 029/132] start score from 1.0 for at most and reflect the same in history --- .../NumberButtonView/render_at_most_above.png | Bin 2294 -> 2338 bytes .../list/NumberButtonView/render_zero.png | Bin 1856 -> 1939 bytes .../common/dialogs/HistoryEditorDialog.kt | 2 ++ .../habits/list/views/NumberButtonView.kt | 4 ++-- .../habits/show/views/HistoryCardView.kt | 1 + .../isoron/uhabits/widgets/HistoryWidget.kt | 5 ++++- .../core/commands/CreateHabitCommand.kt | 1 + .../org/isoron/uhabits/core/models/Habit.kt | 5 +++-- .../isoron/uhabits/core/models/ScoreList.kt | 7 +++---- .../screens/habits/show/views/HistoryCard.kt | 6 ++++++ .../uhabits/core/ui/views/HistoryChart.kt | 3 ++- .../uhabits/core/ui/views/HistoryChartTest.kt | 1 + 12 files changed, 25 insertions(+), 10 deletions(-) diff --git a/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_above.png b/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_at_most_above.png index 5bd20a34f244dd23221010487efa7e8ee62530e4..4cea804986c070e0879924ed281e4bb417a0e1dc 100644 GIT binary patch delta 2297 zcmaKudpy&N8^^yhq8p8{II>1=TT&6iL559XiZ0qtERoB?`mJ%$cjeNw&?e=6>1VE4 znz=S@mFp4exTNITw2-Kka>9;5 zN9E4t#@zHC&}kQr*`%4GnH+BgQgxyFK7}UR;?@u?J@P*9Be!tAhzQ+b@_oPbV`a52 zByw@4xdAD?`&08X(-!mLit+(G=|9>FuwkP;b=xb6eqK8VNRb)=Sy|Fq-I)2W6yoK( zud{55?Fz(!y|Xbr;qRYYe}4;Jx&Q|;7pfTr@;cIz6K|!n=X6J*-%HitR zr7tQyeSxQ&LeBNy^8$`T2nYK?XPzngi?Ah6A7sd`Bm;O)-t_aV1AC+MX~F!56lx?s zU3nWTdFsRJ*#&n=m!Y+e=v>C1t&UYLq6GX8INbtD)c-D@=7K?MDC!)JIIs}I}%ie>g>cn5gBfK0t-l!Aq7vRQ`7aeGqX3 z^9fj}VSSjKB*7u`TU`;z6xNR;MGK!I@{i3(^#)qk$E1tbyB0XeQh1e>vjRP~I0%Vz zz2@NL^z0E!fO4&1GKXwL1?lY@B4Le#Qb9A4vMjm^4YKQv>86fwpxAbo$j$vE9fJ@-bjv6t8ACc|e$u9FbB8xV2-fPV`2FDEpz%cU#6bjdf;TloD$>wd&;&v;;*G#{XYu7OUK=Y{ ze%!N&LQV3wvZ&sBf^;_NQ0gT)k%r8~Kl}Z@UQqg2Wqb)w`7tq_3)>IZe|ElWp!IOo zogyf^S3=YKn#kJX=@>V`OFUd;PTXQfjrE2Q(FAXu7jNI@YO+QVrpO7!vh)dFlK;(3 zPlxNs+B)SXmdA*MmR}X3^Mm9v)mv~E_q$8s0H4n<#-?smR{?ijfA-CYdnss zFTf?Mcb=Zv@{f2uKM4I%{1IcHY)Rkr*R4ubzSvJHPmy1KZ%}1Rz{G*N!hExT*2*hmBkZ8 z9$mb}6mLzn34?)sVs^7c9d#lWK6s-e4#_jTw>fQ+hPz_; zCa|%|s;twbBQn>nGk^yZJ-`%i>s+h!hu3G9EDe|S)XnAk!!1E31BK*FaTrFh=o7}& z_~2|s6o(m~t@}qkpHEc5aRaqO-~ zK5gLUD43;)4|VZ=4pIA%KYyo@clgGnu|&Qya{8Frwwkjv!;&}iSmL%j;2{W{v$CzY1DzKsaGui>K$85tSzycMgo z<|tqsRjgJPZC57O{k)3sMoZKt?h299KM#q`6T@Y@)6Tb&K2I$! zE@p950^ld1r;bwWI!kdq8_em(u)SsIgDJaL3-bwu52S@ zA4aUy+1T9NYyb?^#WByH?i}xT!(6OEqo%ETb^;MZniky^0L3`dT68F(2!CN4iww*# zTPK~M=Jq+_5j#7(b6Q$jZE{f}Pg$KL`W3M(W#C?g4gz@zpo^uIC#sfh0IO8#LAtB6 zIDzpT&X?0=mw*XF>s+Nf2vxie<&BOPgzWkF;X_$k$K_LZYR|uGOEF3B%&kSwUV$w^ zmrF;6Q6TwTqc>H3`;RqfW#Hi3U4oe#b>~iUg{x%g>sXjQyM;b*TAsh9%BwylU4P&eYm;YyP{nxaIFs?+Zh*0 zGLsYj42LvW#08g zv97ju>-P)<1c04Z84q2z=d(L1*dq1aGs#}Nw7ZaXhW@e*uWok-TB11lyQ0CZox0Eq zT1mF2n8M)GgFUd!$V3^faOD}6jAmA(0xJkGKQ>*QrW(BhsgfHVB>VYB3i-ad&&Z7h+i(-Q9nf~8qW~h995dHUR>GO` z(X)w#g4w1tmO$<2ys{8WS?4r-Nj4FnNmp1~f!e$j)|x4bVqw_SXLpLH5)V)0m6VjwdQNgHD^bx4<4=0kHzoes9=Yf`zgb5|=Ud`o z|7?E>{NwDb&3590>n@_b>M7jox8+rv8^uef!~5C=#r`+> zMK2@}3m2M0%2L5B0JGj$cs&3eWBo59`rjwv^jTM8$+w8G9#RI@1Ly34;U4z8_7|kd BVmbf- delta 2253 zcmaJ@dpOe#8~)8PY9VvZp|wzHN^*D|qBdbkSm|XGwU+Z?ms7}Z_;Q*Yrf3MsM8YeS zZ8;xCsnO>w=CGIV-AD*Ay*~Z*y?=erKhHnUeO>qUT+e;qPsyPTxlC)Y*bZfljVxFy zh)%=0stiewEHhe67pA~9OVJy8ij=Nfwg0af9(XfOj*`n#ar1lJOE6ekTKX;b1Kz)^ z`uF-$p#Ag?4u4X{EXGh>MJeY6P{lX>M~?)4@n zajt&0%n25j6(a=KErD?dd_jsN5CaL(76E$403#?A`jheEg^p`~I$ z3(QkBNk99f(ag+@lkWw;)m`P9D_x;v1w-S{c~sgeUR{#SBp8#6{Hh{`I`e%zl9LgE z)T2aYyR(5!OsqE=k~YG%%<$DGz~r{v7&wnxkq&frx6~Jx0s0009=RG|RD4=o&J<0e zIQt^WXdoV;(fh`pzPeSvgvlRdfzKu-brw zVw_qs&^9#i{8G^A4%>sOx$AuABkL!04|J%*Zyk&bKS|#Pifd|W?t6QCgN6xx?OONR z`^f}@2V{FXiK0T>SQiY@(I-`B&H);iE#a#(2!C(y{~(nu-*% z@OZbcn|bt4o*I9jCjc%Pp;l+J)ix&6l+o zo0x{)cKW(SoE9-pD0u;rMms2*r2*tya3tP$$@=HvBA#m$@ut=T+4GQ?Q@+xmhZB9TIDE zK`22+D;{m*E0^pNau%UalOr87Wv11u-W)qM<@0)ys1O;I9qBHTo9Tc0~Zr+QF2b=fJ0w9%{;vs}@6nj3E^{^PP&BNj)J2 z`jBK4PjscExff$!VS%_rVthf<2g9+IdZ|4+ssXo~3|Vrq>g5{Lez%OTsT=pf7tX$g z%R+Z;+NWr6ZaJas?z5{V($k3EzCSAo}S($Dk>_I zwI~+6CnEM?_Lj9}Q4wFFywpAFu5u#fBUv}qU?s3)%eBH+>z?`4Q_Cpl*KxnVTrv(h zq7U~&^Lzkx`0D@yq4cm=+ih#v%k-L}#fjZ=Fxmg?c|?#1KwTQ?*Fi*|zvMV;*x$|c z-Zm*_v4o||!cAs1OS)Ab)p?BZfH&h@!E-dA5jwu^-Ep_DvD!U)O29{<3|1oOzu5X7 zooS4lz@2!UgLbNyX+7lxyD!>0FYrMVG7+{p=A3AfDp5}ipw2bO{QGsSN8UCl;avq* zHCUE3H0!UNgh|(=_GIiuM)%;t{K_-c^sbqcI{S)XaH`=vo8M47V8~L7f($X9o=N&T z+jhvd+2bffS;)o8?=no9gb7;8F8kaBlWu~d;i-Jycwu2-m(4pf;EP;RlL=H!&EDk& zJYK6&p|$M?wp8MqBVa6g1C#_1%j@PrHxJ$PYf@_c3I8lJtywLIHH}rh>s_^LLqhLJ zs_BcGJoMfCZUHB0=YLcrF>o!zQO0C^h{djUFIV)*QMh2%dcupdmXn>vuiYcL4*hn2 z_Z&OK5(z&BNDmz+uLFNOthSA7&YOISfPC))hii|R8riQJkf9(Do8rp~QzCPK8zG({;M1& diff --git a/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_zero.png b/uhabits-android/src/androidTest/assets/views/habits/list/NumberButtonView/render_zero.png index 5f6bf8c65cf649ef2b9f437feaea7fed323ec774..a405c0092d9cc66fdd53d00eba078fe57112d507 100644 GIT binary patch delta 1924 zcmZuyX;jjA7yf|@wrS{?xrW5#R9J&c*{EeoBiPY#tEk);oJ>q9MRWN(c1kKn1>4lp z8kfQtN==NN}mp6rselD7Q3XNPX$cob#UZ-VgV~J@>dRCwoF;R3FX+A zqkioN)}tW?Xe3I-p4rW zwFagCJJ#FjTvW)@qQeEwjWUQZoWgzPKMJ?^w1nd$HfrLfX}`GqbhL>>MvyK{Zihx4 zHUL60m`Tyw=y){oXRpXex!-VeH<1em$kO{*)z83zf%}COW|3wtYS<=krA^Drucpri zJHs1>K74*!VgfK)+wM$p>h)O6bYWTzJ-c-U@-C|kPAB-rEEd&|PrMn17`V#gq1XPl;e!8!lbK=U=3XM( z5~j({Whs9n4U|zIW;2v-dB4|x?&PZMC@F1qHMIahC^U^OV3N#;UB0uem`C!-FcGs3 zo>8$g`tZvI^qY%z8wOA-~@40 zFUkzi1%|*AR9IR;R*C0%6utXZPPaqw&G13wxz{7vfpRqz#n9;Gl@qw8%yiIlMKo?< zXlTeS)1JkuoPaxVYNJM9co)X8AA%{CnvP4C>Yg&vf~0W$y(yl;@_ou`%CL2qlw!eL zK+o9;9ZO0|j6p^P?Tm_-KAwD)KJtOb4gcZ0LXZbdYgI505Oq%J$W=wGKNlT;xtC>Ai^0jYpaIh|HTZ>gkc#u||kNS(swp7({4c0PyfY;nRu~_^F=5;GD!>r>B zni`DXQIUo~vI0)2>XmNdD$uJlgn|D4hCMv%=JwDnP2bz43({l-r?ayBcUM-XhpPi1 zq{fVF(kkbqbtS%7z|xg_s-94u#LSu%j(ybw9+Fmzj`oYPB6^bj3LxnoR(}{eIig-{ zA#$C&vJE>TV~R8qkJg{`6=joaLk1Wx>W;(k${-dEe0hL-OIoXM((~+@hYrQ!k|}Kg z2T+EecLa=o@Si>zqNj`02;G}fHy($S!R?$Q5&PQd; zDE>YpGzq)zAJ1Q=!A9(s(U~~i0Snf>I*%i-1O)NIpV3`)&ljlD#bQ|EK|(t>d^$1mJBZ(57UkwZi3#d`-|*>q=~QA&P$ z`03-Wgi`4;`9Y4#X(OeOUldwi|MLA2z`9LLFaA*2a#0Z9_j&C6XA^)b5r$nFl$iC! z(B>ko3mVUIZdu^p$o*n4u`xTbDDS&7mV^1!N3=A)-fN!GjON- zM(oj;hdNvdTNZUNt|=)XKqo9^Zg=V^eaZQ0BjB1diJ$DgfR z^L6K5pB6Q^xw;O}#B6J)redsD z<0mYB8sSp9?xs-O3a1M;gIJ6;)zSBV6D!ev+2BZWU}1F#IIoLYK-?FA=Xyuw{}%(< BuiO9t delta 1841 zcmaJ?c{JOJ7XFdMQXQm2>9nOa(<-f?v9;DX(IQbPQc6>lT02$yQk9tLSR127V{h$G zNKk@U)3H}-Yh$U3Xe}j0FliLwWzPHSo%7E7{<(kMd%t_X@7$Xq$B<3`1rH9jv~iLW zAy&#e2>>JnHb{h1RQ_r{?%oM!#XkJfP_J|y$^qkAG!FG|Gmd-}Y&O#n+o*xnd<^hW z6pVl6=3l5%OgaYB<1BTg4X`xf9l`P(vYr!cp_bSW7$|08q}#g{-Wu}LKtpEnV}l;M zy2vG7ZT*1vf*zZOk2L&o=7nDF!(r2ot=UVV>mTW%eVhkICu9@5=KfEp^Rw=RguU6` z-hTG_H6m|tA!P8mmP}$|;_x>&M|E!)Q0Cy@ztyG+xC1xNE=Ce6xcr^9J9XPJ2k&Y2 z<>Kl2d%rV?O2IjJ=0eEy)hk!ZV=4nrXUEC-CC-K@4QSc>W9aVS*ngGXYuHUWns@=?5q`ObeBg&K_x1I)Z^*>Wp2x|Yfs0{S zMPY1Z_ze2bw6sDSQgT0}g9Oi!25R*Ru48{Kw<={jM8vNzpnb$&l2@NhUWB&{q5-PY z#UBCaDC%KB$;sJ{XJr7hVSYFqP7ZK=vp?~lx&Zr{?^`hY;Fv|Ch<6VV{(92S7&D$s|z38Yu;9u%Rs{U2I{3*m_O zTz-w%LZ(eKZ@zObnoW9G72xTui3fV_Y=pr`t%_0N)^aE>PP7-3@;%lJE;RS9ma%oD z+;Hv*jx8a>uCu%l^7&tz&i*C~uvFemAMLMY6%N;{h~NQER-Og@TnimZhd6aSMV5DhM;ncNep4 z7vRAs%+=Jau#_`#yVW%O{hiFg1?}Yi-^n}8NobIJQC*l&ftR_yJ9{5zW2j1;DdytR zbr+98=>@&{LVs+#nDU0ndWoZ><8*?^ljN179G{`4em+2s39l~8c7rezvpbv?{?vx~iH z62x?EwM8}pK>)X+q9RhvCD7c5!Z$i-4+H7&xB2tzsX zsXgP98Z#Zz2gXxDhq@lvy;BCiRta2vb4p4j*VpuThH$Q-4s$La*vCuH`}q1cl@223 zJ44@x>P+q8Mkb-Sc1b3axp&9Ig9G)@e{dnCxbKOsIdf@i6_y_$i!xWV8ns5Ua7yz1J45s~>@Mc4H*`aC{#Wi$uo#aG1P8jcLD4EdEj#LjO4A(n)6@gpymT z?zSGaKt6w4Qn;8qijRl+eNCd8OS%NQZ#_D=kDZY)fkcsa(v#3mnpqx&EInuAbH-5eU_fp8DKU zT1a1$lVOPl`c=$RdEel07pY69t;v5-wBX8>Kc9Vt;DymU^(A_0As01fFFQvczlUCl zE^{QN+BGE>t&e0+PvtbK%b`Y;11na2GlVoP{+^kQ83snuma9K zNua9~TAnehc`}R!0V8;kUd#duNUdHu&F=VLGnKaDjnoB3Dg)2Y1<<(h83=hN z*rKy$mV`(>J4UOBX;M=6^5($6fFc|Y&$B|B3|BR#P2_1=Amf&H_kB@iV*y@I_$EPQ z%(+sfZxPj_8!EpDz#{#Z;{tQ!)*e~B2p0PScfJD*jby(xW(A#=P1O7!Uj{gkRCqB8 Tp&gmy0wUO0T|-hWJ%0N)amSc; 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 fcad26125..5edae637f 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 @@ -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 { }, @@ -101,6 +102,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { theme = LightTheme() ) chart?.series = model.series + chart?.defaultSquare = model.defaultSquare dataView.postInvalidate() } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt index 08685026d..405bf606d 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt @@ -162,14 +162,14 @@ class NumberButtonView( fun draw(canvas: Canvas) { var activeColor = if (targetType == NumericalHabitType.AT_LEAST) { when { + value < 0.0 && preferences.areQuestionMarksEnabled -> lowContrast max(0.0, value) >= threshold -> color - value <= 0 -> lowContrast else -> mediumContrast } } else { when { + value < 0.0 && preferences.areQuestionMarksEnabled -> lowContrast value <= threshold -> color - value >= 2 * threshold -> lowContrast else -> mediumContrast } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt index c60e84bd1..f429e1718 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt @@ -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() diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt index 2e26a487b..c8d4dce44 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt @@ -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 } } @@ -71,6 +73,7 @@ class HistoryWidget( dateFormatter = JavaLocalDateFormatter(Locale.getDefault()), firstWeekday = prefs.firstWeekday, series = listOf(), + defaultSquare = HistoryChart.Square.OFF, ) } ).apply { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/CreateHabitCommand.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/CreateHabitCommand.kt index 49e3bae7a..8ff21f407 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/CreateHabitCommand.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/CreateHabitCommand.kt @@ -31,5 +31,6 @@ data class CreateHabitCommand( val habit = modelFactory.buildHabit() habit.copyFrom(model) habitList.add(habit) + habit.recompute() } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt index a2dd13846..5134d45b0 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt @@ -90,9 +90,10 @@ data class Habit( isNumerical = isNumerical, ) - val to = DateUtils.getTodayWithOffset().plus(30) + val today = DateUtils.getTodayWithOffset() + val to = today.plus(30) val entries = computedEntries.getKnown() - var from = entries.lastOrNull()?.timestamp ?: to + var from = entries.lastOrNull()?.timestamp ?: today if (from.isNewerThan(to)) from = to scores.recompute( diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt index a062f7ede..23bd88fd1 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt @@ -75,13 +75,12 @@ class ScoreList { to: Timestamp, ) { map.clear() - if (computedEntries.getKnown().isEmpty()) return - if (from.isNewerThan(to)) return var rollingSum = 0.0 var numerator = frequency.numerator var denominator = frequency.denominator val freq = frequency.toDouble() val values = computedEntries.getByInterval(from, to).map { it.value }.toIntArray() + val isAtMost = numericalHabitType == NumericalHabitType.AT_MOST // For non-daily boolean habits, we double the numerator and the denominator to smooth // out irregular repetition schedules (for example, weekly habits performed on different @@ -91,7 +90,7 @@ class ScoreList { denominator *= 2 } - var previousValue = 0.0 + var previousValue = if (isNumerical && isAtMost) 1.0 else 0.0 for (i in values.indices) { val offset = values.size - i - 1 if (isNumerical) { @@ -101,7 +100,7 @@ class ScoreList { } val normalizedRollingSum = rollingSum / 1000 - val percentageCompleted = if (numericalHabitType == NumericalHabitType.AT_LEAST) { + val percentageCompleted = if (!isAtMost) { if (targetValue > 0) min(1.0, normalizedRollingSum / targetValue) else diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index 8798f027d..dcc7cba24 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -45,6 +45,7 @@ data class HistoryCardState( val color: PaletteColor, val firstWeekday: DayOfWeek, val series: List, + val defaultSquare: HistoryChart.Square, val theme: Theme, val today: LocalDate, ) @@ -131,6 +132,10 @@ class HistoryCardPresenter( } } } + val defaultSquare = if (habit.isNumerical && habit.targetType == NumericalHabitType.AT_MOST) + HistoryChart.Square.ON + else + HistoryChart.Square.OFF return HistoryCardState( color = habit.color, @@ -138,6 +143,7 @@ class HistoryCardPresenter( today = today.toLocalDate(), theme = theme, series = series, + defaultSquare = defaultSquare ) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt index 699cc2ee6..f0da7a196 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt @@ -41,6 +41,7 @@ class HistoryChart( var firstWeekday: DayOfWeek, var paletteColor: PaletteColor, var series: List, + var defaultSquare: Square, var theme: Theme, var today: LocalDate, var onDateClickedListener: OnDateClickedListener = OnDateClickedListener { }, @@ -189,7 +190,7 @@ class HistoryChart( offset: Int, ) { - val value = if (offset >= series.size) Square.OFF else series[offset] + val value = if (offset >= series.size) defaultSquare else series[offset] val squareColor: Color val color = theme.color(paletteColor.paletteIndex) squareColor = when (value) { diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt index bce63bcec..a53135f9b 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt @@ -49,6 +49,7 @@ class HistoryChartTest { dateFormatter = JavaLocalDateFormatter(Locale.US), firstWeekday = SUNDAY, onDateClickedListener = dateClickedListener, + defaultSquare = OFF, series = listOf( 2, // today 2, 1, 2, 1, 2, 1, 2, From 17ed85fc1b5f666f718953709fd57606299c09ae Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Wed, 22 Sep 2021 16:18:50 +0300 Subject: [PATCH 030/132] fix test --- .../habits/list/NumberPanelView/render.png | Bin 7535 -> 6582 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/uhabits-android/src/androidTest/assets/views/habits/list/NumberPanelView/render.png b/uhabits-android/src/androidTest/assets/views/habits/list/NumberPanelView/render.png index 22584afb3d05a46822f721bc66137703c5203e49..a8571c3fac0e4785eb428f1a81c8a351ddfdd281 100644 GIT binary patch literal 6582 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 From 7de94f2caf8a2024c25239f9af35b25ff935494b Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Wed, 22 Sep 2021 16:42:40 +0300 Subject: [PATCH 031/132] Add border to create habit buttons --- uhabits-android/src/main/res/drawable/round_ripple.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/uhabits-android/src/main/res/drawable/round_ripple.xml b/uhabits-android/src/main/res/drawable/round_ripple.xml index 5131e5db5..f2f8d9189 100644 --- a/uhabits-android/src/main/res/drawable/round_ripple.xml +++ b/uhabits-android/src/main/res/drawable/round_ripple.xml @@ -23,6 +23,7 @@ android:color="?colorAccent"> + From 4aebeedec6898501a0671f32c70a239aeab45060 Mon Sep 17 00:00:00 2001 From: sgallese Date: Wed, 22 Sep 2021 20:06:41 -0700 Subject: [PATCH 032/132] Finish intro when skipped pressed --- .../org/isoron/uhabits/activities/intro/IntroActivity.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt index 7336bbd41..1a4288910 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt @@ -67,5 +67,8 @@ class IntroActivity : AppIntro2() { finish() } - override fun onSlideChanged() {} + override fun onSkipPressed(currentFragment: Fragment?) { + super.onSkipPressed(currentFragment) + finish() + } } From c79d1e82a59bc76755d2aa246cd7a0801808cbcc Mon Sep 17 00:00:00 2001 From: sgallese Date: Wed, 22 Sep 2021 20:07:01 -0700 Subject: [PATCH 033/132] Update AppIntro to latest version --- build.gradle.kts | 1 + uhabits-android/build.gradle.kts | 2 +- .../uhabits/activities/intro/IntroActivity.kt | 14 ++++++++------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 993a59a6c..3fc6fe5fd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,5 +20,6 @@ allprojects { maven(url = "https://oss.sonatype.org/content/repositories/snapshots/") maven(url = "https://kotlin.bintray.com/ktor") maven(url = "https://kotlin.bintray.com/kotlin-js-wrappers") + maven(url = "https://jitpack.io") } } diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 319a19f2f..ff936f6b9 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -105,7 +105,7 @@ dependencies { androidTestImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0") compileOnly("javax.annotation:jsr250-api:1.0") coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5") - implementation("com.github.paolorotolo:appintro:4.1.0") + implementation("com.github.AppIntro:AppIntro:6.1.0") implementation("com.google.code.findbugs:jsr305:3.0.2") implementation("com.google.dagger:dagger:$daggerVersion") implementation("com.google.guava:guava:30.1.1-android") diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt index 1a4288910..499694a90 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/intro/IntroActivity.kt @@ -21,8 +21,9 @@ package org.isoron.uhabits.activities.intro import android.graphics.Color import android.os.Bundle -import com.github.paolorotolo.appintro.AppIntro2 -import com.github.paolorotolo.appintro.AppIntroFragment +import androidx.fragment.app.Fragment +import com.github.appintro.AppIntro2 +import com.github.appintro.AppIntroFragment import org.isoron.uhabits.R /** @@ -30,7 +31,9 @@ import org.isoron.uhabits.R * launched for the first time. */ class IntroActivity : AppIntro2() { - override fun init(savedInstanceState: Bundle?) { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) showStatusBar(false) addSlide( @@ -61,9 +64,8 @@ class IntroActivity : AppIntro2() { ) } - override fun onNextPressed() {} - - override fun onDonePressed() { + override fun onDonePressed(currentFragment: Fragment?) { + super.onDonePressed(currentFragment) finish() } From 07e55f1c76abded6df2d18a1b8f3d3a15d5d217e Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Sun, 26 Sep 2021 22:58:24 +0300 Subject: [PATCH 034/132] modify review comments --- .../java/org/isoron/uhabits/core/models/Habit.kt | 10 ++++------ .../core/ui/screens/habits/show/views/HistoryCard.kt | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt index 5134d45b0..20c3d7949 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt @@ -59,10 +59,9 @@ data class Habit( val today = DateUtils.getTodayWithOffset() val value = computedEntries.get(today).value return if (isNumerical) { - val targetValuePerDay = (targetValue / frequency.denominator) when (targetType) { - NumericalHabitType.AT_LEAST -> value / 1000.0 >= targetValuePerDay - NumericalHabitType.AT_MOST -> value / 1000.0 <= targetValuePerDay + NumericalHabitType.AT_LEAST -> value / 1000.0 >= targetValue + NumericalHabitType.AT_MOST -> value / 1000.0 <= targetValue } } else { value != Entry.NO && value != Entry.UNKNOWN @@ -73,10 +72,9 @@ data class Habit( val today = DateUtils.getTodayWithOffset() val value = computedEntries.get(today).value return if (isNumerical) { - val targetValuePerDay = (targetValue / frequency.denominator) when (targetType) { - NumericalHabitType.AT_LEAST -> value / 1000.0 < targetValuePerDay - NumericalHabitType.AT_MOST -> value / 1000.0 > targetValuePerDay + NumericalHabitType.AT_LEAST -> value / 1000.0 < targetValue + NumericalHabitType.AT_MOST -> value / 1000.0 > targetValue } } else { value == Entry.NO diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index dcc7cba24..3ce83c8b3 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -117,7 +117,7 @@ class HistoryCardPresenter( } else { entries.map { when { - max(0.0, it.value / 1000.0) < 2 * habit.targetValue -> HistoryChart.Square.ON + max(0.0, it.value / 1000.0) <= habit.targetValue -> HistoryChart.Square.ON else -> HistoryChart.Square.OFF } } From d6a7fa3d7ad134b04b072b81c4cb0d075f3b8553 Mon Sep 17 00:00:00 2001 From: KristianTashkov Date: Mon, 27 Sep 2021 00:34:27 +0300 Subject: [PATCH 035/132] Add unit tests for numerical habits --- .../isoron/uhabits/core/test/HabitFixtures.kt | 13 + .../uhabits/core/models/ScoreListTest.kt | 245 ++++++++++++++++-- 2 files changed, 234 insertions(+), 24 deletions(-) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/test/HabitFixtures.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/test/HabitFixtures.kt index 38a34f0e1..fffe4ac85 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/test/HabitFixtures.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/test/HabitFixtures.kt @@ -50,6 +50,19 @@ class HabitFixtures(private val modelFactory: ModelFactory, private val habitLis return habit } + fun createEmptyNumericalHabit(targetType: NumericalHabitType): Habit { + val habit = modelFactory.buildHabit() + habit.type = HabitType.NUMERICAL + habit.name = "Run" + habit.question = "How many miles did you run today?" + habit.unit = "miles" + habit.targetType = targetType + habit.targetValue = 2.0 + habit.color = PaletteColor(1) + saveIfSQLite(habit) + return habit + } + fun createLongHabit(): Habit { val habit = createEmptyHabit() habit.frequency = Frequency(3, 7) diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/ScoreListTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/ScoreListTest.kt index ae2a8eedb..6ca3e2806 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/ScoreListTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/models/ScoreListTest.kt @@ -28,14 +28,36 @@ import org.junit.Before import org.junit.Test import java.util.ArrayList -class ScoreListTest : BaseUnitTest() { - private lateinit var habit: Habit - private lateinit var today: Timestamp +open class BaseScoreListTest : BaseUnitTest() { + protected lateinit var habit: Habit + protected lateinit var today: Timestamp + @Before @Throws(Exception::class) override fun setUp() { super.setUp() today = getToday() + } + + protected fun checkScoreValues(expectedValues: DoubleArray) { + var current = today + val scores = habit.scores + for (expectedValue in expectedValues) { + assertThat(scores[current].value, IsCloseTo.closeTo(expectedValue, E)) + current = current.minus(1) + } + } + + companion object { + const val E = 1e-6 + } +} + +class YesNoScoreListTest : BaseScoreListTest() { + @Before + @Throws(Exception::class) + override fun setUp() { + super.setUp() habit = fixtures.createEmptyHabit() } @@ -122,18 +144,6 @@ class ScoreListTest : BaseUnitTest() { checkScoreValues(expectedValues) } - @Test - fun test_withZeroTarget() { - habit = fixtures.createNumericalHabit() - habit.targetValue = 0.0 - habit.recompute() - assertTrue(habit.scores[today].value.isFinite()) - - habit.targetType = NumericalHabitType.AT_MOST - habit.recompute() - assertTrue(habit.scores[today].value.isFinite()) - } - @Test fun test_imperfectNonDaily() { // If the habit should be performed 3 times per week and the user misses 1 repetition @@ -259,17 +269,204 @@ class ScoreListTest : BaseUnitTest() { val entries = habit.originalEntries entries.add(Entry(today.minus(day), Entry.SKIP)) } +} - private fun checkScoreValues(expectedValues: DoubleArray) { - var current = today - val scores = habit.scores - for (expectedValue in expectedValues) { - assertThat(scores[current].value, IsCloseTo.closeTo(expectedValue, E)) - current = current.minus(1) - } +open class NumericalScoreListTest : BaseScoreListTest() { + protected fun addEntry(day: Int, value: Int) { + val entries = habit.originalEntries + entries.add(Entry(today.minus(day), value)) } - companion object { - private const val E = 1e-6 + protected fun addEntries(from: Int, to: Int, value: Int) { + val entries = habit.originalEntries + for (i in from until to) entries.add(Entry(today.minus(i), value)) + habit.recompute() + } +} + +class NumericalAtLeastScoreListTest : NumericalScoreListTest() { + @Before + @Throws(Exception::class) + override fun setUp() { + super.setUp() + habit = fixtures.createEmptyNumericalHabit(NumericalHabitType.AT_LEAST) + } + + @Test + fun test_withZeroTarget() { + habit = fixtures.createNumericalHabit() + habit.targetValue = 0.0 + habit.recompute() + assertTrue(habit.scores[today].value.isFinite()) + } + + @Test + fun test_getValue() { + addEntries(0, 20, 2000) + val expectedValues = doubleArrayOf( + 0.655747, + 0.636894, + 0.617008, + 0.596033, + 0.573910, + 0.550574, + 0.525961, + 0.500000, + 0.472617, + 0.443734, + 0.413270, + 0.381137, + 0.347244, + 0.311495, + 0.273788, + 0.234017, + 0.192067, + 0.147820, + 0.101149, + 0.051922, + 0.000000, + 0.000000, + 0.000000 + ) + checkScoreValues(expectedValues) + } + + @Test + fun test_recompute() { + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.0, E)) + addEntries(0, 2, 2000) + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.101149, E)) + habit.frequency = Frequency(1, 2) + habit.recompute() + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.072631, E)) + } + + @Test + fun shouldAchieveHighScoreInReasonableTime() { + // Daily habits should achieve at least 99% in 3 months + habit = fixtures.createEmptyNumericalHabit(NumericalHabitType.AT_LEAST) + habit.frequency = Frequency.DAILY + for (i in 0..89) addEntry(i, 2000) + habit.recompute() + assertThat(habit.scores[today].value, OrderingComparison.greaterThan(0.99)) + + // Weekly habits should achieve at least 99% in 9 months + habit = fixtures.createEmptyNumericalHabit(NumericalHabitType.AT_LEAST) + habit.frequency = Frequency.WEEKLY + for (i in 0..38) addEntry(7 * i, 2000) + habit.recompute() + assertThat(habit.scores[today].value, OrderingComparison.greaterThan(0.99)) + + // Monthly habits should achieve at least 99% in 18 months + habit.frequency = Frequency(1, 30) + for (i in 0..17) addEntry(30 * i, 2000) + habit.recompute() + assertThat(habit.scores[today].value, OrderingComparison.greaterThan(0.99)) + } + + @Test + fun shouldAchieveComparableScoreToProgress() { + addEntries(0, 500, 1000) + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.5, E)) + + addEntries(0, 500, 500) + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.25, E)) + } + + @Test + fun overeachievingIsntRelevant() { + addEntry(0, 10000000) + habit.recompute() + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.051922, E)) + } +} + +class NumericalAtMostScoreListTest : NumericalScoreListTest() { + @Before + @Throws(Exception::class) + override fun setUp() { + super.setUp() + habit = fixtures.createEmptyNumericalHabit(NumericalHabitType.AT_MOST) + } + + @Test + fun test_withZeroTarget() { + habit = fixtures.createNumericalHabit() + habit.targetType = NumericalHabitType.AT_MOST + habit.targetValue = 0.0 + habit.recompute() + assertTrue(habit.scores[today].value.isFinite()) + } + + @Test + fun test_getValue() { + addEntry(20, 1000) + addEntries(0, 20, 5000) + val expectedValues = doubleArrayOf( + 0.344253, + 0.363106, + 0.382992, + 0.403967, + 0.426090, + 0.449426, + 0.474039, + 0.500000, + 0.527383, + 0.556266, + 0.586730, + 0.618863, + 0.652756, + 0.688505, + 0.726212, + 0.765983, + 0.807933, + 0.852180, + 0.898851, + 0.948078, + 1.0, + 0.0, + 0.0 + ) + checkScoreValues(expectedValues) + } + + @Test + fun test_recompute() { + habit.recompute() + assertThat(habit.scores[today].value, IsCloseTo.closeTo(1.0, E)) + addEntries(0, 2, 5000) + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.898850, E)) + habit.frequency = Frequency(1, 2) + habit.recompute() + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.927369, E)) + } + + @Test + fun shouldAchieveComparableScoreToProgress() { + addEntries(0, 500, 3000) + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.5, E)) + + addEntries(0, 500, 3500) + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.25, E)) + } + + @Test + fun undereachievingIsntRelevant() { + addEntry(1, 10000000) + habit.recompute() + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.950773, E)) + } + + @Test + fun overeachievingIsntRelevant() { + addEntry(0, 5000) + + addEntry(1, 0) + habit.recompute() + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.948077, E)) + + addEntry(1, 1000) + habit.recompute() + assertThat(habit.scores[today].value, IsCloseTo.closeTo(0.948077, E)) } } From 66a2b41250996bc7a3ac1ad35b12749c04682e82 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Wed, 29 Sep 2021 03:03:21 -0500 Subject: [PATCH 036/132] Target type: use dropdown instead of radio button --- .../habits/edit/EditHabitActivity.kt | 35 ++++++++++++---- .../main/res/layout/activity_edit_habit.xml | 40 ++++++++----------- .../src/main/res/values/strings.xml | 4 +- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt index 8bd84b98c..572917d10 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt @@ -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) @@ -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 @@ -117,10 +119,6 @@ class EditHabitActivity : AppCompatActivity() { binding.notesInput.setText(habit.description) binding.unitInput.setText(habit.unit) binding.targetInput.setText(habit.targetValue.toString()) - if (habit.targetType == NumericalHabitType.AT_MOST) { - binding.targetTypeAtMost.isChecked = true - binding.targetTypeAtLeast.isChecked = false - } } else { habitType = HabitType.fromInt(intent.getIntExtra("habitType", HabitType.YES_NO.value)) } @@ -177,6 +175,23 @@ class EditHabitActivity : AppCompatActivity() { dialog.show(supportFragmentManager, "frequencyPicker") } + populateTargetType() + binding.targetTypePicker.setOnClickListener { + val builder = AlertDialog.Builder(this) + val arrayAdapter = ArrayAdapter(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(this, android.R.layout.select_dialog_item) @@ -267,10 +282,7 @@ class EditHabitActivity : AppCompatActivity() { habit.frequency = Frequency(freqNum, freqDen) if (habitType == HabitType.NUMERICAL) { habit.targetValue = targetInput.text.toString().toDouble() - if (binding.targetTypeAtLeast.isChecked) - habit.targetType = NumericalHabitType.AT_LEAST - else - habit.targetType = NumericalHabitType.AT_MOST + habit.targetType = targetType habit.unit = unitInput.text.trim().toString() } habit.type = habitType @@ -332,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) diff --git a/uhabits-android/src/main/res/layout/activity_edit_habit.xml b/uhabits-android/src/main/res/layout/activity_edit_habit.xml index e30490bfb..75dddb551 100644 --- a/uhabits-android/src/main/res/layout/activity_edit_habit.xml +++ b/uhabits-android/src/main/res/layout/activity_edit_habit.xml @@ -167,29 +167,7 @@ android:hint="@string/measurable_units_example"/> - - - - - - - - - + + + + + + + + + diff --git a/uhabits-android/src/main/res/values/strings.xml b/uhabits-android/src/main/res/values/strings.xml index 8c5e9552a..13767b3df 100644 --- a/uhabits-android/src/main/res/values/strings.xml +++ b/uhabits-android/src/main/res/values/strings.xml @@ -185,8 +185,8 @@ Calendar Unit Target Type - At Least - At Most + At least + At most e.g. Did you exercise today? Question Target From 2a0afedb1db01406b6b0d96763cf2f0919761dfd Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Wed, 29 Sep 2021 03:14:41 -0500 Subject: [PATCH 037/132] SubtitleCard: Show at-most icon --- .../activities/habits/show/views/SubtitleCardViewTest.kt | 2 -- .../activities/habits/show/views/SubtitleCardView.kt | 8 +++++++- .../src/main/res/layout/show_habit_subtitle.xml | 1 - uhabits-android/src/main/res/values/fontawesome.xml | 2 +- .../core/ui/screens/habits/show/views/SubtitleCard.kt | 7 +++++-- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt index a43543936..3323f78df 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardViewTest.kt @@ -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(), ) ) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt index 49c67aae1..5bbfb46d6 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt @@ -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 @@ -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 } diff --git a/uhabits-android/src/main/res/layout/show_habit_subtitle.xml b/uhabits-android/src/main/res/layout/show_habit_subtitle.xml index f8f3924bc..7361b4565 100644 --- a/uhabits-android/src/main/res/layout/show_habit_subtitle.xml +++ b/uhabits-android/src/main/res/layout/show_habit_subtitle.xml @@ -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" /> diff --git a/uhabits-android/src/main/res/values/fontawesome.xml b/uhabits-android/src/main/res/values/fontawesome.xml index 917cf0d73..0ff190382 100644 --- a/uhabits-android/src/main/res/values/fontawesome.xml +++ b/uhabits-android/src/main/res/values/fontawesome.xml @@ -21,6 +21,7 @@ + @@ -181,7 +182,6 @@ - diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt index 525f8fc7c..4cbbd74ec 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt @@ -21,6 +21,7 @@ package org.isoron.uhabits.core.ui.screens.habits.show.views import org.isoron.uhabits.core.models.Frequency import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.NumericalHabitType import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.Reminder import org.isoron.uhabits.core.ui.views.Theme @@ -31,8 +32,9 @@ data class SubtitleCardState( val isNumerical: Boolean, val question: String, val reminder: Reminder?, - val targetValue: Double, - val unit: String, + val targetValue: Double = 0.0, + val targetType: NumericalHabitType = NumericalHabitType.AT_LEAST, + val unit: String = "", val theme: Theme, ) @@ -48,6 +50,7 @@ class SubtitleCardPresenter { question = habit.question, reminder = habit.reminder, targetValue = habit.targetValue, + targetType = habit.targetType, unit = habit.unit, theme = theme, ) From 6d98f7aafaef6293eaa74baa198e87ec5b9c21db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 03:01:49 +0000 Subject: [PATCH 038/132] Bump kotlinx-coroutines-core-jvm from 1.5.1 to 1.5.2 Bumps [kotlinx-coroutines-core-jvm](https://github.com/Kotlin/kotlinx.coroutines) from 1.5.1 to 1.5.2. - [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases) - [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md) - [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.5.1...1.5.2) --- updated-dependencies: - dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index 58424882f..3e44e7e46 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -46,7 +46,7 @@ kotlin { compileOnly("com.google.dagger:dagger:2.38.1") implementation("com.google.guava:guava:30.1.1-android") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.5.30") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.1") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2") implementation("androidx.annotation:annotation:1.2.0") implementation("com.google.code.findbugs:jsr305:3.0.2") implementation("com.opencsv:opencsv:5.5.1") From 23479c77650085823ae8bceca1678cb6e7f2a94d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 05:59:39 +0000 Subject: [PATCH 039/132] Bump opencsv from 5.5.1 to 5.5.2 Bumps opencsv from 5.5.1 to 5.5.2. --- updated-dependencies: - dependency-name: com.opencsv:opencsv dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- uhabits-core/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index ff936f6b9..df770d459 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -120,7 +120,7 @@ dependencies { implementation("androidx.legacy:legacy-preference-v14:1.0.0") implementation("androidx.legacy:legacy-support-v4:1.0.0") implementation("com.google.android.material:material:1.4.0") - implementation("com.opencsv:opencsv:5.5.1") + implementation("com.opencsv:opencsv:5.5.2") implementation(project(":uhabits-core")) kapt("com.google.dagger:dagger-compiler:$daggerVersion") kaptAndroidTest("com.google.dagger:dagger-compiler:$daggerVersion") diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index 3e44e7e46..257061cfd 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -49,7 +49,7 @@ kotlin { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2") implementation("androidx.annotation:annotation:1.2.0") implementation("com.google.code.findbugs:jsr305:3.0.2") - implementation("com.opencsv:opencsv:5.5.1") + implementation("com.opencsv:opencsv:5.5.2") implementation("commons-codec:commons-codec:1.15") implementation("org.apache.commons:commons-lang3:3.12.0") } From 6ab4a696b6e8353b9ba98d5d737457437854af0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 06:07:09 +0000 Subject: [PATCH 040/132] Bump kotlin-stdlib from 1.5.30 to 1.5.31 Bumps [kotlin-stdlib](https://github.com/JetBrains/kotlin) from 1.5.30 to 1.5.31. - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.5.31/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.30...v1.5.31) --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-stdlib dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index 257061cfd..f18b8f7bf 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -45,7 +45,7 @@ kotlin { implementation(kotlin("stdlib-jdk8")) compileOnly("com.google.dagger:dagger:2.38.1") implementation("com.google.guava:guava:30.1.1-android") - implementation("org.jetbrains.kotlin:kotlin-stdlib:1.5.30") + implementation("org.jetbrains.kotlin:kotlin-stdlib:1.5.31") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2") implementation("androidx.annotation:annotation:1.2.0") implementation("com.google.code.findbugs:jsr305:3.0.2") From 29615b670b42457920606ced94c751aaff0f0970 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 06:07:09 +0000 Subject: [PATCH 041/132] Bump kxCoroutinesVersion from 1.5.1 to 1.5.2 Bumps `kxCoroutinesVersion` from 1.5.1 to 1.5.2. Updates `kotlinx-coroutines-android` from 1.5.1 to 1.5.2 - [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases) - [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md) - [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.5.1...1.5.2) Updates `kotlinx-coroutines-core` from 1.5.1 to 1.5.2 - [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases) - [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md) - [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.5.1...1.5.2) --- updated-dependencies: - dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-android dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index df770d459..f2fde1b80 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -88,7 +88,7 @@ android { dependencies { val daggerVersion = "2.38.1" val kotlinVersion = "1.5.30" - val kxCoroutinesVersion = "1.5.1" + val kxCoroutinesVersion = "1.5.2" val ktorVersion = "1.6.3" val espressoVersion = "3.4.0" From c03305120ecc0d11799fee9796870e9a21c9a44d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 06:07:10 +0000 Subject: [PATCH 042/132] Bump daggerVersion from 2.38.1 to 2.39 Bumps `daggerVersion` from 2.38.1 to 2.39. Updates `dagger` from 2.38.1 to 2.39 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.38.1...dagger-2.39) Updates `dagger-compiler` from 2.38.1 to 2.39 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.38.1...dagger-2.39) --- updated-dependencies: - dependency-name: com.google.dagger:dagger dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.dagger:dagger-compiler dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- uhabits-core/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index f2fde1b80..581931802 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -86,7 +86,7 @@ android { } dependencies { - val daggerVersion = "2.38.1" + val daggerVersion = "2.39" val kotlinVersion = "1.5.30" val kxCoroutinesVersion = "1.5.2" val ktorVersion = "1.6.3" diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index f18b8f7bf..33c61a18a 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -43,7 +43,7 @@ kotlin { val jvmMain by getting { dependencies { implementation(kotlin("stdlib-jdk8")) - compileOnly("com.google.dagger:dagger:2.38.1") + compileOnly("com.google.dagger:dagger:2.39") implementation("com.google.guava:guava:30.1.1-android") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.5.31") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2") From 4c269c55d243f7afdce5fec8d9249bf9376b08e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 15:39:15 +0000 Subject: [PATCH 043/132] Bump kotlin-stdlib-jdk8 from 1.5.30 to 1.5.31 Bumps [kotlin-stdlib-jdk8](https://github.com/JetBrains/kotlin) from 1.5.30 to 1.5.31. - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.5.31/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.30...v1.5.31) --- updated-dependencies: - dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- uhabits-server/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 581931802..96ea82c76 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -87,7 +87,7 @@ android { dependencies { val daggerVersion = "2.39" - val kotlinVersion = "1.5.30" + val kotlinVersion = "1.5.31" val kxCoroutinesVersion = "1.5.2" val ktorVersion = "1.6.3" val espressoVersion = "3.4.0" diff --git a/uhabits-server/build.gradle.kts b/uhabits-server/build.gradle.kts index dbb410194..53724a501 100644 --- a/uhabits-server/build.gradle.kts +++ b/uhabits-server/build.gradle.kts @@ -34,7 +34,7 @@ application { dependencies { val ktorVersion = "1.6.3" - val kotlinVersion = "1.5.30" + val kotlinVersion = "1.5.31" val logbackVersion = "1.2.5" implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion") implementation("io.ktor:ktor-server-netty:$ktorVersion") From 265b65eb8ad25da3686698921604e47778b37fc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 15:39:17 +0000 Subject: [PATCH 044/132] Bump guava from 30.1.1-android to 31.0.1-android Bumps [guava](https://github.com/google/guava) from 30.1.1-android to 31.0.1-android. - [Release notes](https://github.com/google/guava/releases) - [Commits](https://github.com/google/guava/commits) --- updated-dependencies: - dependency-name: com.google.guava:guava dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- uhabits-core/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 96ea82c76..524ff92e0 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -108,7 +108,7 @@ dependencies { implementation("com.github.AppIntro:AppIntro:6.1.0") implementation("com.google.code.findbugs:jsr305:3.0.2") implementation("com.google.dagger:dagger:$daggerVersion") - implementation("com.google.guava:guava:30.1.1-android") + implementation("com.google.guava:guava:31.0.1-android") implementation("io.ktor:ktor-client-android:$ktorVersion") implementation("io.ktor:ktor-client-core:$ktorVersion") implementation("io.ktor:ktor-client-jackson:$ktorVersion") diff --git a/uhabits-core/build.gradle.kts b/uhabits-core/build.gradle.kts index 33c61a18a..ae3a8b44f 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -44,7 +44,7 @@ kotlin { dependencies { implementation(kotlin("stdlib-jdk8")) compileOnly("com.google.dagger:dagger:2.39") - implementation("com.google.guava:guava:30.1.1-android") + implementation("com.google.guava:guava:31.0.1-android") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.5.31") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2") implementation("androidx.annotation:annotation:1.2.0") From fd124f2a6cd0d6b75d076ac1dda67b777a558be2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 15:40:33 +0000 Subject: [PATCH 045/132] Bump ktorVersion from 1.6.3 to 1.6.4 Bumps `ktorVersion` from 1.6.3 to 1.6.4. Updates `ktor-client-mock` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) Updates `ktor-jackson` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) Updates `ktor-client-android` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) Updates `ktor-client-core` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) Updates `ktor-client-jackson` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) Updates `ktor-client-json` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) Updates `ktor-server-netty` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) Updates `ktor-server-core` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) Updates `ktor-html-builder` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) Updates `ktor-server-tests` from 1.6.3 to 1.6.4 - [Release notes](https://github.com/ktorio/ktor/releases) - [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md) - [Commits](https://github.com/ktorio/ktor/compare/1.6.3...1.6.4) --- updated-dependencies: - dependency-name: io.ktor:ktor-client-mock dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.ktor:ktor-jackson dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.ktor:ktor-client-android dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.ktor:ktor-client-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.ktor:ktor-client-jackson dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.ktor:ktor-client-json dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.ktor:ktor-server-netty dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.ktor:ktor-server-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.ktor:ktor-html-builder dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.ktor:ktor-server-tests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-android/build.gradle.kts | 2 +- uhabits-server/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uhabits-android/build.gradle.kts b/uhabits-android/build.gradle.kts index 524ff92e0..451e27583 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -89,7 +89,7 @@ dependencies { val daggerVersion = "2.39" val kotlinVersion = "1.5.31" val kxCoroutinesVersion = "1.5.2" - val ktorVersion = "1.6.3" + val ktorVersion = "1.6.4" val espressoVersion = "3.4.0" androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion") diff --git a/uhabits-server/build.gradle.kts b/uhabits-server/build.gradle.kts index 53724a501..2c95dbaa0 100644 --- a/uhabits-server/build.gradle.kts +++ b/uhabits-server/build.gradle.kts @@ -33,7 +33,7 @@ application { } dependencies { - val ktorVersion = "1.6.3" + val ktorVersion = "1.6.4" val kotlinVersion = "1.5.31" val logbackVersion = "1.2.5" implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion") From fa3774a32b481b0655b7c694db17593cd143403d Mon Sep 17 00:00:00 2001 From: Quentin Hibon Date: Fri, 1 Oct 2021 23:08:35 +0200 Subject: [PATCH 046/132] Bump org.jlleitschuh.gradle.ktlint from 10.1.0 to 10.2.0 --- build.gradle.kts | 2 +- .../java/org/isoron/uhabits/widgets/CheckmarkWidgetTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3fc6fe5fd..8b4bfc046 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ plugins { id("org.jetbrains.kotlin.kapt") version kotlinVersion apply (false) id("org.jetbrains.kotlin.android.extensions") version kotlinVersion apply (false) id("org.jetbrains.kotlin.multiplatform") version kotlinVersion apply (false) - id("org.jlleitschuh.gradle.ktlint") version "10.1.0" + id("org.jlleitschuh.gradle.ktlint") version "10.2.0" } apply { diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/CheckmarkWidgetTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/CheckmarkWidgetTest.kt index b73c49c1b..05adfdbbe 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/CheckmarkWidgetTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/CheckmarkWidgetTest.kt @@ -24,8 +24,8 @@ import android.widget.FrameLayout import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest import org.hamcrest.CoreMatchers -import org.hamcrest.CoreMatchers.`is` import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.CoreMatchers.`is` import org.hamcrest.MatcherAssert.assertThat import org.isoron.uhabits.BaseViewTest import org.isoron.uhabits.R From c50c5af49789a766f6ffc047e1f28c4e17656ce5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 20:56:29 +0000 Subject: [PATCH 047/132] Bump logback-classic from 1.2.5 to 1.2.6 Bumps logback-classic from 1.2.5 to 1.2.6. --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- uhabits-server/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uhabits-server/build.gradle.kts b/uhabits-server/build.gradle.kts index 2c95dbaa0..8f0fc2554 100644 --- a/uhabits-server/build.gradle.kts +++ b/uhabits-server/build.gradle.kts @@ -35,7 +35,7 @@ application { dependencies { val ktorVersion = "1.6.4" val kotlinVersion = "1.5.31" - val logbackVersion = "1.2.5" + val logbackVersion = "1.2.6" implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion") implementation("io.ktor:ktor-server-netty:$ktorVersion") implementation("ch.qos.logback:logback-classic:$logbackVersion") From d38f83e96135080a5ff9276e3f127477cab7091e Mon Sep 17 00:00:00 2001 From: Bindu <56578479+vbh@users.noreply.github.com> Date: Mon, 13 Sep 2021 07:05:17 -0700 Subject: [PATCH 048/132] Added a notes field and implemented dialog for numeric habits --- .../common/dialogs/NumberPickerFactory.kt | 11 ++- .../habits/list/ListHabitsScreen.kt | 3 +- .../habits/list/views/CheckmarkButtonView.kt | 6 ++ .../habits/list/views/CheckmarkPanelView.kt | 10 +++ .../habits/list/views/HabitCardListAdapter.kt | 3 +- .../habits/list/views/HabitCardListView.kt | 2 + .../habits/list/views/HabitCardView.kt | 9 ++- .../habits/list/views/NumberButtonView.kt | 16 +++- .../habits/list/views/NumberPanelView.kt | 10 +++ .../habits/show/ShowHabitActivity.kt | 3 +- .../NumericalCheckmarkWidgetActivity.kt | 5 +- .../main/res/layout/number_picker_dialog.xml | 73 +++++++++++++------ .../src/main/res/values/strings.xml | 1 + .../java/org/isoron/uhabits/core/Constants.kt | 2 +- .../core/commands/CreateRepetitionCommand.kt | 3 +- .../uhabits/core/io/HabitBullCSVImporter.kt | 3 +- .../isoron/uhabits/core/io/LoopDBImporter.kt | 4 +- .../org/isoron/uhabits/core/models/Entry.kt | 1 + .../core/models/sqlite/records/EntryRecord.kt | 6 +- .../screens/habits/list/HabitCardListCache.kt | 29 +++++++- .../screens/habits/list/ListHabitsBehavior.kt | 19 +++-- .../screens/habits/show/views/HistoryCard.kt | 10 ++- .../uhabits/core/ui/widgets/WidgetBehavior.kt | 22 ++++-- .../src/jvmMain/resources/migrations/25.sql | 1 + .../commands/CreateRepetitionCommandTest.kt | 2 +- .../habits/list/ListHabitsBehaviorTest.kt | 6 +- 26 files changed, 200 insertions(+), 60 deletions(-) create mode 100644 uhabits-core/src/jvmMain/resources/migrations/25.sql diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt index 1ca119a77..e62abc1a5 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt @@ -47,6 +47,7 @@ class NumberPickerFactory fun create( value: Double, unit: String, + notes: String, callback: ListHabitsBehavior.NumberPickerCallback ): AlertDialog { val inflater = LayoutInflater.from(context) @@ -54,6 +55,7 @@ class NumberPickerFactory val picker = view.findViewById(R.id.picker) val picker2 = view.findViewById(R.id.picker2) + val etNotes = view.findViewById(R.id.etNotes) val watcherFilter: InputFilter = SeparatorWatcherInputFilter(picker2) val numberPickerInputText = getNumberPickerInputText(picker) @@ -77,13 +79,18 @@ class NumberPickerFactory picker2.setFormatter { v -> String.format("%02d", v) } picker2.value = intValue % 100 + etNotes.setText(notes) val dialog = AlertDialog.Builder(context) .setView(view) .setTitle(R.string.change_value) - .setPositiveButton(android.R.string.ok) { _, _ -> + .setPositiveButton(R.string.save) { _, _ -> picker.clearFocus() val v = picker.value + 0.01 * picker2.value - callback.onNumberPicked(v) + val note = etNotes.text.toString() + callback.onNumberPicked(v, note) + } + .setNegativeButton(R.string.cancel) { _, _ -> + callback.onNumberPickerDismissed() } .setOnDismissListener { callback.onNumberPickerDismissed() diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt index 58ad6a031..7746285de 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt @@ -225,9 +225,10 @@ class ListHabitsScreen override fun showNumberPicker( value: Double, unit: String, + notes: String, callback: ListHabitsBehavior.NumberPickerCallback ) { - numberPickerFactory.create(value, unit, callback).show() + numberPickerFactory.create(value, unit, notes, callback).show() } private fun getExecuteString(command: Command): String? { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt index 339cc46b4..26735f865 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt @@ -71,6 +71,12 @@ class CheckmarkButtonView( invalidate() } + var hasNotes = false + set(value) { + field = value + invalidate() + } + var onToggle: (Int) -> Unit = {} private var drawer = Drawer() diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt index 136ea0050..9dba30f31 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt @@ -54,6 +54,12 @@ class CheckmarkPanelView( setupButtons() } + var notes = BooleanArray(0) + set(values) { + field = values + setupButtons() + } + var onToggle: (Timestamp, Int) -> Unit = { _, _ -> } set(value) { field = value @@ -72,6 +78,10 @@ class CheckmarkPanelView( index + dataOffset < values.size -> values[index + dataOffset] else -> UNKNOWN } + button.hasNotes = when { + index + dataOffset < notes.size -> notes[index + dataOffset] + else -> false + } button.color = color button.onToggle = { value -> onToggle(timestamp, value) } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.kt index a780bad08..b8770d0cb 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.kt @@ -124,8 +124,9 @@ class HabitCardListAdapter @Inject constructor( val habit = cache.getHabitByPosition(position) val score = cache.getScore(habit!!.id!!) val checkmarks = cache.getCheckmarks(habit.id!!) + val notesIndicators = cache.getNoteIndicators(habit.id!!) val selected = selected.contains(habit) - listView!!.bindCardView(holder, habit, score, checkmarks, selected) + listView!!.bindCardView(holder, habit, score, checkmarks, notesIndicators, selected) } override fun onViewAttachedToWindow(holder: HabitCardViewHolder) { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt index 58ee2b36a..c8b3915b9 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt @@ -87,6 +87,7 @@ class HabitCardListView( habit: Habit, score: Double, checkmarks: IntArray, + notesIndicators: BooleanArray, selected: Boolean ): View { val cardView = holder.itemView as HabitCardView @@ -98,6 +99,7 @@ class HabitCardListView( cardView.score = score cardView.unit = habit.unit cardView.threshold = habit.targetValue / habit.frequency.denominator + cardView.notes = notesIndicators val detector = GestureDetector(context, CardViewGestureDetector(holder)) cardView.setOnTouchListener { _, ev -> diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt index d6e7a2ad3..1d3b8c685 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt @@ -115,6 +115,13 @@ class HabitCardView( numberPanel.threshold = value } + var notes + get() = numberPanel.notes + set(values) { + checkmarkPanel.notes = values + numberPanel.notes = values + } + var checkmarkPanel: CheckmarkPanelView private var numberPanel: NumberPanelView private var innerFrame: LinearLayout @@ -143,7 +150,7 @@ 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, "") } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt index 405bf606d..7e386df48 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt @@ -101,6 +101,11 @@ class NumberButtonView( field = value invalidate() } + var hasNotes = false + set(value) { + field = value + invalidate() + } var onEdit: () -> Unit = {} private var drawer: Drawer = Drawer(context) @@ -111,8 +116,7 @@ class NumberButtonView( } override fun onClick(v: View) { - if (preferences.isShortToggleEnabled) onEdit() - else showMessage(resources.getString(R.string.long_press_to_edit)) + onEdit() } override fun onLongClick(v: View): Boolean { @@ -153,6 +157,8 @@ class NumberButtonView( textAlign = Paint.Align.CENTER } + private val pNotesIndicator: Paint = Paint() + init { em = pNumber.measureText("m") lowContrast = sres.getColor(R.attr.contrast40) @@ -200,6 +206,7 @@ class NumberButtonView( pNumber.color = activeColor pNumber.typeface = typeface pUnit.color = activeColor + pNotesIndicator.color = activeColor if (units.isBlank()) { rect.set(0f, 0f, width.toFloat(), height.toFloat()) @@ -211,6 +218,11 @@ class NumberButtonView( rect.offset(0f, 1.3f * em) canvas.drawText(units, rect.centerX(), rect.centerY(), pUnit) } + + if (hasNotes) { + val cy = 0.8f * em + canvas.drawCircle(width.toFloat() - cy, cy, 8f, pNotesIndicator) + } } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt index 0a5339ce0..329df6212 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt @@ -72,6 +72,12 @@ class NumberPanelView( setupButtons() } + var notes = BooleanArray(0) + set(values) { + field = values + setupButtons() + } + var onEdit: (Timestamp) -> Unit = {} set(value) { field = value @@ -90,6 +96,10 @@ class NumberPanelView( index + dataOffset < values.size -> values[index + dataOffset] else -> 0.0 } + button.hasNotes = when { + index + dataOffset < notes.size -> notes[index + dataOffset] + else -> false + } button.color = color button.targetType = targetType button.threshold = threshold diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt index 202adb88d..5ecfeea66 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt @@ -164,9 +164,10 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { override fun showNumberPicker( value: Double, unit: String, + notes: String, callback: ListHabitsBehavior.NumberPickerCallback, ) { - NumberPickerFactory(this@ShowHabitActivity).create(value, unit, callback).show() + NumberPickerFactory(this@ShowHabitActivity).create(value, unit, notes, callback).show() } override fun showEditHabitScreen(habit: Habit) { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt index 696fa8c81..cdc516e9a 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt @@ -60,8 +60,8 @@ class NumericalCheckmarkWidgetActivity : Activity(), ListHabitsBehavior.NumberPi SystemUtils.unlockScreen(this) } - override fun onNumberPicked(newValue: Double) { - behavior.setValue(data.habit, data.timestamp, (newValue * 1000).toInt()) + override fun onNumberPicked(newValue: Double, notes: String) { + behavior.setValue(data.habit, data.timestamp, (newValue * 1000).toInt(), notes) widgetUpdater.updateWidgets() finish() } @@ -79,6 +79,7 @@ class NumericalCheckmarkWidgetActivity : Activity(), ListHabitsBehavior.NumberPi numberPickerFactory.create( entry.value / 1000.0, data.habit.unit, + entry.notes, this ).show() } diff --git a/uhabits-android/src/main/res/layout/number_picker_dialog.xml b/uhabits-android/src/main/res/layout/number_picker_dialog.xml index 4a9ffb4ee..8fc33e764 100644 --- a/uhabits-android/src/main/res/layout/number_picker_dialog.xml +++ b/uhabits-android/src/main/res/layout/number_picker_dialog.xml @@ -19,33 +19,64 @@ --> - + - + + + + + + + - + + + android:orientation="vertical" + android:padding="30dp"> + + + + - + \ No newline at end of file diff --git a/uhabits-android/src/main/res/values/strings.xml b/uhabits-android/src/main/res/values/strings.xml index 13767b3df..36be8d1b3 100644 --- a/uhabits-android/src/main/res/values/strings.xml +++ b/uhabits-android/src/main/res/values/strings.xml @@ -55,6 +55,7 @@ Clear Reminder Save + Cancel Streaks You have no active habits You\'re all done for today! diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/Constants.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/Constants.kt index 1388cb5f8..be6c9634b 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/Constants.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/Constants.kt @@ -20,4 +20,4 @@ package org.isoron.uhabits.core const val DATABASE_FILENAME = "uhabits.db" -const val DATABASE_VERSION = 24 +const val DATABASE_VERSION = 25 diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/CreateRepetitionCommand.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/CreateRepetitionCommand.kt index cf0081152..3dd71c14e 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/CreateRepetitionCommand.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/CreateRepetitionCommand.kt @@ -28,10 +28,11 @@ data class CreateRepetitionCommand( val habit: Habit, val timestamp: Timestamp, val value: Int, + val notes: String, ) : Command { override fun run() { val entries = habit.originalEntries - entries.add(Entry(timestamp, value)) + entries.add(Entry(timestamp, value, notes)) habit.recompute() habitList.resort() } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt index bdf7b70c9..ee94cdbd0 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt @@ -77,7 +77,8 @@ class HabitBullCSVImporter logger.info("Creating habit: $name") } if (parseInt(cols[4]) == 1) { - h.originalEntries.add(Entry(timestamp, Entry.YES_MANUAL)) + val notes = cols[5] ?: "" + h.originalEntries.add(Entry(timestamp, Entry.YES_MANUAL, notes)) } } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/LoopDBImporter.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/LoopDBImporter.kt index 0969cd849..3e060f311 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/LoopDBImporter.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/LoopDBImporter.kt @@ -101,8 +101,8 @@ class LoopDBImporter for (r in entryRecords) { val t = Timestamp(r.timestamp!!) - val (_, value) = habit!!.originalEntries.get(t) - if (value != r.value) CreateRepetitionCommand(habitList, habit, t, r.value!!).run() + val (_, value, notes) = habit!!.originalEntries.get(t) + if (value != r.value || notes != r.notes) CreateRepetitionCommand(habitList, habit, t, r.value!!, r.notes!!).run() } runner.notifyListeners(command) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Entry.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Entry.kt index e7aefb8a6..88d0593ef 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Entry.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Entry.kt @@ -21,6 +21,7 @@ package org.isoron.uhabits.core.models data class Entry( val timestamp: Timestamp, val value: Int, + val notes: String = "", ) { companion object { /** diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/EntryRecord.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/EntryRecord.kt index eb2bf858f..648cce117 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/EntryRecord.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/EntryRecord.kt @@ -41,12 +41,16 @@ class EntryRecord { @field:Column var id: Long? = null + + @field:Column + var notes: String? = null fun copyFrom(entry: Entry) { timestamp = entry.timestamp.unixTime value = entry.value + notes = entry.notes } fun toEntry(): Entry { - return Entry(Timestamp(timestamp!!), value!!) + return Entry(Timestamp(timestamp!!), value!!, notes!!) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.kt index a1490421a..d8076c514 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.kt @@ -78,6 +78,11 @@ class HabitCardListCache @Inject constructor( return data.checkmarks[habitId]!! } + @Synchronized + fun getNoteIndicators(habitId: Long): BooleanArray { + return data.notesIndicators[habitId]!! + } + @Synchronized fun hasNoHabit(): Boolean { return allHabits.isEmpty @@ -163,6 +168,7 @@ class HabitCardListCache @Inject constructor( data.habits.removeAt(position) data.idToHabit.remove(id) data.checkmarks.remove(id) + data.notesIndicators.remove(id) data.scores.remove(id) listener.onItemRemoved(position) } @@ -207,6 +213,7 @@ class HabitCardListCache @Inject constructor( val habits: MutableList val checkmarks: HashMap val scores: HashMap + val notesIndicators: HashMap @Synchronized fun copyCheckmarksFrom(oldData: CacheData) { @@ -217,6 +224,15 @@ class HabitCardListCache @Inject constructor( } } + @Synchronized + fun copyNoteIndicatorsFrom(oldData: CacheData) { + val empty = BooleanArray(checkmarkCount) + for (id in idToHabit.keys) { + if (oldData.notesIndicators.containsKey(id)) notesIndicators[id] = + oldData.notesIndicators[id]!! else notesIndicators[id] = empty + } + } + @Synchronized fun copyScoresFrom(oldData: CacheData) { for (id in idToHabit.keys) { @@ -241,6 +257,7 @@ class HabitCardListCache @Inject constructor( habits = LinkedList() checkmarks = HashMap() scores = HashMap() + notesIndicators = HashMap() } } @@ -271,6 +288,7 @@ class HabitCardListCache @Inject constructor( newData.fetchHabits() newData.copyScoresFrom(data) newData.copyCheckmarksFrom(data) + newData.copyNoteIndicatorsFrom(data) val today = getTodayWithOffset() val dateFrom = today.minus(checkmarkCount - 1) if (runner != null) runner!!.publishProgress(this, -1) @@ -280,10 +298,14 @@ class HabitCardListCache @Inject constructor( if (targetId != null && targetId != habit.id) continue newData.scores[habit.id] = habit.scores[today].value val list: MutableList = ArrayList() - for ((_, value) in habit.computedEntries.getByInterval(dateFrom, today)) + val notesList: MutableList = ArrayList() + for ((_, value, note) in habit.computedEntries.getByInterval(dateFrom, today)) { list.add(value) + if (note.isNotEmpty()) notesList.add(true) else notesList.add(false) + } val entries = list.toTypedArray() newData.checkmarks[habit.id] = ArrayUtils.toPrimitive(entries) + newData.notesIndicators[habit.id] = notesList.toBooleanArray() runner!!.publishProgress(this, position) } } @@ -311,6 +333,7 @@ class HabitCardListCache @Inject constructor( data.idToHabit[id] = habit data.scores[id] = newData.scores[id]!! data.checkmarks[id] = newData.checkmarks[id]!! + data.notesIndicators[id] = newData.notesIndicators[id]!! listener.onItemInserted(position) } @@ -338,14 +361,18 @@ class HabitCardListCache @Inject constructor( private fun performUpdate(id: Long, position: Int) { val oldScore = data.scores[id]!! val oldCheckmarks = data.checkmarks[id] + val oldNoteIndicators = data.notesIndicators[id] val newScore = newData.scores[id]!! val newCheckmarks = newData.checkmarks[id]!! + val newNoteIndicators = newData.notesIndicators[id]!! var unchanged = true if (oldScore != newScore) unchanged = false if (!Arrays.equals(oldCheckmarks, newCheckmarks)) unchanged = false + if (!Arrays.equals(oldNoteIndicators, newNoteIndicators)) unchanged = false if (unchanged) return data.scores[id] = newScore data.checkmarks[id] = newCheckmarks + data.notesIndicators[id] = newNoteIndicators listener.onItemChanged(position) } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt index 89fb09af4..2d00b8fbf 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt @@ -47,14 +47,16 @@ open class ListHabitsBehavior @Inject constructor( } fun onEdit(habit: Habit, timestamp: Timestamp?) { - val entries = habit.computedEntries - val oldValue = entries.get(timestamp!!).value.toDouble() + val entries = habit.computedEntries.get(timestamp!!) + val oldValue = entries.value.toDouble() + val notes = entries.notes screen.showNumberPicker( oldValue / 1000, - habit.unit - ) { newValue: Double -> + habit.unit, + notes + ) { newValue: Double, newNotes:String, -> val value = (newValue * 1000).roundToInt() - commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value)) + commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes)) } } @@ -104,9 +106,9 @@ open class ListHabitsBehavior @Inject constructor( if (prefs.isFirstRun) onFirstRun() } - fun onToggle(habit: Habit, timestamp: Timestamp?, value: Int) { + fun onToggle(habit: Habit, timestamp: Timestamp?, value: Int, notes: String) { commandRunner.run( - CreateRepetitionCommand(habitList, habit, timestamp!!, value) + CreateRepetitionCommand(habitList, habit, timestamp!!, value, notes) ) } @@ -131,7 +133,7 @@ open class ListHabitsBehavior @Inject constructor( } fun interface NumberPickerCallback { - fun onNumberPicked(newValue: Double) + fun onNumberPicked(newValue: Double, notes: String) fun onNumberPickerDismissed() {} } @@ -142,6 +144,7 @@ open class ListHabitsBehavior @Inject constructor( fun showNumberPicker( value: Double, unit: String, + notes: String, callback: NumberPickerCallback ) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index 3ce83c8b3..358e776aa 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -64,7 +64,8 @@ class HistoryCardPresenter( if (habit.isNumerical) { val entries = habit.computedEntries val oldValue = entries.get(timestamp).value - screen.showNumberPicker(oldValue / 1000.0, habit.unit) { newValue: Double -> + val notes = entries.get(timestamp).notes + screen.showNumberPicker(oldValue / 1000.0, habit.unit, notes) { newValue: Double, newNotes: String -> val thousands = (newValue * 1000).roundToInt() commandRunner.run( CreateRepetitionCommand( @@ -72,11 +73,14 @@ class HistoryCardPresenter( habit, timestamp, thousands, + newNotes, ), ) } } else { - val currentValue = habit.computedEntries.get(timestamp).value + val entry = habit.computedEntries.get(timestamp) + val currentValue = entry.value + val notes = entry.notes val nextValue = Entry.nextToggleValue( value = currentValue, isSkipEnabled = preferences.isSkipEnabled, @@ -88,6 +92,7 @@ class HistoryCardPresenter( habit, timestamp, nextValue, + notes, ), ) } @@ -154,6 +159,7 @@ class HistoryCardPresenter( fun showNumberPicker( value: Double, unit: String, + notes: String, callback: ListHabitsBehavior.NumberPickerCallback, ) } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt index 164ca04f3..d36420d57 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt @@ -46,31 +46,37 @@ class WidgetBehavior @Inject constructor( } fun onToggleRepetition(habit: Habit, timestamp: Timestamp) { - val currentValue = habit.originalEntries.get(timestamp).value + val entry = habit.computedEntries.get(timestamp) + val currentValue = entry.value + val notes = entry.notes val newValue = nextToggleValue( value = currentValue, isSkipEnabled = preferences.isSkipEnabled, areQuestionMarksEnabled = preferences.areQuestionMarksEnabled ) - setValue(habit, timestamp, newValue) + setValue(habit, timestamp, newValue, notes) notificationTray.cancel(habit) } fun onIncrement(habit: Habit, timestamp: Timestamp, amount: Int) { - val currentValue = habit.computedEntries.get(timestamp).value - setValue(habit, timestamp, currentValue + amount) + val entry = habit.computedEntries.get(timestamp) + val currentValue = entry.value + val notes = entry.notes + setValue(habit, timestamp, currentValue + amount, notes) notificationTray.cancel(habit) } fun onDecrement(habit: Habit, timestamp: Timestamp, amount: Int) { - val currentValue = habit.computedEntries.get(timestamp).value - setValue(habit, timestamp, currentValue - amount) + val entry = habit.computedEntries.get(timestamp) + val currentValue = entry.value + val notes = entry.notes + setValue(habit, timestamp, currentValue - amount, notes) notificationTray.cancel(habit) } - fun setValue(habit: Habit, timestamp: Timestamp?, newValue: Int) { + fun setValue(habit: Habit, timestamp: Timestamp?, newValue: Int, notes: String = "") { commandRunner.run( - CreateRepetitionCommand(habitList, habit, timestamp!!, newValue) + CreateRepetitionCommand(habitList, habit, timestamp!!, newValue, notes) ) } } diff --git a/uhabits-core/src/jvmMain/resources/migrations/25.sql b/uhabits-core/src/jvmMain/resources/migrations/25.sql new file mode 100644 index 000000000..627a686d5 --- /dev/null +++ b/uhabits-core/src/jvmMain/resources/migrations/25.sql @@ -0,0 +1 @@ +alter table Repetitions add column notes text; \ No newline at end of file diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/commands/CreateRepetitionCommandTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/commands/CreateRepetitionCommandTest.kt index fade73e69..974af722b 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/commands/CreateRepetitionCommandTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/commands/CreateRepetitionCommandTest.kt @@ -38,7 +38,7 @@ class CreateRepetitionCommandTest : BaseUnitTest() { habit = fixtures.createShortHabit() habitList.add(habit) today = getToday() - command = CreateRepetitionCommand(habitList, habit, today, 100) + command = CreateRepetitionCommand(habitList, habit, today, 100, "") } @Test diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt index b81d96284..22548314d 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt @@ -79,8 +79,8 @@ class ListHabitsBehaviorTest : BaseUnitTest() { @Test fun testOnEdit() { behavior.onEdit(habit2, getToday()) - verify(screen).showNumberPicker(eq(0.1), eq("miles"), picker.capture()) - picker.lastValue.onNumberPicked(100.0) + verify(screen).showNumberPicker(eq(0.1), eq("miles"), "", picker.capture()) + picker.lastValue.onNumberPicked(100.0, "") val today = getTodayWithOffset() assertThat(habit2.computedEntries.get(today).value, equalTo(100000)) } @@ -160,7 +160,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() { @Test fun testOnToggle() { assertTrue(habit1.isCompletedToday()) - behavior.onToggle(habit1, getToday(), Entry.NO) + behavior.onToggle(habit1, getToday(), Entry.NO, "") assertFalse(habit1.isCompletedToday()) } } From d6441701415c9b6e8799a27c1eb72d3ee3864897 Mon Sep 17 00:00:00 2001 From: Bindu <56578479+vbh@users.noreply.github.com> Date: Tue, 14 Sep 2021 07:28:41 -0700 Subject: [PATCH 049/132] Implement dialog for Yes/No Habits --- .../common/dialogs/CheckmarkDialog.kt | 50 +++++++++++++++++++ .../common/dialogs/NumberPickerFactory.kt | 2 +- .../habits/list/ListHabitsScreen.kt | 9 ++++ .../habits/list/views/CheckmarkButtonView.kt | 13 ++++- .../habits/list/views/CheckmarkPanelView.kt | 7 +++ .../habits/list/views/HabitCardView.kt | 8 ++- .../habits/list/views/NumberButtonView.kt | 2 +- .../habits/show/ShowHabitActivity.kt | 8 +++ .../src/main/res/layout/checkmark_dialog.xml | 18 +++++++ .../src/main/res/values/strings.xml | 2 +- .../screens/habits/list/ListHabitsBehavior.kt | 40 +++++++++++---- .../screens/habits/show/views/HistoryCard.kt | 4 ++ 12 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt create mode 100644 uhabits-android/src/main/res/layout/checkmark_dialog.xml diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt new file mode 100644 index 000000000..7b7853d3b --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt @@ -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(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 + } +} \ No newline at end of file diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt index e62abc1a5..58db019a3 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt @@ -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 { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt index 7746285de..ea2ad85b0 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt @@ -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 ) : 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 -> { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt index 26735f865..bd1b45715 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt @@ -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) + } } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt index 9dba30f31..dabbdc9c0 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt @@ -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) } } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt index 1d3b8c685..82dc31930 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt @@ -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) } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt index 7e386df48..3213e5a68 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt @@ -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()) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt index 5ecfeea66..9dd01b521 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt @@ -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)) } diff --git a/uhabits-android/src/main/res/layout/checkmark_dialog.xml b/uhabits-android/src/main/res/layout/checkmark_dialog.xml new file mode 100644 index 000000000..765b23776 --- /dev/null +++ b/uhabits-android/src/main/res/layout/checkmark_dialog.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/uhabits-android/src/main/res/values/strings.xml b/uhabits-android/src/main/res/values/strings.xml index 36be8d1b3..c908816c1 100644 --- a/uhabits-android/src/main/res/values/strings.xml +++ b/uhabits-android/src/main/res/values/strings.xml @@ -55,7 +55,6 @@ Clear Reminder Save - Cancel Streaks You have no active habits You\'re all done for today! @@ -233,4 +232,5 @@ No app was found to support this action Extend day a few hours past midnight Wait until 3:00 AM to show a new day. Useful if you typically go to sleep after midnight. Requires app restart. + Edit notes diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt index 2d00b8fbf..5d0bff931 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt @@ -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) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index 358e776aa..899734956 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -162,5 +162,9 @@ class HistoryCardPresenter( notes: String, callback: ListHabitsBehavior.NumberPickerCallback, ) + fun showCheckmarkDialog( + notes: String, + callback: ListHabitsBehavior.CheckMarkDialogCallback, + ) } } From 36c1504c6a19aec1d3ba037cc917219480166b08 Mon Sep 17 00:00:00 2001 From: Bindu <56578479+vbh@users.noreply.github.com> Date: Tue, 14 Sep 2021 23:03:34 -0700 Subject: [PATCH 050/132] Add dialog and notes indicator for HistoryChart --- .../isoron/platform/gui/AndroidDataView.kt | 37 +++++++------ .../common/dialogs/HistoryEditorDialog.kt | 4 +- .../habits/show/views/HistoryCardView.kt | 1 + .../isoron/uhabits/widgets/HistoryWidget.kt | 2 + .../kotlin/org/isoron/platform/gui/View.kt | 2 + .../screens/habits/show/views/HistoryCard.kt | 53 +++++++++++++------ .../uhabits/core/ui/views/HistoryChart.kt | 26 +++++++-- 7 files changed, 91 insertions(+), 34 deletions(-) diff --git a/uhabits-android/src/main/java/org/isoron/platform/gui/AndroidDataView.kt b/uhabits-android/src/main/java/org/isoron/platform/gui/AndroidDataView.kt index df5d5e184..0a8c5ee68 100644 --- a/uhabits-android/src/main/java/org/isoron/platform/gui/AndroidDataView.kt +++ b/uhabits-android/src/main/java/org/isoron/platform/gui/AndroidDataView.kt @@ -49,23 +49,12 @@ class AndroidDataView( override fun onShowPress(e: MotionEvent?) = Unit override fun onSingleTapUp(e: MotionEvent?): Boolean { - val x: Float - val y: Float - try { - val pointerId = e!!.getPointerId(0) - x = e.getX(pointerId) - y = e.getY(pointerId) - } catch (ex: RuntimeException) { - // Android often throws IllegalArgumentException here. Apparently, - // the pointer id may become invalid shortly after calling - // e.getPointerId. - return false - } - view?.onClick(x / canvas.innerDensity, y / canvas.innerDensity) - return true + return handleClick(e, true) } - override fun onLongPress(e: MotionEvent?) = Unit + override fun onLongPress(e: MotionEvent?) { + handleClick(e) + } override fun onScroll( e1: MotionEvent?, @@ -137,4 +126,22 @@ class AndroidDataView( } } } + + private fun handleClick(e: MotionEvent?, isSingleTap: Boolean = false): Boolean { + val x: Float + val y: Float + try { + val pointerId = e!!.getPointerId(0) + x = e.getX(pointerId) + y = e.getY(pointerId) + } catch (ex: RuntimeException) { + // Android often throws IllegalArgumentException here. Apparently, + // the pointer id may become invalid shortly after calling + // e.getPointerId. + return false + } + if (isSingleTap) view?.onClick(x / canvas.innerDensity, y / canvas.innerDensity) + else view?.onLongClick(x / canvas.innerDensity, y / canvas.innerDensity) + return true + } } 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 5edae637f..c040da2ac 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 @@ -63,9 +63,10 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { paletteColor = habit.color, series = emptyList(), defaultSquare = HistoryChart.Square.OFF, + hasNotes = emptyList(), theme = themeSwitcher.currentTheme, today = DateUtils.getTodayWithOffset().toLocalDate(), - onDateClickedListener = onDateClickedListener ?: OnDateClickedListener { }, + onDateClickedListener = onDateClickedListener ?: OnDateClickedListener { _, _ -> }, padding = 10.0, ) dataView = AndroidDataView(context!!, null) @@ -103,6 +104,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { ) chart?.series = model.series chart?.defaultSquare = model.defaultSquare + chart?.hasNotes = model.hasNotes dataView.postInvalidate() } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt index f429e1718..345789cca 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt @@ -44,6 +44,7 @@ class HistoryCardView(context: Context, attrs: AttributeSet) : LinearLayout(cont dateFormatter = JavaLocalDateFormatter(Locale.getDefault()), series = state.series, defaultSquare = state.defaultSquare, + hasNotes = state.hasNotes, firstWeekday = state.firstWeekday, ) binding.chart.postInvalidate() diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt index c8d4dce44..7d520bec5 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt @@ -59,6 +59,7 @@ class HistoryWidget( val historyChart = (this.view as HistoryChart) historyChart.series = model.series historyChart.defaultSquare = model.defaultSquare + historyChart.hasNotes = model.hasNotes } } @@ -74,6 +75,7 @@ class HistoryWidget( firstWeekday = prefs.firstWeekday, series = listOf(), defaultSquare = HistoryChart.Square.OFF, + hasNotes = listOf(), ) } ).apply { diff --git a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/gui/View.kt b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/gui/View.kt index b58e1affe..c6ee60b65 100644 --- a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/gui/View.kt +++ b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/gui/View.kt @@ -23,6 +23,8 @@ interface View { fun draw(canvas: Canvas) fun onClick(x: Double, y: Double) { } + fun onLongClick(x: Double, y: Double) { + } } interface DataView : View { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index 899734956..66a3c214a 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -46,6 +46,7 @@ data class HistoryCardState( val firstWeekday: DayOfWeek, val series: List, val defaultSquare: HistoryChart.Square, + val hasNotes: List, val theme: Theme, val today: LocalDate, ) @@ -58,7 +59,7 @@ class HistoryCardPresenter( val screen: Screen, ) : OnDateClickedListener { - override fun onDateClicked(date: LocalDate) { + override fun onDateClicked(date: LocalDate, isLongClick: Boolean) { val timestamp = Timestamp.fromLocalDate(date) screen.showFeedback() if (habit.isNumerical) { @@ -81,20 +82,34 @@ class HistoryCardPresenter( val entry = habit.computedEntries.get(timestamp) val currentValue = entry.value val notes = entry.notes - val nextValue = Entry.nextToggleValue( - value = currentValue, - isSkipEnabled = preferences.isSkipEnabled, - areQuestionMarksEnabled = preferences.areQuestionMarksEnabled - ) - commandRunner.run( - CreateRepetitionCommand( - habitList, - habit, - timestamp, - nextValue, - notes, - ), - ) + if (!isLongClick) { + val nextValue = Entry.nextToggleValue( + value = currentValue, + isSkipEnabled = preferences.isSkipEnabled, + areQuestionMarksEnabled = preferences.areQuestionMarksEnabled + ) + commandRunner.run( + CreateRepetitionCommand( + habitList, + habit, + timestamp, + nextValue, + notes, + ), + ) + return + } + screen.showCheckmarkDialog(notes) { newNotes -> + commandRunner.run( + CreateRepetitionCommand( + habitList, + habit, + timestamp, + currentValue, + newNotes, + ), + ) + } } } @@ -142,6 +157,13 @@ class HistoryCardPresenter( else HistoryChart.Square.OFF + val hasNotes = entries.map { + when (it.notes) { + "" -> false + else -> true + } + } + return HistoryCardState( color = habit.color, firstWeekday = firstWeekday, @@ -149,6 +171,7 @@ class HistoryCardPresenter( theme = theme, series = series, defaultSquare = defaultSquare + hasNotes = hasNotes, ) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt index f0da7a196..150713056 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt @@ -33,7 +33,7 @@ import kotlin.math.min import kotlin.math.round fun interface OnDateClickedListener { - fun onDateClicked(date: LocalDate) + fun onDateClicked(date: LocalDate, isLongClick: Boolean) } class HistoryChart( @@ -42,9 +42,10 @@ class HistoryChart( var paletteColor: PaletteColor, var series: List, var defaultSquare: Square, + var hasNotes: List, var theme: Theme, var today: LocalDate, - var onDateClickedListener: OnDateClickedListener = OnDateClickedListener { }, + var onDateClickedListener: OnDateClickedListener = OnDateClickedListener { _, _ -> }, var padding: Double = 0.0, ) : DataView { @@ -72,6 +73,14 @@ class HistoryChart( get() = squareSpacing + squareSize override fun onClick(x: Double, y: Double) { + onDateClicked(x, y, false) + } + + override fun onLongClick(x: Double, y: Double) { + onDateClicked(x, y, true) + } + + private fun onDateClicked(x: Double, y: Double, isLongClick: Boolean) { if (width <= 0.0) throw IllegalStateException("onClick must be called after draw(canvas)") val col = ((x - padding) / squareSize).toInt() val row = ((y - padding) / squareSize).toInt() @@ -79,7 +88,7 @@ class HistoryChart( if (row == 0 || col == nColumns) return val clickedDate = topLeftDate.plus(offset) if (clickedDate.isNewerThan(today)) return - onDateClickedListener.onDateClicked(clickedDate) + onDateClickedListener.onDateClicked(clickedDate, isLongClick) } override fun draw(canvas: Canvas) { @@ -191,7 +200,9 @@ class HistoryChart( ) { val value = if (offset >= series.size) defaultSquare else series[offset] + val notes = if (offset >= hasNotes.size) false else hasNotes[offset] val squareColor: Color + val circleColor: Color val color = theme.color(paletteColor.paletteIndex) squareColor = when (value) { Square.ON -> { @@ -235,5 +246,14 @@ class HistoryChart( canvas.setColor(textColor) canvas.setTextAlign(TextAlign.CENTER) canvas.drawText(date.day.toString(), x + width / 2, y + width / 2) + + if (notes) { + circleColor = when (value) { + Square.ON -> theme.lowContrastTextColor + else -> color + } + canvas.setColor(circleColor) + canvas.fillCircle(x + width - width / 5, y + width / 5, width / 12) + } } } From a9fddf99638ebc6b77eb0cd7fc2f37f398b074e6 Mon Sep 17 00:00:00 2001 From: Bindu <56578479+vbh@users.noreply.github.com> Date: Mon, 20 Sep 2021 03:47:59 -0700 Subject: [PATCH 051/132] Update tests and fix formatting. --- .../habits/list/views/NumberButtonViewTest.kt | 2 +- .../isoron/uhabits/performance/PerformanceTest.kt | 2 +- .../activities/common/dialogs/CheckmarkDialog.kt | 4 ++-- .../habits/list/views/NumberButtonView.kt | 3 +-- .../org/isoron/uhabits/core/io/LoopDBImporter.kt | 3 ++- .../core/models/sqlite/records/EntryRecord.kt | 3 ++- .../ui/screens/habits/list/ListHabitsBehavior.kt | 2 +- .../ui/screens/habits/show/views/HistoryCard.kt | 13 +++++-------- .../uhabits/core/ui/widgets/WidgetBehavior.kt | 12 ++++++++---- .../screens/habits/list/HabitCardListCacheTest.kt | 2 +- .../screens/habits/list/ListHabitsBehaviorTest.kt | 4 ++-- .../uhabits/core/ui/views/HistoryChartTest.kt | 12 ++++++++---- .../uhabits/core/ui/widgets/WidgetBehaviorTest.kt | 10 +++++----- 13 files changed, 39 insertions(+), 33 deletions(-) diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt index 75166bfab..ea1571889 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt @@ -119,7 +119,7 @@ class NumberButtonViewTest : BaseViewTest() { fun testClick_shortToggleDisabled() { prefs.isShortToggleEnabled = false view.performClick() - assertFalse(edited) + assertTrue(edited) } @Test diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.kt index 10ad56057..d2debb851 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.kt @@ -61,7 +61,7 @@ class PerformanceTest : BaseAndroidTest() { val habit = fixtures.createEmptyHabit() for (i in 0..4999) { val timestamp: Timestamp = Timestamp(i * DAY_LENGTH) - CreateRepetitionCommand(habitList, habit, timestamp, 1).run() + CreateRepetitionCommand(habitList, habit, timestamp, 1, "").run() } db.setTransactionSuccessful() db.endTransaction() diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt index 7b7853d3b..156864caa 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt @@ -1,10 +1,10 @@ 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 androidx.appcompat.app.AlertDialog import org.isoron.uhabits.R import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior import org.isoron.uhabits.inject.ActivityContext @@ -47,4 +47,4 @@ class CheckmarkDialog return dialog } -} \ No newline at end of file +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt index 3213e5a68..dbb930710 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt @@ -35,7 +35,6 @@ import org.isoron.uhabits.inject.ActivityContext import org.isoron.uhabits.utils.InterfaceUtils.getDimension 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 @@ -219,7 +218,7 @@ class NumberButtonView( canvas.drawText(units, rect.centerX(), rect.centerY(), pUnit) } - if (hasNotes) { + if (hasNotes) { val cy = 0.8f * em canvas.drawCircle(width.toFloat() - cy, cy, 8f, pNotesIndicator) } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/LoopDBImporter.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/LoopDBImporter.kt index 3e060f311..918c2084d 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/LoopDBImporter.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/LoopDBImporter.kt @@ -102,7 +102,8 @@ class LoopDBImporter for (r in entryRecords) { val t = Timestamp(r.timestamp!!) val (_, value, notes) = habit!!.originalEntries.get(t) - if (value != r.value || notes != r.notes) CreateRepetitionCommand(habitList, habit, t, r.value!!, r.notes!!).run() + val oldNotes = r.notes ?: "" + if (value != r.value || notes != oldNotes) CreateRepetitionCommand(habitList, habit, t, r.value!!, oldNotes).run() } runner.notifyListeners(command) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/EntryRecord.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/EntryRecord.kt index 648cce117..aaf8fe9f9 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/EntryRecord.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/EntryRecord.kt @@ -51,6 +51,7 @@ class EntryRecord { } fun toEntry(): Entry { - return Entry(Timestamp(timestamp!!), value!!, notes!!) + val notes = notes ?: "" + return Entry(Timestamp(timestamp!!), value!!, notes) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt index 5d0bff931..ced89ad79 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt @@ -56,7 +56,7 @@ open class ListHabitsBehavior @Inject constructor( oldValue / 1000, habit.unit, notes - ) { newValue: Double, newNotes:String, -> + ) { newValue: Double, newNotes: String, -> val value = (newValue * 1000).roundToInt() commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes)) } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index 66a3c214a..8b944d7b9 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -62,10 +62,10 @@ class HistoryCardPresenter( override fun onDateClicked(date: LocalDate, isLongClick: Boolean) { val timestamp = Timestamp.fromLocalDate(date) screen.showFeedback() + val entries = habit.computedEntries + val oldValue = entries.get(timestamp).value + val notes = entries.get(timestamp).notes if (habit.isNumerical) { - val entries = habit.computedEntries - val oldValue = entries.get(timestamp).value - val notes = entries.get(timestamp).notes screen.showNumberPicker(oldValue / 1000.0, habit.unit, notes) { newValue: Double, newNotes: String -> val thousands = (newValue * 1000).roundToInt() commandRunner.run( @@ -79,12 +79,9 @@ class HistoryCardPresenter( ) } } else { - val entry = habit.computedEntries.get(timestamp) - val currentValue = entry.value - val notes = entry.notes if (!isLongClick) { val nextValue = Entry.nextToggleValue( - value = currentValue, + value = oldValue, isSkipEnabled = preferences.isSkipEnabled, areQuestionMarksEnabled = preferences.areQuestionMarksEnabled ) @@ -105,7 +102,7 @@ class HistoryCardPresenter( habitList, habit, timestamp, - currentValue, + oldValue, newNotes, ), ) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt index d36420d57..65dff6dd2 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt @@ -37,16 +37,20 @@ class WidgetBehavior @Inject constructor( ) { fun onAddRepetition(habit: Habit, timestamp: Timestamp?) { notificationTray.cancel(habit) - setValue(habit, timestamp, Entry.YES_MANUAL) + val entry = habit.originalEntries.get(timestamp!!) + val notes = entry.notes + setValue(habit, timestamp, Entry.YES_MANUAL, notes) } fun onRemoveRepetition(habit: Habit, timestamp: Timestamp?) { notificationTray.cancel(habit) - setValue(habit, timestamp, Entry.NO) + val entry = habit.originalEntries.get(timestamp!!) + val notes = entry.notes + setValue(habit, timestamp, Entry.NO, notes) } fun onToggleRepetition(habit: Habit, timestamp: Timestamp) { - val entry = habit.computedEntries.get(timestamp) + val entry = habit.originalEntries.get(timestamp) val currentValue = entry.value val notes = entry.notes val newValue = nextToggleValue( @@ -74,7 +78,7 @@ class WidgetBehavior @Inject constructor( notificationTray.cancel(habit) } - fun setValue(habit: Habit, timestamp: Timestamp?, newValue: Int, notes: String = "") { + fun setValue(habit: Habit, timestamp: Timestamp?, newValue: Int, notes: String) { commandRunner.run( CreateRepetitionCommand(habitList, habit, timestamp!!, newValue, notes) ) diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCacheTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCacheTest.kt index af3132dde..97da833a5 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCacheTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCacheTest.kt @@ -70,7 +70,7 @@ class HabitCardListCacheTest : BaseUnitTest() { @Test fun testCommandListener_single() { val h2 = habitList.getByPosition(2) - commandRunner.run(CreateRepetitionCommand(habitList, h2, today, Entry.NO)) + commandRunner.run(CreateRepetitionCommand(habitList, h2, today, Entry.NO, "")) verify(listener).onItemChanged(2) verify(listener).onRefreshFinished() verifyNoMoreInteractions(listener) diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt index 22548314d..df58affa6 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt @@ -79,7 +79,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() { @Test fun testOnEdit() { behavior.onEdit(habit2, getToday()) - verify(screen).showNumberPicker(eq(0.1), eq("miles"), "", picker.capture()) + verify(screen).showNumberPicker(eq(0.1), eq("miles"), eq(""), picker.capture()) picker.lastValue.onNumberPicked(100.0, "") val today = getTodayWithOffset() assertThat(habit2.computedEntries.get(today).value, equalTo(100000)) @@ -160,7 +160,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() { @Test fun testOnToggle() { assertTrue(habit1.isCompletedToday()) - behavior.onToggle(habit1, getToday(), Entry.NO, "") + behavior.onToggle(habit1, getToday(), Entry.NO) assertFalse(habit1.isCompletedToday()) } } diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt index a53135f9b..84ecc9bfb 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt @@ -72,6 +72,10 @@ class HistoryChartTest { 1 -> DIMMED else -> OFF } + }, + hasNotes = MutableList(85) { + index: Int -> + index % 3 == 0 } ) @@ -86,20 +90,20 @@ class HistoryChartTest { // Click top left date view.onClick(20.0, 46.0) - verify(dateClickedListener).onDateClicked(LocalDate(2014, 10, 26)) + verify(dateClickedListener).onDateClicked(LocalDate(2014, 10, 26), false) reset(dateClickedListener) view.onClick(2.0, 28.0) - verify(dateClickedListener).onDateClicked(LocalDate(2014, 10, 26)) + verify(dateClickedListener).onDateClicked(LocalDate(2014, 10, 26), false) reset(dateClickedListener) // Click date in the middle view.onClick(163.0, 113.0) - verify(dateClickedListener).onDateClicked(LocalDate(2014, 12, 10)) + verify(dateClickedListener).onDateClicked(LocalDate(2014, 12, 10), false) reset(dateClickedListener) // Click today view.onClick(336.0, 37.0) - verify(dateClickedListener).onDateClicked(LocalDate(2015, 1, 25)) + verify(dateClickedListener).onDateClicked(LocalDate(2015, 1, 25), false) reset(dateClickedListener) // Click header diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/widgets/WidgetBehaviorTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/widgets/WidgetBehaviorTest.kt index 18a06c8da..d58ef1979 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/widgets/WidgetBehaviorTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/widgets/WidgetBehaviorTest.kt @@ -58,7 +58,7 @@ class WidgetBehaviorTest : BaseUnitTest() { fun testOnAddRepetition() { behavior.onAddRepetition(habit, today) verify(commandRunner).run( - CreateRepetitionCommand(habitList, habit, today, Entry.YES_MANUAL) + CreateRepetitionCommand(habitList, habit, today, Entry.YES_MANUAL, "") ) verify(notificationTray).cancel(habit) verifyZeroInteractions(preferences) @@ -68,7 +68,7 @@ class WidgetBehaviorTest : BaseUnitTest() { fun testOnRemoveRepetition() { behavior.onRemoveRepetition(habit, today) verify(commandRunner).run( - CreateRepetitionCommand(habitList, habit, today, Entry.NO) + CreateRepetitionCommand(habitList, habit, today, Entry.NO, "") ) verify(notificationTray).cancel(habit) verifyZeroInteractions(preferences) @@ -94,7 +94,7 @@ class WidgetBehaviorTest : BaseUnitTest() { behavior.onToggleRepetition(habit, today) verify(preferences).isSkipEnabled verify(commandRunner).run( - CreateRepetitionCommand(habitList, habit, today, nextValue) + CreateRepetitionCommand(habitList, habit, today, nextValue, "") ) verify(notificationTray).cancel( habit @@ -110,7 +110,7 @@ class WidgetBehaviorTest : BaseUnitTest() { habit.recompute() behavior.onIncrement(habit, today, 100) verify(commandRunner).run( - CreateRepetitionCommand(habitList, habit, today, 600) + CreateRepetitionCommand(habitList, habit, today, 600, "") ) verify(notificationTray).cancel(habit) verifyZeroInteractions(preferences) @@ -123,7 +123,7 @@ class WidgetBehaviorTest : BaseUnitTest() { habit.recompute() behavior.onDecrement(habit, today, 100) verify(commandRunner).run( - CreateRepetitionCommand(habitList, habit, today, 400) + CreateRepetitionCommand(habitList, habit, today, 400, "") ) verify(notificationTray).cancel(habit) verifyZeroInteractions(preferences) From 7cc4b66dfdcc645effedd402bd413a1dbbe408a0 Mon Sep 17 00:00:00 2001 From: Bindu <56578479+vbh@users.noreply.github.com> Date: Tue, 21 Sep 2021 02:35:30 -0700 Subject: [PATCH 052/132] Update HabitBullCSV test to accept notes --- uhabits-core/assets/test/habitbull.csv | 2 +- uhabits-core/assets/test/habitbull2.csv | 4 ++-- .../org/isoron/uhabits/core/io/HabitBullCSVImporter.kt | 4 +++- .../java/org/isoron/uhabits/core/io/ImportTest.kt | 10 ++++++++++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/uhabits-core/assets/test/habitbull.csv b/uhabits-core/assets/test/habitbull.csv index 977a8e8df..014b7d656 100644 --- a/uhabits-core/assets/test/habitbull.csv +++ b/uhabits-core/assets/test/habitbull.csv @@ -1,5 +1,5 @@ HabitName,HabitDescription,HabitCategory,CalendarDate,Value,CommentText -Breed dragons,with love and fire,Diet & Food,2016-03-18,1, +Breed dragons,with love and fire,Diet & Food,2016-03-18,1,text Breed dragons,with love and fire,Diet & Food,2016-03-19,1, Breed dragons,with love and fire,Diet & Food,2016-03-21,1, Reduce sleep,only 2 hours per day,Time Management,2016-03-15,1, diff --git a/uhabits-core/assets/test/habitbull2.csv b/uhabits-core/assets/test/habitbull2.csv index 890632bbd..9296b1ebc 100644 --- a/uhabits-core/assets/test/habitbull2.csv +++ b/uhabits-core/assets/test/habitbull2.csv @@ -1,7 +1,7 @@ HabitName,HabitDescription,HabitCategory,CalendarDate,Value,CommentText H1,,C1,11/5/2020,1, H2,,C2,11/5/2020,-2150000000, -H3,Habit 3,C3,4/11/2019,1, +H3,Habit 3,C3,4/11/2019,1,text H3,Habit 3,C3,4/12/2019,1, H3,Habit 3,C3,4/13/2019,0, H3,Habit 3,C3,4/14/2019,1, @@ -65,7 +65,7 @@ H3,Habit 3,C3,6/10/2019,1, H3,Habit 3,C3,6/11/2019,1, H3,Habit 3,C3,6/12/2019,1, H3,Habit 3,C3,6/13/2019,1, -H3,Habit 3,C3,6/14/2019,0, +H3,Habit 3,C3,6/14/2019,0,Habit 3 notes H3,Habit 3,C3,6/15/2019,1, H4,Habit 4,C4,11/6/2020,1, H4,Habit 4,C4,11/9/2020,1, diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt index ee94cdbd0..140122db7 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.kt @@ -76,9 +76,11 @@ class HabitBullCSVImporter map[name] = h logger.info("Creating habit: $name") } + val notes = cols[5] ?: "" if (parseInt(cols[4]) == 1) { - val notes = cols[5] ?: "" h.originalEntries.add(Entry(timestamp, Entry.YES_MANUAL, notes)) + } else { + h.originalEntries.add(Entry(timestamp, Entry.NO, notes)) } } } diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/io/ImportTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/io/ImportTest.kt index 6a8bd0c4f..daad1784e 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/io/ImportTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/io/ImportTest.kt @@ -54,6 +54,7 @@ class ImportTest : BaseUnitTest() { assertTrue(isChecked(habit, 2016, 3, 18)) assertTrue(isChecked(habit, 2016, 3, 19)) assertFalse(isChecked(habit, 2016, 3, 20)) + assertTrue(isNotesEqual(habit, 2016, 3, 18, "text")) } @Test @@ -68,6 +69,8 @@ class ImportTest : BaseUnitTest() { assertTrue(isChecked(habit, 2019, 4, 11)) assertTrue(isChecked(habit, 2019, 5, 7)) assertFalse(isChecked(habit, 2019, 6, 14)) + assertTrue(isNotesEqual(habit, 2019, 4, 11, "text")) + assertTrue(isNotesEqual(habit, 2019, 6, 14, "Habit 3 notes")) } @Test @@ -127,6 +130,13 @@ class ImportTest : BaseUnitTest() { return h.originalEntries.get(timestamp).value == Entry.YES_MANUAL } + private fun isNotesEqual(h: Habit, year: Int, month: Int, day: Int, notes: String): Boolean { + val date = getStartOfTodayCalendar() + date.set(year, month - 1, day) + val timestamp = Timestamp(date) + return h.originalEntries.get(timestamp).notes == notes + } + @Throws(IOException::class) private fun importFromFile(assetFilename: String) { val file = File.createTempFile("asset", "") From af7f60fc4d016875882652ee088acb455354250b Mon Sep 17 00:00:00 2001 From: Bindu <56578479+vbh@users.noreply.github.com> Date: Wed, 29 Sep 2021 08:22:15 -0700 Subject: [PATCH 053/132] Address review comments --- .../habits/list/views/NumberButtonViewTest.kt | 10 +-- .../common/dialogs/HistoryEditorDialog.kt | 2 +- .../habits/list/views/CheckmarkButtonView.kt | 12 +-- .../habits/list/views/CheckmarkPanelView.kt | 4 +- .../habits/list/views/HabitCardListView.kt | 2 +- .../habits/list/views/HabitCardView.kt | 8 +- .../habits/list/views/NumberButtonView.kt | 9 +- .../habits/list/views/NumberPanelView.kt | 4 +- .../isoron/uhabits/utils/ViewExtensions.kt | 12 +++ .../isoron/uhabits/core/models/EntryList.kt | 2 +- .../screens/habits/list/HabitCardListCache.kt | 6 +- .../screens/habits/list/ListHabitsBehavior.kt | 12 ++- .../screens/habits/show/views/HistoryCard.kt | 87 +++++++++++-------- .../uhabits/core/ui/views/HistoryChart.kt | 13 ++- .../uhabits/core/ui/widgets/WidgetBehavior.kt | 15 ++-- .../uhabits/core/ui/views/HistoryChartTest.kt | 39 ++++++++- 16 files changed, 138 insertions(+), 99 deletions(-) diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt index ea1571889..935fc7028 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonViewTest.kt @@ -116,15 +116,7 @@ class NumberButtonViewTest : BaseViewTest() { } @Test - fun testClick_shortToggleDisabled() { - prefs.isShortToggleEnabled = false - view.performClick() - assertTrue(edited) - } - - @Test - fun testClick_shortToggleEnabled() { - prefs.isShortToggleEnabled = true + fun testClick() { view.performClick() assertTrue(edited) } 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 c040da2ac..55ed8093e 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 @@ -66,7 +66,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { hasNotes = emptyList(), theme = themeSwitcher.currentTheme, today = DateUtils.getTodayWithOffset().toLocalDate(), - onDateClickedListener = onDateClickedListener ?: OnDateClickedListener { _, _ -> }, + onDateClickedListener = onDateClickedListener ?: object : OnDateClickedListener {}, padding = 10.0, ) dataView = AndroidDataView(context!!, null) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt index bd1b45715..498b80ab6 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkButtonView.kt @@ -38,6 +38,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.dim +import org.isoron.uhabits.utils.drawNotesIndicator import org.isoron.uhabits.utils.getFontAwesome import org.isoron.uhabits.utils.sres import org.isoron.uhabits.utils.toMeasureSpec @@ -104,7 +105,8 @@ class CheckmarkButtonView( } override fun onLongClick(v: View): Boolean { - performToggle() + if (preferences.isShortToggleEnabled) onEdit() + else performToggle() return true } @@ -134,8 +136,6 @@ 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 @@ -145,7 +145,6 @@ class CheckmarkButtonView( } else -> lowContrastColor } - pNotesIndicator.color = color val id = when (value) { SKIP -> R.string.fa_skipped NO -> R.string.fa_times @@ -181,10 +180,7 @@ class CheckmarkButtonView( canvas.drawText(label, rect.centerX(), rect.centerY(), paint) } - if (hasNotes) { - val cy = 0.8f * em - canvas.drawCircle(width.toFloat() - cy, cy, 8f, pNotesIndicator) - } + drawNotesIndicator(canvas, color, em, hasNotes) } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt index dabbdc9c0..859cf734d 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelView.kt @@ -54,7 +54,7 @@ class CheckmarkPanelView( setupButtons() } - var notes = BooleanArray(0) + var notesIndicators = BooleanArray(0) set(values) { field = values setupButtons() @@ -85,7 +85,7 @@ class CheckmarkPanelView( else -> UNKNOWN } button.hasNotes = when { - index + dataOffset < notes.size -> notes[index + dataOffset] + index + dataOffset < notesIndicators.size -> notesIndicators[index + dataOffset] else -> false } button.color = color diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt index c8b3915b9..8ce805098 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.kt @@ -99,7 +99,7 @@ class HabitCardListView( cardView.score = score cardView.unit = habit.unit cardView.threshold = habit.targetValue / habit.frequency.denominator - cardView.notes = notesIndicators + cardView.notesIndicators = notesIndicators val detector = GestureDetector(context, CardViewGestureDetector(holder)) cardView.setOnTouchListener { _, ev -> diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt index 82dc31930..b04a92477 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.kt @@ -115,11 +115,11 @@ class HabitCardView( numberPanel.threshold = value } - var notes - get() = checkmarkPanel.notes + var notesIndicators + get() = checkmarkPanel.notesIndicators set(values) { - checkmarkPanel.notes = values - numberPanel.notes = values + checkmarkPanel.notesIndicators = values + numberPanel.notesIndicators = values } var checkmarkPanel: CheckmarkPanelView diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt index dbb930710..b958dae8b 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.kt @@ -34,6 +34,7 @@ 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.dim +import org.isoron.uhabits.utils.drawNotesIndicator import org.isoron.uhabits.utils.getFontAwesome import org.isoron.uhabits.utils.sres import java.lang.Double.max @@ -156,8 +157,6 @@ class NumberButtonView( textAlign = Paint.Align.CENTER } - private val pNotesIndicator: Paint = Paint() - init { em = pNumber.measureText("m") lowContrast = sres.getColor(R.attr.contrast40) @@ -205,7 +204,6 @@ class NumberButtonView( pNumber.color = activeColor pNumber.typeface = typeface pUnit.color = activeColor - pNotesIndicator.color = color if (units.isBlank()) { rect.set(0f, 0f, width.toFloat(), height.toFloat()) @@ -218,10 +216,7 @@ class NumberButtonView( canvas.drawText(units, rect.centerX(), rect.centerY(), pUnit) } - if (hasNotes) { - val cy = 0.8f * em - canvas.drawCircle(width.toFloat() - cy, cy, 8f, pNotesIndicator) - } + drawNotesIndicator(canvas, color, em, hasNotes) } } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt index 329df6212..520401f65 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.kt @@ -72,7 +72,7 @@ class NumberPanelView( setupButtons() } - var notes = BooleanArray(0) + var notesIndicators = BooleanArray(0) set(values) { field = values setupButtons() @@ -97,7 +97,7 @@ class NumberPanelView( else -> 0.0 } button.hasNotes = when { - index + dataOffset < notes.size -> notes[index + dataOffset] + index + dataOffset < notesIndicators.size -> notesIndicators[index + dataOffset] else -> false } button.color = color diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt b/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt index bfa64ebf0..b6903b3b0 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/utils/ViewExtensions.kt @@ -22,7 +22,9 @@ package org.isoron.uhabits.utils import android.app.Activity import android.content.ActivityNotFoundException import android.content.Intent +import android.graphics.Canvas import android.graphics.Color +import android.graphics.Paint import android.graphics.drawable.ColorDrawable import android.os.Handler import android.view.LayoutInflater @@ -199,5 +201,15 @@ fun View.dim(id: Int) = InterfaceUtils.getDimension(context, id) fun View.sp(value: Float) = InterfaceUtils.spToPixels(context, value) fun View.dp(value: Float) = InterfaceUtils.dpToPixels(context, value) fun View.str(id: Int) = resources.getString(id) + +fun View.drawNotesIndicator(canvas: Canvas, color: Int, size: Float, hasNotes: Boolean) { + val pNotesIndicator = Paint() + pNotesIndicator.color = color + if (hasNotes) { + val cy = 0.8f * size + canvas.drawCircle(width.toFloat() - cy, cy, 8f, pNotesIndicator) + } +} + val View.sres: StyledResources get() = StyledResources(context) diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/EntryList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/EntryList.kt index b11baea24..5212923b1 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/EntryList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/EntryList.kt @@ -100,7 +100,7 @@ open class EntryList { val intervals = buildIntervals(frequency, original) snapIntervalsTogether(intervals) val computed = buildEntriesFromInterval(original, intervals) - computed.filter { it.value != UNKNOWN }.forEach { add(it) } + computed.filter { it.value != UNKNOWN || it.notes.isNotEmpty() }.forEach { add(it) } } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.kt index d8076c514..f1e306758 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/HabitCardListCache.kt @@ -298,14 +298,14 @@ class HabitCardListCache @Inject constructor( if (targetId != null && targetId != habit.id) continue newData.scores[habit.id] = habit.scores[today].value val list: MutableList = ArrayList() - val notesList: MutableList = ArrayList() + val notesIndicators: MutableList = ArrayList() for ((_, value, note) in habit.computedEntries.getByInterval(dateFrom, today)) { list.add(value) - if (note.isNotEmpty()) notesList.add(true) else notesList.add(false) + notesIndicators.add(note.isNotEmpty()) } val entries = list.toTypedArray() newData.checkmarks[habit.id] = ArrayUtils.toPrimitive(entries) - newData.notesIndicators[habit.id] = notesList.toBooleanArray() + newData.notesIndicators[habit.id] = notesIndicators.toBooleanArray() runner!!.publishProgress(this, position) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt index ced89ad79..9139da08b 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt @@ -48,24 +48,22 @@ open class ListHabitsBehavior @Inject constructor( } fun onEdit(habit: Habit, timestamp: Timestamp?) { - val entries = habit.computedEntries.get(timestamp!!) - val notes = entries.notes + val entry = habit.computedEntries.get(timestamp!!) if (habit.type == HabitType.NUMERICAL) { - val oldValue = entries.value.toDouble() + val oldValue = entry.value.toDouble() screen.showNumberPicker( oldValue / 1000, habit.unit, - notes + entry.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 + entry.notes ) { newNotes -> - commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes)) + commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, entry.value, newNotes)) } } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index 8b944d7b9..a3b9c9587 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -59,50 +59,44 @@ class HistoryCardPresenter( val screen: Screen, ) : OnDateClickedListener { - override fun onDateClicked(date: LocalDate, isLongClick: Boolean) { + override fun onDateShortPress(date: LocalDate) { val timestamp = Timestamp.fromLocalDate(date) screen.showFeedback() - val entries = habit.computedEntries - val oldValue = entries.get(timestamp).value - val notes = entries.get(timestamp).notes if (habit.isNumerical) { - screen.showNumberPicker(oldValue / 1000.0, habit.unit, notes) { newValue: Double, newNotes: String -> - val thousands = (newValue * 1000).roundToInt() - commandRunner.run( - CreateRepetitionCommand( - habitList, - habit, - timestamp, - thousands, - newNotes, - ), - ) - } + showNumberPicker(timestamp) } else { - if (!isLongClick) { - val nextValue = Entry.nextToggleValue( - value = oldValue, - isSkipEnabled = preferences.isSkipEnabled, - areQuestionMarksEnabled = preferences.areQuestionMarksEnabled - ) - commandRunner.run( - CreateRepetitionCommand( - habitList, - habit, - timestamp, - nextValue, - notes, - ), - ) - return - } - screen.showCheckmarkDialog(notes) { newNotes -> + val entry = habit.computedEntries.get(timestamp) + val nextValue = Entry.nextToggleValue( + value = entry.value, + isSkipEnabled = preferences.isSkipEnabled, + areQuestionMarksEnabled = preferences.areQuestionMarksEnabled + ) + commandRunner.run( + CreateRepetitionCommand( + habitList, + habit, + timestamp, + nextValue, + entry.notes, + ), + ) + } + } + + override fun onDateLongPress(date: LocalDate) { + val timestamp = Timestamp.fromLocalDate(date) + screen.showFeedback() + if (habit.isNumerical) { + showNumberPicker(timestamp) + } else { + val entry = habit.computedEntries.get(timestamp) + screen.showCheckmarkDialog(entry.notes) { newNotes -> commandRunner.run( CreateRepetitionCommand( habitList, habit, timestamp, - oldValue, + entry.value, newNotes, ), ) @@ -110,6 +104,27 @@ class HistoryCardPresenter( } } + private fun showNumberPicker(timestamp: Timestamp) { + val entry = habit.computedEntries.get(timestamp) + val oldValue = entry.value + screen.showNumberPicker( + oldValue / 1000.0, + habit.unit, + entry.notes + ) { newValue: Double, newNotes: String -> + val thousands = (newValue * 1000).roundToInt() + commandRunner.run( + CreateRepetitionCommand( + habitList, + habit, + timestamp, + thousands, + newNotes, + ), + ) + } + } + fun onClickEditButton() { screen.showHistoryEditorDialog(this) } @@ -167,7 +182,7 @@ class HistoryCardPresenter( today = today.toLocalDate(), theme = theme, series = series, - defaultSquare = defaultSquare + defaultSquare = defaultSquare, hasNotes = hasNotes, ) } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt index 150713056..c7c9d443c 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt @@ -32,8 +32,9 @@ import kotlin.math.max import kotlin.math.min import kotlin.math.round -fun interface OnDateClickedListener { - fun onDateClicked(date: LocalDate, isLongClick: Boolean) +interface OnDateClickedListener { + fun onDateShortPress(date: LocalDate) {} + fun onDateLongPress(date: LocalDate) {} } class HistoryChart( @@ -45,7 +46,7 @@ class HistoryChart( var hasNotes: List, var theme: Theme, var today: LocalDate, - var onDateClickedListener: OnDateClickedListener = OnDateClickedListener { _, _ -> }, + var onDateClickedListener: OnDateClickedListener = object : OnDateClickedListener {}, var padding: Double = 0.0, ) : DataView { @@ -88,7 +89,11 @@ class HistoryChart( if (row == 0 || col == nColumns) return val clickedDate = topLeftDate.plus(offset) if (clickedDate.isNewerThan(today)) return - onDateClickedListener.onDateClicked(clickedDate, isLongClick) + if (isLongClick) { + onDateClickedListener.onDateLongPress(clickedDate) + } else { + onDateClickedListener.onDateShortPress(clickedDate) + } } override fun draw(canvas: Canvas) { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt index 65dff6dd2..879b788be 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.kt @@ -38,43 +38,38 @@ class WidgetBehavior @Inject constructor( fun onAddRepetition(habit: Habit, timestamp: Timestamp?) { notificationTray.cancel(habit) val entry = habit.originalEntries.get(timestamp!!) - val notes = entry.notes - setValue(habit, timestamp, Entry.YES_MANUAL, notes) + setValue(habit, timestamp, Entry.YES_MANUAL, entry.notes) } fun onRemoveRepetition(habit: Habit, timestamp: Timestamp?) { notificationTray.cancel(habit) val entry = habit.originalEntries.get(timestamp!!) - val notes = entry.notes - setValue(habit, timestamp, Entry.NO, notes) + setValue(habit, timestamp, Entry.NO, entry.notes) } fun onToggleRepetition(habit: Habit, timestamp: Timestamp) { val entry = habit.originalEntries.get(timestamp) val currentValue = entry.value - val notes = entry.notes val newValue = nextToggleValue( value = currentValue, isSkipEnabled = preferences.isSkipEnabled, areQuestionMarksEnabled = preferences.areQuestionMarksEnabled ) - setValue(habit, timestamp, newValue, notes) + setValue(habit, timestamp, newValue, entry.notes) notificationTray.cancel(habit) } fun onIncrement(habit: Habit, timestamp: Timestamp, amount: Int) { val entry = habit.computedEntries.get(timestamp) val currentValue = entry.value - val notes = entry.notes - setValue(habit, timestamp, currentValue + amount, notes) + setValue(habit, timestamp, currentValue + amount, entry.notes) notificationTray.cancel(habit) } fun onDecrement(habit: Habit, timestamp: Timestamp, amount: Int) { val entry = habit.computedEntries.get(timestamp) val currentValue = entry.value - val notes = entry.notes - setValue(habit, timestamp, currentValue - amount, notes) + setValue(habit, timestamp, currentValue - amount, entry.notes) notificationTray.cancel(habit) } diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt index 84ecc9bfb..627e29dca 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt @@ -90,20 +90,20 @@ class HistoryChartTest { // Click top left date view.onClick(20.0, 46.0) - verify(dateClickedListener).onDateClicked(LocalDate(2014, 10, 26), false) + verify(dateClickedListener).onDateShortPress(LocalDate(2014, 10, 26)) reset(dateClickedListener) view.onClick(2.0, 28.0) - verify(dateClickedListener).onDateClicked(LocalDate(2014, 10, 26), false) + verify(dateClickedListener).onDateShortPress(LocalDate(2014, 10, 26)) reset(dateClickedListener) // Click date in the middle view.onClick(163.0, 113.0) - verify(dateClickedListener).onDateClicked(LocalDate(2014, 12, 10), false) + verify(dateClickedListener).onDateShortPress(LocalDate(2014, 12, 10)) reset(dateClickedListener) // Click today view.onClick(336.0, 37.0) - verify(dateClickedListener).onDateClicked(LocalDate(2015, 1, 25), false) + verify(dateClickedListener).onDateShortPress(LocalDate(2015, 1, 25)) reset(dateClickedListener) // Click header @@ -115,6 +115,37 @@ class HistoryChartTest { verifyNoMoreInteractions(dateClickedListener) } + @Test + fun testLongClick() = runBlocking { + assertRenders(400, 200, "$base/base.png", view) + + // Click top left date + view.onLongClick(20.0, 46.0) + verify(dateClickedListener).onDateLongPress(LocalDate(2014, 10, 26)) + reset(dateClickedListener) + view.onLongClick(2.0, 28.0) + verify(dateClickedListener).onDateLongPress(LocalDate(2014, 10, 26)) + reset(dateClickedListener) + + // Click date in the middle + view.onLongClick(163.0, 113.0) + verify(dateClickedListener).onDateLongPress(LocalDate(2014, 12, 10)) + reset(dateClickedListener) + + // Click today + view.onLongClick(336.0, 37.0) + verify(dateClickedListener).onDateLongPress(LocalDate(2015, 1, 25)) + reset(dateClickedListener) + + // Click header + view.onLongClick(160.0, 15.0) + verifyNoMoreInteractions(dateClickedListener) + + // Click right axis + view.onLongClick(360.0, 60.0) + verifyNoMoreInteractions(dateClickedListener) + } + @Test fun testDrawWeekDay() = runBlocking { view.firstWeekday = DayOfWeek.MONDAY From 79e302f9225c681abb1933f3e6fdfa1ad1e4ed1c Mon Sep 17 00:00:00 2001 From: Bindu <56578479+vbh@users.noreply.github.com> Date: Thu, 30 Sep 2021 00:51:05 -0700 Subject: [PATCH 054/132] Change variable name --- .../activities/common/dialogs/HistoryEditorDialog.kt | 4 ++-- .../uhabits/activities/habits/show/views/HistoryCardView.kt | 2 +- .../main/java/org/isoron/uhabits/widgets/HistoryWidget.kt | 4 ++-- .../core/ui/screens/habits/show/views/HistoryCard.kt | 6 +++--- .../java/org/isoron/uhabits/core/ui/views/HistoryChart.kt | 6 +++--- .../org/isoron/uhabits/core/ui/views/HistoryChartTest.kt | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) 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 55ed8093e..21999d4e1 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 @@ -63,7 +63,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { paletteColor = habit.color, series = emptyList(), defaultSquare = HistoryChart.Square.OFF, - hasNotes = emptyList(), + notesIndicators = emptyList(), theme = themeSwitcher.currentTheme, today = DateUtils.getTodayWithOffset().toLocalDate(), onDateClickedListener = onDateClickedListener ?: object : OnDateClickedListener {}, @@ -104,7 +104,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { ) chart?.series = model.series chart?.defaultSquare = model.defaultSquare - chart?.hasNotes = model.hasNotes + chart?.notesIndicators = model.notesIndicators dataView.postInvalidate() } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt index 345789cca..74e566fbb 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/HistoryCardView.kt @@ -44,7 +44,7 @@ class HistoryCardView(context: Context, attrs: AttributeSet) : LinearLayout(cont dateFormatter = JavaLocalDateFormatter(Locale.getDefault()), series = state.series, defaultSquare = state.defaultSquare, - hasNotes = state.hasNotes, + notesIndicators = state.notesIndicators, firstWeekday = state.firstWeekday, ) binding.chart.postInvalidate() diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt index 7d520bec5..25d8b7348 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/HistoryWidget.kt @@ -59,7 +59,7 @@ class HistoryWidget( val historyChart = (this.view as HistoryChart) historyChart.series = model.series historyChart.defaultSquare = model.defaultSquare - historyChart.hasNotes = model.hasNotes + historyChart.notesIndicators = model.notesIndicators } } @@ -75,7 +75,7 @@ class HistoryWidget( firstWeekday = prefs.firstWeekday, series = listOf(), defaultSquare = HistoryChart.Square.OFF, - hasNotes = listOf(), + notesIndicators = listOf(), ) } ).apply { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index a3b9c9587..ae738f932 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -46,7 +46,7 @@ data class HistoryCardState( val firstWeekday: DayOfWeek, val series: List, val defaultSquare: HistoryChart.Square, - val hasNotes: List, + val notesIndicators: List, val theme: Theme, val today: LocalDate, ) @@ -169,7 +169,7 @@ class HistoryCardPresenter( else HistoryChart.Square.OFF - val hasNotes = entries.map { + val notesIndicators = entries.map { when (it.notes) { "" -> false else -> true @@ -183,7 +183,7 @@ class HistoryCardPresenter( theme = theme, series = series, defaultSquare = defaultSquare, - hasNotes = hasNotes, + notesIndicators = notesIndicators, ) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt index c7c9d443c..afdc5d3b0 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/views/HistoryChart.kt @@ -43,7 +43,7 @@ class HistoryChart( var paletteColor: PaletteColor, var series: List, var defaultSquare: Square, - var hasNotes: List, + var notesIndicators: List, var theme: Theme, var today: LocalDate, var onDateClickedListener: OnDateClickedListener = object : OnDateClickedListener {}, @@ -205,7 +205,7 @@ class HistoryChart( ) { val value = if (offset >= series.size) defaultSquare else series[offset] - val notes = if (offset >= hasNotes.size) false else hasNotes[offset] + val hasNotes = if (offset >= notesIndicators.size) false else notesIndicators[offset] val squareColor: Color val circleColor: Color val color = theme.color(paletteColor.paletteIndex) @@ -252,7 +252,7 @@ class HistoryChart( canvas.setTextAlign(TextAlign.CENTER) canvas.drawText(date.day.toString(), x + width / 2, y + width / 2) - if (notes) { + if (hasNotes) { circleColor = when (value) { Square.ON -> theme.lowContrastTextColor else -> color diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt index 627e29dca..8a9d523ab 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/views/HistoryChartTest.kt @@ -73,7 +73,7 @@ class HistoryChartTest { else -> OFF } }, - hasNotes = MutableList(85) { + notesIndicators = MutableList(85) { index: Int -> index % 3 == 0 } From 71f400f587ccb14b1e94cd4fdf44d57fe6431ead Mon Sep 17 00:00:00 2001 From: Bindu <56578479+vbh@users.noreply.github.com> Date: Sat, 2 Oct 2021 11:06:51 -0700 Subject: [PATCH 055/132] improve numerical dialog design --- .../common/dialogs/NumberPickerFactory.kt | 3 +- .../habits/list/ListHabitsScreen.kt | 3 +- .../habits/show/ShowHabitActivity.kt | 3 +- .../NumericalCheckmarkWidgetActivity.kt | 1 + .../main/res/drawable/dialog_bg_input_box.xml | 29 ++++ .../main/res/layout/number_picker_dialog.xml | 128 +++++++++++------- uhabits-android/src/main/res/values/attrs.xml | 1 + .../src/main/res/values/strings.xml | 2 +- .../src/main/res/values/styles.xml | 27 ++++ .../isoron/uhabits/core/models/Timestamp.kt | 5 + .../screens/habits/list/ListHabitsBehavior.kt | 4 +- .../screens/habits/show/views/HistoryCard.kt | 4 +- .../isoron/uhabits/core/utils/DateFormats.kt | 3 + .../habits/list/ListHabitsBehaviorTest.kt | 2 +- 14 files changed, 160 insertions(+), 55 deletions(-) create mode 100644 uhabits-android/src/main/res/drawable/dialog_bg_input_box.xml diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt index 58db019a3..404c18e9c 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/NumberPickerFactory.kt @@ -48,6 +48,7 @@ class NumberPickerFactory value: Double, unit: String, notes: String, + dateString: String, callback: ListHabitsBehavior.NumberPickerCallback ): AlertDialog { val inflater = LayoutInflater.from(context) @@ -82,7 +83,7 @@ class NumberPickerFactory etNotes.setText(notes) val dialog = AlertDialog.Builder(context) .setView(view) - .setTitle(R.string.change_value) + .setTitle(dateString) .setPositiveButton(R.string.save) { _, _ -> picker.clearFocus() val v = picker.value + 0.01 * picker2.value diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt index ea2ad85b0..f9a9bfef5 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt @@ -228,9 +228,10 @@ class ListHabitsScreen value: Double, unit: String, notes: String, + dateString: String, callback: ListHabitsBehavior.NumberPickerCallback ) { - numberPickerFactory.create(value, unit, notes, callback).show() + numberPickerFactory.create(value, unit, notes, dateString, callback).show() } override fun showCheckmarkDialog( diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt index 9dd01b521..e42cd57bf 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitActivity.kt @@ -166,9 +166,10 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { value: Double, unit: String, notes: String, + dateString: String, callback: ListHabitsBehavior.NumberPickerCallback, ) { - NumberPickerFactory(this@ShowHabitActivity).create(value, unit, notes, callback).show() + NumberPickerFactory(this@ShowHabitActivity).create(value, unit, notes, dateString, callback).show() } override fun showCheckmarkDialog( diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt index cdc516e9a..c557ed942 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/activities/NumericalCheckmarkWidgetActivity.kt @@ -80,6 +80,7 @@ class NumericalCheckmarkWidgetActivity : Activity(), ListHabitsBehavior.NumberPi entry.value / 1000.0, data.habit.unit, entry.notes, + today.toDialogDateString(), this ).show() } diff --git a/uhabits-android/src/main/res/drawable/dialog_bg_input_box.xml b/uhabits-android/src/main/res/drawable/dialog_bg_input_box.xml new file mode 100644 index 000000000..0f2a651a7 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/dialog_bg_input_box.xml @@ -0,0 +1,29 @@ + + + + + + + + \ No newline at end of file diff --git a/uhabits-android/src/main/res/layout/number_picker_dialog.xml b/uhabits-android/src/main/res/layout/number_picker_dialog.xml index 8fc33e764..0bfa7df54 100644 --- a/uhabits-android/src/main/res/layout/number_picker_dialog.xml +++ b/uhabits-android/src/main/res/layout/number_picker_dialog.xml @@ -19,63 +19,95 @@ --> + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingTop="12dp" + android:paddingStart="10dp" + android:paddingEnd="10dp"> - - - - - - - - + android:layout_height="wrap_content" + android:orientation="horizontal" + android:padding="5dp" + android:baselineAligned="false"> + + + + + + + + + + + + + + + + + + + + - - - - + android:orientation="horizontal" + android:padding="5dp" + android:baselineAligned="false"> + + + + + + + + + + + + diff --git a/uhabits-android/src/main/res/values/attrs.xml b/uhabits-android/src/main/res/values/attrs.xml index 081878e5b..b00eaf69b 100644 --- a/uhabits-android/src/main/res/values/attrs.xml +++ b/uhabits-android/src/main/res/values/attrs.xml @@ -43,6 +43,7 @@ + diff --git a/uhabits-android/src/main/res/values/strings.xml b/uhabits-android/src/main/res/values/strings.xml index c908816c1..6aeb30eb7 100644 --- a/uhabits-android/src/main/res/values/strings.xml +++ b/uhabits-android/src/main/res/values/strings.xml @@ -181,7 +181,7 @@ By status Export Press-and-hold to change the value - Change value + Value Calendar Unit Target Type diff --git a/uhabits-android/src/main/res/values/styles.xml b/uhabits-android/src/main/res/values/styles.xml index 0a3e9da10..46d40c46c 100644 --- a/uhabits-android/src/main/res/values/styles.xml +++ b/uhabits-android/src/main/res/values/styles.xml @@ -63,6 +63,7 @@ @color/grey_200 @color/grey_800 false + @color/white + + + + + diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Timestamp.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Timestamp.kt index feb118ce5..2233237c0 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Timestamp.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Timestamp.kt @@ -20,6 +20,7 @@ package org.isoron.uhabits.core.models import org.isoron.platform.time.LocalDate import org.isoron.uhabits.core.utils.DateFormats.Companion.getCSVDateFormat +import org.isoron.uhabits.core.utils.DateFormats.Companion.getDialogDateFormat import org.isoron.uhabits.core.utils.DateUtils import org.isoron.uhabits.core.utils.DateUtils.Companion.getStartOfTodayCalendar import org.isoron.uhabits.core.utils.DateUtils.Companion.truncate @@ -81,6 +82,10 @@ data class Timestamp(var unixTime: Long) : Comparable { return day } + fun toDialogDateString(): String { + return getDialogDateFormat().format(Date(unixTime)) + } + override fun toString(): String { return getCSVDateFormat().format(Date(unixTime)) } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt index 9139da08b..124f17445 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehavior.kt @@ -54,7 +54,8 @@ open class ListHabitsBehavior @Inject constructor( screen.showNumberPicker( oldValue / 1000, habit.unit, - entry.notes + entry.notes, + timestamp.toDialogDateString(), ) { newValue: Double, newNotes: String, -> val value = (newValue * 1000).roundToInt() commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes)) @@ -159,6 +160,7 @@ open class ListHabitsBehavior @Inject constructor( value: Double, unit: String, notes: String, + dateString: String, callback: NumberPickerCallback ) fun showCheckmarkDialog( diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index ae738f932..5e71c4590 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -110,7 +110,8 @@ class HistoryCardPresenter( screen.showNumberPicker( oldValue / 1000.0, habit.unit, - entry.notes + entry.notes, + timestamp.toDialogDateString(), ) { newValue: Double, newNotes: String -> val thousands = (newValue * 1000).roundToInt() commandRunner.run( @@ -195,6 +196,7 @@ class HistoryCardPresenter( value: Double, unit: String, notes: String, + dateString: String, callback: ListHabitsBehavior.NumberPickerCallback, ) fun showCheckmarkDialog( diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/DateFormats.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/DateFormats.kt index fc18d5374..8b7b4253b 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/DateFormats.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/utils/DateFormats.kt @@ -41,5 +41,8 @@ class DateFormats { @JvmStatic fun getCSVDateFormat(): SimpleDateFormat = fromSkeleton("yyyy-MM-dd", Locale.US) + + @JvmStatic fun getDialogDateFormat(): SimpleDateFormat = + fromSkeleton("MMM dd, yyyy", Locale.US) } } diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt index df58affa6..8192583ad 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsBehaviorTest.kt @@ -79,7 +79,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() { @Test fun testOnEdit() { behavior.onEdit(habit2, getToday()) - verify(screen).showNumberPicker(eq(0.1), eq("miles"), eq(""), picker.capture()) + verify(screen).showNumberPicker(eq(0.1), eq("miles"), eq(""), eq("Jan 25, 2015"), picker.capture()) picker.lastValue.onNumberPicked(100.0, "") val today = getTodayWithOffset() assertThat(habit2.computedEntries.get(today).value, equalTo(100000)) From 8036b10ee6db5cbb6b123ff5fa1b6473db886821 Mon Sep 17 00:00:00 2001 From: Bindu <56578479+vbh@users.noreply.github.com> Date: Sun, 3 Oct 2021 04:36:49 -0700 Subject: [PATCH 056/132] improve yes/no dialog design --- .../common/dialogs/CheckmarkDialog.kt | 93 ++++++++++++++++--- .../habits/list/ListHabitsScreen.kt | 5 +- .../habits/show/ShowHabitActivity.kt | 7 +- .../main/res/drawable/bg_select_button.xml | 14 +++ .../src/main/res/layout/checkmark_dialog.xml | 91 ++++++++++++++++-- .../src/main/res/values/strings.xml | 1 - .../src/main/res/values/styles.xml | 12 +++ .../screens/habits/list/ListHabitsBehavior.kt | 15 ++- .../screens/habits/show/views/HistoryCard.kt | 14 ++- 9 files changed, 224 insertions(+), 28 deletions(-) create mode 100644 uhabits-android/src/main/res/drawable/bg_select_button.xml diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt index 156864caa..800156a62 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt @@ -1,36 +1,63 @@ package org.isoron.uhabits.activities.common.dialogs import android.content.Context +import android.graphics.Color +import android.graphics.Typeface import android.view.LayoutInflater +import android.view.View import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE -import android.widget.EditText +import android.widget.Button import androidx.appcompat.app.AlertDialog 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.models.PaletteColor +import org.isoron.uhabits.core.preferences.Preferences import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior +import org.isoron.uhabits.databinding.CheckmarkDialogBinding import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.utils.InterfaceUtils +import org.isoron.uhabits.utils.StyledResources import javax.inject.Inject class CheckmarkDialog @Inject constructor( - @ActivityContext private val context: Context -) { + @ActivityContext private val context: Context, + private val preferences: Preferences, +) : View.OnClickListener { + + private lateinit var binding: CheckmarkDialogBinding + private lateinit var fontAwesome: Typeface + private val allButtons = mutableListOf