From d53312d261f9b331bb8b9cfc636dca757730b0fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 May 2022 03:04:58 +0000 Subject: [PATCH 1/9] Bump kotlin-stdlib from 1.6.10 to 1.6.21 Bumps [kotlin-stdlib](https://github.com/JetBrains/kotlin) from 1.6.10 to 1.6.21. - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.6.21/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.6.10...v1.6.21) --- 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 df0308761..ba4e0f3f7 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.41") implementation("com.google.guava:guava:31.1-android") - implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.10") + implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.21") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.0") implementation("androidx.annotation:annotation:1.3.0") implementation("com.google.code.findbugs:jsr305:3.0.2") From 45c62b4ab23c720fa18b0de28a9f7ddc29be552b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 May 2022 03:01:19 +0000 Subject: [PATCH 2/9] Bump kxCoroutinesVersion from 1.6.0 to 1.6.1 Bumps `kxCoroutinesVersion` from 1.6.0 to 1.6.1. Updates `kotlinx-coroutines-android` from 1.6.0 to 1.6.1 - [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.6.0...1.6.1) Updates `kotlinx-coroutines-core` from 1.6.0 to 1.6.1 - [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.6.0...1.6.1) --- 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 cef316a10..0251a8351 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -88,7 +88,7 @@ android { dependencies { val daggerVersion = "2.41" val kotlinVersion = "1.6.10" - val kxCoroutinesVersion = "1.6.0" + val kxCoroutinesVersion = "1.6.1" val ktorVersion = "1.6.8" val espressoVersion = "3.4.0" From a6cbd44e422254776158a5336dc86a949e51b156 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 May 2022 17:44:41 +0000 Subject: [PATCH 3/9] Bump kotlinx-coroutines-core-jvm from 1.6.0 to 1.6.1 Bumps [kotlinx-coroutines-core-jvm](https://github.com/Kotlin/kotlinx.coroutines) from 1.6.0 to 1.6.1. - [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.6.0...1.6.1) --- 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 ba4e0f3f7..d7335a596 100644 --- a/uhabits-core/build.gradle.kts +++ b/uhabits-core/build.gradle.kts @@ -46,7 +46,7 @@ kotlin { compileOnly("com.google.dagger:dagger:2.41") implementation("com.google.guava:guava:31.1-android") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.21") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.1") implementation("androidx.annotation:annotation:1.3.0") implementation("com.google.code.findbugs:jsr305:3.0.2") implementation("com.opencsv:opencsv:5.6") From d82a3c145dd998d009b600e4a40088be1c29a908 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 May 2022 17:44:40 +0000 Subject: [PATCH 4/9] Bump kotlin-stdlib-jdk8 from 1.6.10 to 1.6.21 Bumps [kotlin-stdlib-jdk8](https://github.com/JetBrains/kotlin) from 1.6.10 to 1.6.21. - [Release notes](https://github.com/JetBrains/kotlin/releases) - [Changelog](https://github.com/JetBrains/kotlin/blob/v1.6.21/ChangeLog.md) - [Commits](https://github.com/JetBrains/kotlin/compare/v1.6.10...v1.6.21) --- 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 0251a8351..2849d9df7 100644 --- a/uhabits-android/build.gradle.kts +++ b/uhabits-android/build.gradle.kts @@ -87,7 +87,7 @@ android { dependencies { val daggerVersion = "2.41" - val kotlinVersion = "1.6.10" + val kotlinVersion = "1.6.21" val kxCoroutinesVersion = "1.6.1" val ktorVersion = "1.6.8" val espressoVersion = "3.4.0" diff --git a/uhabits-server/build.gradle.kts b/uhabits-server/build.gradle.kts index 19834ad81..c41221430 100644 --- a/uhabits-server/build.gradle.kts +++ b/uhabits-server/build.gradle.kts @@ -34,7 +34,7 @@ application { dependencies { val ktorVersion = "1.6.8" - val kotlinVersion = "1.6.10" + val kotlinVersion = "1.6.21" val logbackVersion = "1.2.11" implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion") implementation("io.ktor:ktor-server-netty:$ktorVersion") From 9d4161a25558c89609d010fc81887dcf057dbd89 Mon Sep 17 00:00:00 2001 From: Jakub Kalinowski Date: Mon, 2 May 2022 01:01:13 +0000 Subject: [PATCH 5/9] Issue 1332: Multiple numeric dialogs appearing (#1356) Co-authored-by: Jakub Kalinowski --- .../common/dialogs/NumberPickerFactory.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) 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 8c62e337a..0ee4dad34 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 @@ -50,7 +50,6 @@ class NumberPickerFactory @Inject constructor( @ActivityContext private val context: Context ) { - @SuppressLint("SetTextI18n") fun create( value: Double, @@ -60,6 +59,8 @@ class NumberPickerFactory frequency: Frequency, callback: ListHabitsBehavior.NumberPickerCallback ): AlertDialog { + clearCurrentDialog() + val inflater = LayoutInflater.from(context) val view = inflater.inflate(R.layout.number_picker_dialog, null) @@ -113,6 +114,7 @@ class NumberPickerFactory } .setOnDismissListener { callback.onNumberPickerDismissed() + currentDialog = null } if (frequency == DAILY) { @@ -153,6 +155,7 @@ class NumberPickerFactory false } + currentDialog = dialog return dialog } @@ -169,6 +172,14 @@ class NumberPickerFactory val inputMethodManager = context.getSystemService(InputMethodManager::class.java) inputMethodManager?.showSoftInput(v, 0) } + + companion object { + private var currentDialog: AlertDialog? = null + fun clearCurrentDialog() { + currentDialog?.dismiss() + currentDialog = null + } + } } class SeparatorWatcherInputFilter(private val nextPicker: NumberPicker) : InputFilter { From 7187214282835bca5fbc3ba9c9cf9f4ee00be9c1 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Tue, 12 Apr 2022 15:01:12 -0500 Subject: [PATCH 6/9] Replace notesIndicator by notes --- .../habits/list/views/CheckmarkButtonView.kt | 4 +-- .../habits/list/views/CheckmarkPanelView.kt | 8 ++--- .../habits/list/views/HabitCardListAdapter.kt | 4 +-- .../habits/list/views/HabitCardListView.kt | 4 +-- .../habits/list/views/HabitCardView.kt | 8 ++--- .../habits/list/views/NumberButtonView.kt | 4 +-- .../habits/list/views/NumberPanelView.kt | 8 ++--- .../isoron/uhabits/utils/ViewExtensions.kt | 4 +-- .../screens/habits/list/HabitCardListCache.kt | 30 +++++++++---------- 9 files changed, 37 insertions(+), 37 deletions(-) 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 a142e3044..604c5720b 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,7 +71,7 @@ class CheckmarkButtonView( invalidate() } - var hasNotes = false + var notes = "" set(value) { field = value invalidate() @@ -179,7 +179,7 @@ class CheckmarkButtonView( canvas.drawText(label, rect.centerX(), rect.centerY(), paint) } - drawNotesIndicator(canvas, color, em, hasNotes) + drawNotesIndicator(canvas, color, em, notes) } } } 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 859cf734d..76df675ec 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 notesIndicators = BooleanArray(0) + var notes = arrayOf() set(values) { field = values setupButtons() @@ -84,9 +84,9 @@ class CheckmarkPanelView( index + dataOffset < values.size -> values[index + dataOffset] else -> UNKNOWN } - button.hasNotes = when { - index + dataOffset < notesIndicators.size -> notesIndicators[index + dataOffset] - else -> false + button.notes = when { + index + dataOffset < notes.size -> notes[index + dataOffset] + else -> "" } 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 b8770d0cb..06412103b 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,9 +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 notes = cache.getNotes(habit.id!!) val selected = selected.contains(habit) - listView!!.bindCardView(holder, habit, score, checkmarks, notesIndicators, selected) + listView!!.bindCardView(holder, habit, score, checkmarks, notes, 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 8ce805098..fd6df425f 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,7 +87,7 @@ class HabitCardListView( habit: Habit, score: Double, checkmarks: IntArray, - notesIndicators: BooleanArray, + notes: Array, selected: Boolean ): View { val cardView = holder.itemView as HabitCardView @@ -99,7 +99,7 @@ class HabitCardListView( cardView.score = score cardView.unit = habit.unit cardView.threshold = habit.targetValue / habit.frequency.denominator - cardView.notesIndicators = notesIndicators + cardView.notes = notes 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 c901dc92f..040e36b68 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 @@ -121,11 +121,11 @@ class HabitCardView( numberPanel.threshold = value } - var notesIndicators - get() = checkmarkPanel.notesIndicators + var notes + get() = checkmarkPanel.notes set(values) { - checkmarkPanel.notesIndicators = values - numberPanel.notesIndicators = values + checkmarkPanel.notes = values + numberPanel.notes = 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 ed00049ee..4d8bdda05 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 @@ -102,7 +102,7 @@ class NumberButtonView( field = value invalidate() } - var hasNotes = false + var notes = "" set(value) { field = value invalidate() @@ -221,7 +221,7 @@ class NumberButtonView( canvas.drawText(units, rect.centerX(), rect.centerY(), pUnit) } - drawNotesIndicator(canvas, color, em, hasNotes) + drawNotesIndicator(canvas, color, em, notes) } } } 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 520401f65..b9be8c820 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 notesIndicators = BooleanArray(0) + var notes = arrayOf() set(values) { field = values setupButtons() @@ -96,9 +96,9 @@ class NumberPanelView( index + dataOffset < values.size -> values[index + dataOffset] else -> 0.0 } - button.hasNotes = when { - index + dataOffset < notesIndicators.size -> notesIndicators[index + dataOffset] - else -> false + button.notes = when { + index + dataOffset < notes.size -> notes[index + dataOffset] + else -> "" } button.color = color button.targetType = targetType 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 b6903b3b0..f406635cd 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 @@ -202,10 +202,10 @@ 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) { +fun View.drawNotesIndicator(canvas: Canvas, color: Int, size: Float, notes: String) { val pNotesIndicator = Paint() pNotesIndicator.color = color - if (hasNotes) { + if (notes.isNotBlank()) { val cy = 0.8f * size canvas.drawCircle(width.toFloat() - cy, cy, 8f, pNotesIndicator) } 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 f1e306758..606f1cb09 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 @@ -79,8 +79,8 @@ class HabitCardListCache @Inject constructor( } @Synchronized - fun getNoteIndicators(habitId: Long): BooleanArray { - return data.notesIndicators[habitId]!! + fun getNotes(habitId: Long): Array { + return data.notes[habitId]!! } @Synchronized @@ -168,7 +168,7 @@ class HabitCardListCache @Inject constructor( data.habits.removeAt(position) data.idToHabit.remove(id) data.checkmarks.remove(id) - data.notesIndicators.remove(id) + data.notes.remove(id) data.scores.remove(id) listener.onItemRemoved(position) } @@ -213,7 +213,7 @@ class HabitCardListCache @Inject constructor( val habits: MutableList val checkmarks: HashMap val scores: HashMap - val notesIndicators: HashMap + val notes: HashMap> @Synchronized fun copyCheckmarksFrom(oldData: CacheData) { @@ -226,10 +226,10 @@ class HabitCardListCache @Inject constructor( @Synchronized fun copyNoteIndicatorsFrom(oldData: CacheData) { - val empty = BooleanArray(checkmarkCount) + val empty = (0..checkmarkCount).map { "" }.toTypedArray() for (id in idToHabit.keys) { - if (oldData.notesIndicators.containsKey(id)) notesIndicators[id] = - oldData.notesIndicators[id]!! else notesIndicators[id] = empty + if (oldData.notes.containsKey(id)) notes[id] = + oldData.notes[id]!! else notes[id] = empty } } @@ -257,7 +257,7 @@ class HabitCardListCache @Inject constructor( habits = LinkedList() checkmarks = HashMap() scores = HashMap() - notesIndicators = HashMap() + notes = HashMap() } } @@ -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 notesIndicators: MutableList = ArrayList() + val notes: MutableList = ArrayList() for ((_, value, note) in habit.computedEntries.getByInterval(dateFrom, today)) { list.add(value) - notesIndicators.add(note.isNotEmpty()) + notes.add(note) } val entries = list.toTypedArray() newData.checkmarks[habit.id] = ArrayUtils.toPrimitive(entries) - newData.notesIndicators[habit.id] = notesIndicators.toBooleanArray() + newData.notes[habit.id] = notes.toTypedArray() runner!!.publishProgress(this, position) } } @@ -333,7 +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]!! + data.notes[id] = newData.notes[id]!! listener.onItemInserted(position) } @@ -361,10 +361,10 @@ 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 oldNoteIndicators = data.notes[id] val newScore = newData.scores[id]!! val newCheckmarks = newData.checkmarks[id]!! - val newNoteIndicators = newData.notesIndicators[id]!! + val newNoteIndicators = newData.notes[id]!! var unchanged = true if (oldScore != newScore) unchanged = false if (!Arrays.equals(oldCheckmarks, newCheckmarks)) unchanged = false @@ -372,7 +372,7 @@ class HabitCardListCache @Inject constructor( if (unchanged) return data.scores[id] = newScore data.checkmarks[id] = newCheckmarks - data.notesIndicators[id] = newNoteIndicators + data.notes[id] = newNoteIndicators listener.onItemChanged(position) } From 0de6896691dea9afa74cd12e19cb90e02bb5d911 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Tue, 12 Apr 2022 15:22:28 -0500 Subject: [PATCH 7/9] Add notes to DelayedToggle, make delay skipable --- .../habits/list/views/EntryButtonViewTest.kt | 2 +- .../habits/list/views/EntryPanelViewTest.kt | 4 ++-- .../habits/list/views/CheckmarkButtonView.kt | 12 ++++++----- .../habits/list/views/CheckmarkPanelView.kt | 4 ++-- .../habits/list/views/HabitCardView.kt | 20 +++++++++---------- .../screens/habits/list/ListHabitsBehavior.kt | 3 +-- .../habits/list/ListHabitsBehaviorTest.kt | 7 ++++++- 7 files changed, 29 insertions(+), 23 deletions(-) diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt index 6184b44a9..e45569d99 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt @@ -43,7 +43,7 @@ class EntryButtonViewTest : BaseViewTest() { view = component.getEntryButtonViewFactory().create().apply { value = Entry.NO color = PaletteUtils.getAndroidTestColor(5) - onToggle = { toggled = true } + onToggle = { _, _, _ -> toggled = true } } measureView(view, dpToPixels(48), dpToPixels(48)) } diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt index 7aff33f0a..f09c48dba 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryPanelViewTest.kt @@ -77,7 +77,7 @@ class EntryPanelViewTest : BaseViewTest() { @Test fun testToggle() { val timestamps = mutableListOf() - view.onToggle = { t, _ -> timestamps.add(t) } + view.onToggle = { t, _, _, _ -> timestamps.add(t) } view.buttons[0].performLongClick() view.buttons[2].performLongClick() view.buttons[3].performLongClick() @@ -88,7 +88,7 @@ class EntryPanelViewTest : BaseViewTest() { fun testToggle_withOffset() { val timestamps = mutableListOf() view.dataOffset = 3 - view.onToggle = { t, _ -> timestamps += t } + view.onToggle = { t, _, _, _ -> timestamps += t } view.buttons[0].performLongClick() view.buttons[2].performLongClick() view.buttons[3].performLongClick() 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 604c5720b..b50d3ab44 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 @@ -44,6 +44,8 @@ import org.isoron.uhabits.utils.sres import org.isoron.uhabits.utils.toMeasureSpec import javax.inject.Inject +const val TOGGLE_DELAY_MILLIS = 2000L + class CheckmarkButtonViewFactory @Inject constructor( @ActivityContext val context: Context, @@ -77,7 +79,7 @@ class CheckmarkButtonView( invalidate() } - var onToggle: (Int) -> Unit = {} + var onToggle: (Int, String, Long) -> Unit = { _, _, _ -> } var onEdit: () -> Unit = {} private var drawer = Drawer() @@ -87,25 +89,25 @@ class CheckmarkButtonView( setOnLongClickListener(this) } - fun performToggle() { + fun performToggle(delay: Long) { value = Entry.nextToggleValue( value = value, isSkipEnabled = preferences.isSkipEnabled, areQuestionMarksEnabled = preferences.areQuestionMarksEnabled ) - onToggle(value) + onToggle(value, notes, delay) performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) invalidate() } override fun onClick(v: View) { - if (preferences.isShortToggleEnabled) performToggle() + if (preferences.isShortToggleEnabled) performToggle(TOGGLE_DELAY_MILLIS) else onEdit() } override fun onLongClick(v: View): Boolean { if (preferences.isShortToggleEnabled) onEdit() - else performToggle() + else performToggle(TOGGLE_DELAY_MILLIS) return true } 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 76df675ec..9a44fde10 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 @@ -60,7 +60,7 @@ class CheckmarkPanelView( setupButtons() } - var onToggle: (Timestamp, Int) -> Unit = { _, _ -> } + var onToggle: (Timestamp, Int, String, Long) -> Unit = { _, _, _, _ -> } set(value) { field = value setupButtons() @@ -89,7 +89,7 @@ class CheckmarkPanelView( else -> "" } button.color = color - button.onToggle = { value -> onToggle(timestamp, value) } + button.onToggle = { value, notes, delay -> onToggle(timestamp, value, notes, delay) } 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 040e36b68..424aae50b 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 @@ -60,7 +60,8 @@ class HabitCardViewFactory data class DelayedToggle( var habit: Habit, var timestamp: Timestamp, - var value: Int + var value: Int, + var notes: String ) class HabitCardView( @@ -159,11 +160,11 @@ class HabitCardView( } checkmarkPanel = checkmarkPanelFactory.create().apply { - onToggle = { timestamp, value -> - triggerRipple(timestamp) + onToggle = { timestamp, value, notes, delay -> + if (delay > 0) triggerRipple(timestamp) habit?.let { - val taskId = queueToggle(it, timestamp, value); - { runPendingToggles(taskId) }.delay(TOGGLE_DELAY_MILLIS) + val taskId = queueToggle(it, timestamp, value, notes); + { runPendingToggles(taskId) }.delay(delay) } } onEdit = { timestamp -> @@ -207,7 +208,7 @@ class HabitCardView( @Synchronized private fun runPendingToggles(id: Int) { if (currentToggleTaskId != id) return - for ((h, t, v) in queuedToggles) behavior.onToggle(h, t, v) + for ((h, t, v, n) in queuedToggles) behavior.onToggle(h, t, v, n) queuedToggles.clear() } @@ -215,10 +216,11 @@ class HabitCardView( private fun queueToggle( it: Habit, timestamp: Timestamp, - value: Int + value: Int, + notes: String, ): Int { currentToggleTaskId += 1 - queuedToggles.add(DelayedToggle(it, timestamp, value)) + queuedToggles.add(DelayedToggle(it, timestamp, value, notes)) return currentToggleTaskId } @@ -308,8 +310,6 @@ class HabitCardView( } companion object { - const val TOGGLE_DELAY_MILLIS = 1000L - fun (() -> Unit).delay(delayInMillis: Long) { Handler(Looper.getMainLooper()).postDelayed(this, delayInMillis) } 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 278d904db..d4aa170cf 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 @@ -123,8 +123,7 @@ open class ListHabitsBehavior @Inject constructor( if (prefs.isFirstRun) onFirstRun() } - fun onToggle(habit: Habit, timestamp: Timestamp?, value: Int) { - val notes = habit.computedEntries.get(timestamp!!).notes + fun onToggle(habit: Habit, timestamp: Timestamp, value: Int, notes: String) { commandRunner.run( CreateRepetitionCommand(habitList, habit, timestamp, value, notes) ) 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 4df4a28f3..02637192a 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 @@ -168,7 +168,12 @@ class ListHabitsBehaviorTest : BaseUnitTest() { @Test fun testOnToggle() { assertTrue(habit1.isCompletedToday()) - behavior.onToggle(habit1, getToday(), Entry.NO) + behavior.onToggle( + habit = habit1, + timestamp = getToday(), + value = Entry.NO, + notes = "" + ) assertFalse(habit1.isCompletedToday()) } } From 825a5f2cb9cf16f806ac8a89f9c6052dd0044e24 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Fri, 15 Apr 2022 08:34:03 -0500 Subject: [PATCH 8/9] Implement CheckmarkPopup --- .../habits/list/views/EntryButtonViewTest.kt | 18 ++- .../habits/list/views/NumberPanelViewTest.kt | 4 +- .../common/dialogs/CheckmarkPopup.kt | 127 ++++++++++++++++++ .../common/dialogs/HistoryEditorDialog.kt | 2 +- .../habits/list/ListHabitsScreen.kt | 36 ++++- .../habits/list/views/CheckmarkButtonView.kt | 9 +- .../habits/list/views/CheckmarkPanelView.kt | 5 +- .../habits/list/views/HabitCardView.kt | 8 +- .../habits/list/views/NumberPanelView.kt | 6 +- .../habits/show/ShowHabitActivity.kt | 46 ++++++- .../isoron/uhabits/utils/ViewExtensions.kt | 43 ++++++ .../main/res/drawable/checkmark_dialog_bg.xml | 27 ++++ .../res/drawable/checkmark_dialog_divider.xml | 25 ++++ .../src/main/res/layout/checkmark_popup.xml | 72 ++++++++++ .../src/main/res/values/styles.xml | 11 ++ .../kotlin/org/isoron/platform/gui/Canvas.kt | 5 + .../screens/habits/list/ListHabitsBehavior.kt | 15 ++- .../screens/habits/show/views/HistoryCard.kt | 86 +++++++----- .../uhabits/core/ui/views/HistoryChart.kt | 10 +- .../habits/list/ListHabitsBehaviorTest.kt | 3 +- .../uhabits/core/ui/views/HistoryChartTest.kt | 44 ++++-- 21 files changed, 530 insertions(+), 72 deletions(-) create mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt create mode 100644 uhabits-android/src/main/res/drawable/checkmark_dialog_bg.xml create mode 100644 uhabits-android/src/main/res/drawable/checkmark_dialog_divider.xml create mode 100644 uhabits-android/src/main/res/layout/checkmark_popup.xml diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt index e45569d99..9b807c764 100644 --- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt +++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/EntryButtonViewTest.kt @@ -36,6 +36,7 @@ class EntryButtonViewTest : BaseViewTest() { lateinit var view: CheckmarkButtonView var toggled = false + var edited = false @Before override fun setUp() { @@ -44,6 +45,7 @@ class EntryButtonViewTest : BaseViewTest() { value = Entry.NO color = PaletteUtils.getAndroidTestColor(5) onToggle = { _, _, _ -> toggled = true } + onEdit = { _ -> edited = true } } measureView(view, dpToPixels(48), dpToPixels(48)) } @@ -70,20 +72,28 @@ class EntryButtonViewTest : BaseViewTest() { fun testClick_withShortToggleDisabled() { prefs.isShortToggleEnabled = false view.performClick() - assertFalse(toggled) + assertTrue(!toggled and edited) } @Test fun testClick_withShortToggleEnabled() { prefs.isShortToggleEnabled = true view.performClick() - assertTrue(toggled) + assertTrue(toggled and !edited) } @Test - fun testLongClick() { + fun testLongClick_withShortToggleDisabled() { + prefs.isShortToggleEnabled = false + view.performLongClick() + assertTrue(toggled and !edited) + } + + @Test + fun testLongClick_withShortToggleEnabled() { + prefs.isShortToggleEnabled = true view.performLongClick() - assertTrue(toggled) + assertTrue(!toggled and edited) } private fun assertRendersCheckedExplicitly() { 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 da0a2eb8a..fb816f4d4 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 @@ -76,7 +76,7 @@ class NumberPanelViewTest : BaseViewTest() { @Test fun testEdit() { val timestamps = mutableListOf() - view.onEdit = { timestamps.plusAssign(it) } + view.onEdit = { _, t -> timestamps.plusAssign(t) } view.buttons[0].performLongClick() view.buttons[2].performLongClick() view.buttons[3].performLongClick() @@ -87,7 +87,7 @@ class NumberPanelViewTest : BaseViewTest() { fun testEdit_withOffset() { val timestamps = mutableListOf() view.dataOffset = 3 - view.onEdit = { timestamps += it } + view.onEdit = { _, t -> timestamps += t } view.buttons[0].performLongClick() view.buttons[2].performLongClick() view.buttons[3].performLongClick() diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt new file mode 100644 index 000000000..85d7fdfc1 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkPopup.kt @@ -0,0 +1,127 @@ +/* + * 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.activities.common.dialogs + +import android.content.Context +import android.graphics.drawable.ColorDrawable +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.View.GONE +import android.widget.PopupWindow +import org.isoron.platform.gui.ScreenLocation +import org.isoron.uhabits.R +import org.isoron.uhabits.core.models.Entry.Companion.NO +import org.isoron.uhabits.core.models.Entry.Companion.SKIP +import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN +import org.isoron.uhabits.core.models.Entry.Companion.YES_AUTO +import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL +import org.isoron.uhabits.core.preferences.Preferences +import org.isoron.uhabits.databinding.CheckmarkPopupBinding +import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome +import org.isoron.uhabits.utils.dimBehind +import org.isoron.uhabits.utils.dp +import org.isoron.uhabits.utils.sres + +const val POPUP_WIDTH = 4 * 48f + 16f +const val POPUP_HEIGHT = 48f * 2.5f + 8f + +class CheckmarkPopup( + private val context: Context, + private val color: Int, + private var notes: String, + private var value: Int, + private val prefs: Preferences, + private val anchor: View, +) { + var onToggle: (Int, String) -> Unit = { _, _ -> } + + private val view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context)).apply { + // Required for round corners + container.clipToOutline = true + } + + init { + initColors() + initTypefaces() + hideDisabledButtons() + populate() + } + + private fun initColors() { + arrayOf(view.yesBtn, view.skipBtn).forEach { + it.setTextColor(color) + } + arrayOf(view.noBtn, view.unknownBtn).forEach { + it.setTextColor(view.root.sres.getColor(R.attr.contrast60)) + } + } + + private fun initTypefaces() { + arrayOf(view.yesBtn, view.noBtn, view.skipBtn, view.unknownBtn).forEach { + it.typeface = getFontAwesome(context) + } + } + + private fun hideDisabledButtons() { + if (!prefs.isSkipEnabled) view.skipBtn.visibility = GONE + if (!prefs.areQuestionMarksEnabled) view.unknownBtn.visibility = GONE + } + + private fun populate() { + val selectedBtn = when (value) { + YES_MANUAL -> view.yesBtn + YES_AUTO -> view.noBtn + NO -> view.noBtn + UNKNOWN -> if (prefs.areQuestionMarksEnabled) view.unknownBtn else view.noBtn + SKIP -> if (prefs.isSkipEnabled) view.skipBtn else view.noBtn + else -> null + } + selectedBtn?.background = ColorDrawable(view.root.sres.getColor(R.attr.contrast40)) + view.notes.setText(notes) + } + + fun show(location: ScreenLocation) { + val popup = PopupWindow() + popup.contentView = view.root + popup.width = view.root.dp(POPUP_WIDTH).toInt() + popup.height = view.root.dp(POPUP_HEIGHT).toInt() + popup.isFocusable = true + popup.elevation = view.root.dp(24f) + fun onClick(v: Int) { + this.value = v + popup.dismiss() + } + view.yesBtn.setOnClickListener { onClick(YES_MANUAL) } + view.noBtn.setOnClickListener { onClick(NO) } + view.skipBtn.setOnClickListener { onClick(SKIP) } + view.unknownBtn.setOnClickListener { onClick(UNKNOWN) } + popup.setOnDismissListener { + onToggle(value, view.notes.text.toString()) + } + popup.showAtLocation( + anchor, + Gravity.NO_GRAVITY, + view.root.dp(location.x.toFloat()).toInt(), + view.root.dp(location.y.toFloat()).toInt(), + ) + popup.dimBehind() + } +} 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 21999d4e1..5cfe90ea6 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 @@ -43,7 +43,7 @@ class HistoryEditorDialog : AppCompatDialogFragment(), CommandRunner.Listener { private lateinit var commandRunner: CommandRunner private lateinit var habit: Habit private lateinit var preferences: Preferences - private lateinit var dataView: AndroidDataView + lateinit var dataView: AndroidDataView private var chart: HistoryChart? = null private var onDateClickedListener: OnDateClickedListener? = null 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 4ec28f9f3..baec44b2f 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 @@ -24,12 +24,16 @@ import android.content.Context import android.content.Intent import androidx.appcompat.app.AppCompatActivity import dagger.Lazy +import org.isoron.platform.gui.ScreenLocation +import org.isoron.platform.gui.toInt import org.isoron.platform.time.LocalDate import org.isoron.uhabits.R import org.isoron.uhabits.activities.common.dialogs.CheckmarkDialog +import org.isoron.uhabits.activities.common.dialogs.CheckmarkPopup import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory +import org.isoron.uhabits.activities.common.dialogs.POPUP_WIDTH import org.isoron.uhabits.activities.habits.edit.HabitTypeDialog import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter import org.isoron.uhabits.core.commands.ArchiveHabitsCommand @@ -43,6 +47,7 @@ import org.isoron.uhabits.core.commands.UnarchiveHabitsCommand import org.isoron.uhabits.core.models.Frequency import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.PaletteColor +import org.isoron.uhabits.core.preferences.Preferences import org.isoron.uhabits.core.tasks.TaskRunner import org.isoron.uhabits.core.ui.ThemeSwitcher import org.isoron.uhabits.core.ui.callbacks.OnColorPickedCallback @@ -63,6 +68,7 @@ import org.isoron.uhabits.tasks.ExportDBTaskFactory import org.isoron.uhabits.tasks.ImportDataTask import org.isoron.uhabits.tasks.ImportDataTaskFactory import org.isoron.uhabits.utils.copyTo +import org.isoron.uhabits.utils.currentTheme import org.isoron.uhabits.utils.restartWithFade import org.isoron.uhabits.utils.showMessage import org.isoron.uhabits.utils.showSendEmailScreen @@ -93,7 +99,9 @@ class ListHabitsScreen private val colorPickerFactory: ColorPickerDialogFactory, private val numberPickerFactory: NumberPickerFactory, private val checkMarkDialog: CheckmarkDialog, - private val behavior: Lazy + private val behavior: Lazy, + private val preferences: Preferences, + private val rootView: Lazy, ) : CommandRunner.Listener, ListHabitsBehavior.Screen, ListHabitsMenuBehavior.Screen, @@ -237,6 +245,32 @@ class ListHabitsScreen numberPickerFactory.create(value, unit, notes, dateString, frequency, callback).show() } + override fun showCheckmarkPopup( + selectedValue: Int, + notes: String, + color: PaletteColor, + location: ScreenLocation, + callback: ListHabitsBehavior.CheckMarkDialogCallback + ) { + val view = rootView.get() + CheckmarkPopup( + context = context, + prefs = preferences, + anchor = view, + color = view.currentTheme().color(color).toInt(), + notes = notes, + value = selectedValue, + ).apply { + onToggle = { value, notes -> callback.onNotesSaved(value, notes) } + show( + ScreenLocation( + x = location.x - POPUP_WIDTH / 2, + y = location.y + ) + ) + } + } + override fun showCheckmarkDialog( selectedValue: Int, notes: String, 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 b50d3ab44..a408f92ee 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 @@ -28,6 +28,7 @@ import android.text.TextPaint import android.view.HapticFeedbackConstants import android.view.View import android.view.View.MeasureSpec.EXACTLY +import org.isoron.platform.gui.ScreenLocation import org.isoron.uhabits.R import org.isoron.uhabits.core.models.Entry import org.isoron.uhabits.core.models.Entry.Companion.NO @@ -38,6 +39,7 @@ import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL import org.isoron.uhabits.core.preferences.Preferences import org.isoron.uhabits.inject.ActivityContext import org.isoron.uhabits.utils.drawNotesIndicator +import org.isoron.uhabits.utils.getCenter import org.isoron.uhabits.utils.getFontAwesome import org.isoron.uhabits.utils.sp import org.isoron.uhabits.utils.sres @@ -81,7 +83,8 @@ class CheckmarkButtonView( var onToggle: (Int, String, Long) -> Unit = { _, _, _ -> } - var onEdit: () -> Unit = {} + var onEdit: (ScreenLocation) -> Unit = { _ -> } + private var drawer = Drawer() init { @@ -102,11 +105,11 @@ class CheckmarkButtonView( override fun onClick(v: View) { if (preferences.isShortToggleEnabled) performToggle(TOGGLE_DELAY_MILLIS) - else onEdit() + else onEdit(getCenter()) } override fun onLongClick(v: View): Boolean { - if (preferences.isShortToggleEnabled) onEdit() + if (preferences.isShortToggleEnabled) onEdit(getCenter()) else performToggle(TOGGLE_DELAY_MILLIS) return true } 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 9a44fde10..62fb3e436 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 @@ -20,6 +20,7 @@ package org.isoron.uhabits.activities.habits.list.views import android.content.Context +import org.isoron.platform.gui.ScreenLocation import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN import org.isoron.uhabits.core.models.Timestamp import org.isoron.uhabits.core.preferences.Preferences @@ -66,7 +67,7 @@ class CheckmarkPanelView( setupButtons() } - var onEdit: (Timestamp) -> Unit = {} + var onEdit: (ScreenLocation, Timestamp) -> Unit = { _, _ -> } set(value) { field = value setupButtons() @@ -90,7 +91,7 @@ class CheckmarkPanelView( } button.color = color button.onToggle = { value, notes, delay -> onToggle(timestamp, value, notes, delay) } - button.onEdit = { onEdit(timestamp) } + button.onEdit = { location -> onEdit(location, timestamp) } } } } 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 424aae50b..7296575e7 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 @@ -167,17 +167,17 @@ class HabitCardView( { runPendingToggles(taskId) }.delay(delay) } } - onEdit = { timestamp -> + onEdit = { location, timestamp -> triggerRipple(timestamp) - habit?.let { behavior.onEdit(it, timestamp) } + habit?.let { behavior.onEdit(location, it, timestamp) } } } numberPanel = numberPanelFactory.create().apply { visibility = GONE - onEdit = { timestamp -> + onEdit = { location, timestamp -> triggerRipple(timestamp) - habit?.let { behavior.onEdit(it, timestamp) } + habit?.let { behavior.onEdit(location, it, timestamp) } } } 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 b9be8c820..dc49b557b 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,11 +20,13 @@ package org.isoron.uhabits.activities.habits.list.views import android.content.Context +import org.isoron.platform.gui.ScreenLocation 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 import org.isoron.uhabits.inject.ActivityContext +import org.isoron.uhabits.utils.getCenter import javax.inject.Inject class NumberPanelViewFactory @@ -78,7 +80,7 @@ class NumberPanelView( setupButtons() } - var onEdit: (Timestamp) -> Unit = {} + var onEdit: (ScreenLocation, Timestamp) -> Unit = { _, _ -> } set(value) { field = value setupButtons() @@ -104,7 +106,7 @@ class NumberPanelView( button.targetType = targetType button.threshold = threshold button.units = units - button.onEdit = { onEdit(timestamp) } + button.onEdit = { onEdit(getCenter(), timestamp) } } } } 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 4af6948ad..95c6bdbbf 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 @@ -27,6 +27,8 @@ import androidx.appcompat.app.AppCompatActivity import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.isoron.platform.gui.ScreenLocation +import org.isoron.platform.gui.toInt import org.isoron.platform.time.LocalDate import org.isoron.uhabits.AndroidDirFinder import org.isoron.uhabits.HabitsApplication @@ -34,9 +36,11 @@ 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.CheckmarkPopup import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog import org.isoron.uhabits.activities.common.dialogs.HistoryEditorDialog import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory +import org.isoron.uhabits.activities.common.dialogs.POPUP_WIDTH import org.isoron.uhabits.core.commands.Command import org.isoron.uhabits.core.commands.CommandRunner import org.isoron.uhabits.core.models.Frequency @@ -49,6 +53,8 @@ import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuPresenter import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitPresenter import org.isoron.uhabits.core.ui.views.OnDateClickedListener import org.isoron.uhabits.intents.IntentFactory +import org.isoron.uhabits.utils.currentTheme +import org.isoron.uhabits.utils.getTopLeftCorner import org.isoron.uhabits.utils.showMessage import org.isoron.uhabits.utils.showSendFileScreen import org.isoron.uhabits.widgets.WidgetUpdater @@ -173,7 +179,14 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { frequency: Frequency, callback: ListHabitsBehavior.NumberPickerCallback ) { - NumberPickerFactory(this@ShowHabitActivity).create(value, unit, notes, dateString, frequency, callback).show() + NumberPickerFactory(this@ShowHabitActivity).create( + value, + unit, + notes, + dateString, + frequency, + callback + ).show() } override fun showCheckmarkDialog( @@ -194,6 +207,37 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener { ).show() } + override fun showCheckmarkPopup( + selectedValue: Int, + notes: String, + preferences: Preferences, + color: PaletteColor, + location: ScreenLocation, + callback: ListHabitsBehavior.CheckMarkDialogCallback + ) { + val dialog = + supportFragmentManager.findFragmentByTag("historyEditor") as HistoryEditorDialog? + ?: return + val view = dialog.dataView + val corner = view.getTopLeftCorner() + CheckmarkPopup( + context = this@ShowHabitActivity, + prefs = preferences, + notes = notes, + color = view.currentTheme().color(color).toInt(), + anchor = view, + value = selectedValue, + ).apply { + onToggle = { v, n -> callback.onNotesSaved(v, n) } + show( + ScreenLocation( + x = corner.x + location.x - POPUP_WIDTH / 2, + y = corner.y + location.y, + ) + ) + } + } + override fun showEditHabitScreen(habit: Habit) { startActivity(IntentFactory().startEditActivity(this@ShowHabitActivity, habit)) } 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 f406635cd..df140aa79 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 @@ -21,6 +21,7 @@ package org.isoron.uhabits.utils import android.app.Activity import android.content.ActivityNotFoundException +import android.content.Context import android.content.Intent import android.graphics.Canvas import android.graphics.Color @@ -32,6 +33,8 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import android.view.WindowManager +import android.widget.PopupWindow import android.widget.RelativeLayout import android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM import android.widget.RelativeLayout.ALIGN_PARENT_TOP @@ -42,6 +45,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.core.content.FileProvider import com.google.android.material.snackbar.Snackbar +import org.isoron.platform.gui.ScreenLocation import org.isoron.platform.gui.toInt import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.R @@ -213,3 +217,42 @@ fun View.drawNotesIndicator(canvas: Canvas, color: Int, size: Float, notes: Stri val View.sres: StyledResources get() = StyledResources(context) + +fun PopupWindow.dimBehind() { + // https://stackoverflow.com/questions/35874001/dim-the-background-using-popupwindow-in-android + val container = contentView.rootView + val context = contentView.context + val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager + val p = container.layoutParams as WindowManager.LayoutParams + p.flags = p.flags or WindowManager.LayoutParams.FLAG_DIM_BEHIND + p.dimAmount = 0.5f + wm.updateViewLayout(container, p) +} + +/** + * Returns the absolute screen coordinates for the center of this view (in density-independent + * pixels). + */ +fun View.getCenter(): ScreenLocation { + val density = resources.displayMetrics.density + val loc = IntArray(2) + this.getLocationInWindow(loc) + return ScreenLocation( + x = ((loc[0] + width / 2) / density).toDouble(), + y = ((loc[1] + height / 2) / density).toDouble(), + ) +} + +/** + * Returns the absolute screen coordinates for the top left corner of this view (in + * density-independent pixels). + */ +fun View.getTopLeftCorner(): ScreenLocation { + val density = resources.displayMetrics.density + val loc = IntArray(2) + this.getLocationInWindow(loc) + return ScreenLocation( + x = (loc[0] / density).toDouble(), + y = (loc[1] / density).toDouble(), + ) +} diff --git a/uhabits-android/src/main/res/drawable/checkmark_dialog_bg.xml b/uhabits-android/src/main/res/drawable/checkmark_dialog_bg.xml new file mode 100644 index 000000000..cea93a111 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/checkmark_dialog_bg.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/uhabits-android/src/main/res/drawable/checkmark_dialog_divider.xml b/uhabits-android/src/main/res/drawable/checkmark_dialog_divider.xml new file mode 100644 index 000000000..ef44b9f19 --- /dev/null +++ b/uhabits-android/src/main/res/drawable/checkmark_dialog_divider.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/uhabits-android/src/main/res/layout/checkmark_popup.xml b/uhabits-android/src/main/res/layout/checkmark_popup.xml new file mode 100644 index 000000000..f1aa569a6 --- /dev/null +++ b/uhabits-android/src/main/res/layout/checkmark_popup.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + diff --git a/uhabits-android/src/main/res/values/styles.xml b/uhabits-android/src/main/res/values/styles.xml index 147d05d24..474d62d16 100644 --- a/uhabits-android/src/main/res/values/styles.xml +++ b/uhabits-android/src/main/res/values/styles.xml @@ -399,4 +399,15 @@ true + + diff --git a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/gui/Canvas.kt b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/gui/Canvas.kt index faab51b87..1459956ce 100644 --- a/uhabits-core/src/commonMain/kotlin/org/isoron/platform/gui/Canvas.kt +++ b/uhabits-core/src/commonMain/kotlin/org/isoron/platform/gui/Canvas.kt @@ -29,6 +29,11 @@ enum class Font { FONT_AWESOME } +data class ScreenLocation( + val x: Double, + val y: Double, +) + interface Canvas { fun setColor(color: Color) fun drawLine(x1: Double, y1: Double, x2: Double, y2: Double) 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 d4aa170cf..14fa256e9 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 @@ -18,6 +18,7 @@ */ package org.isoron.uhabits.core.ui.screens.habits.list +import org.isoron.platform.gui.ScreenLocation import org.isoron.platform.time.LocalDate import org.isoron.uhabits.core.commands.CommandRunner import org.isoron.uhabits.core.commands.CreateRepetitionCommand @@ -50,7 +51,7 @@ open class ListHabitsBehavior @Inject constructor( screen.showHabitScreen(h) } - fun onEdit(habit: Habit, timestamp: Timestamp?) { + fun onEdit(location: ScreenLocation, habit: Habit, timestamp: Timestamp?) { val entry = habit.computedEntries.get(timestamp!!) if (habit.type == HabitType.NUMERICAL) { val oldValue = entry.value.toDouble() @@ -65,12 +66,11 @@ open class ListHabitsBehavior @Inject constructor( commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, value, newNotes)) } } else { - screen.showCheckmarkDialog( + screen.showCheckmarkPopup( entry.value, entry.notes, - timestamp.toLocalDate(), - timestamp.toDialogDateString(), habit.color, + location, ) { newValue, newNotes -> commandRunner.run(CreateRepetitionCommand(habitList, habit, timestamp, newValue, newNotes)) } @@ -171,6 +171,13 @@ open class ListHabitsBehavior @Inject constructor( frequency: Frequency, callback: NumberPickerCallback ) + fun showCheckmarkPopup( + selectedValue: Int, + notes: String, + color: PaletteColor, + location: ScreenLocation, + callback: CheckMarkDialogCallback + ) fun showCheckmarkDialog( selectedValue: Int, notes: 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 97d149906..7c932fb42 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 @@ -19,6 +19,7 @@ package org.isoron.uhabits.core.ui.screens.habits.show.views +import org.isoron.platform.gui.ScreenLocation import org.isoron.platform.time.DayOfWeek import org.isoron.platform.time.LocalDate import org.isoron.uhabits.core.commands.CommandRunner @@ -65,55 +66,65 @@ class HistoryCardPresenter( val screen: Screen, ) : OnDateClickedListener { - override fun onDateLongPress(date: LocalDate) { + override fun onDateLongPress(location: ScreenLocation, date: LocalDate) { val timestamp = Timestamp.fromLocalDate(date) screen.showFeedback() if (habit.isNumerical) { showNumberPicker(timestamp) } else { - val entry = habit.computedEntries.get(timestamp) - val nextValue = Entry.nextToggleValue( - value = entry.value, - isSkipEnabled = preferences.isSkipEnabled, - areQuestionMarksEnabled = preferences.areQuestionMarksEnabled - ) + if (preferences.isShortToggleEnabled) showCheckmarkPopup(location, timestamp) + else toggle(timestamp) + } + } + + override fun onDateShortPress(location: ScreenLocation, date: LocalDate) { + val timestamp = Timestamp.fromLocalDate(date) + screen.showFeedback() + if (habit.isNumerical) { + showNumberPicker(timestamp) + } else { + if (preferences.isShortToggleEnabled) toggle(timestamp) + else showCheckmarkPopup(location, timestamp) + } + } + + private fun showCheckmarkPopup(location: ScreenLocation, timestamp: Timestamp) { + val entry = habit.computedEntries.get(timestamp) + screen.showCheckmarkPopup( + entry.value, + entry.notes, + preferences, + habit.color, + location, + ) { newValue, newNotes -> commandRunner.run( CreateRepetitionCommand( habitList, habit, timestamp, - nextValue, - entry.notes, + newValue, + newNotes, ), ) } } - override fun onDateShortPress(date: LocalDate) { - val timestamp = Timestamp.fromLocalDate(date) - screen.showFeedback() - if (habit.isNumerical) { - showNumberPicker(timestamp) - } else { - val entry = habit.computedEntries.get(timestamp) - screen.showCheckmarkDialog( - entry.value, + private fun toggle(timestamp: Timestamp) { + 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, - timestamp.toLocalDate(), - preferences, - habit.color, - ) { newValue, newNotes -> - commandRunner.run( - CreateRepetitionCommand( - habitList, - habit, - timestamp, - newValue, - newNotes, - ), - ) - } - } + ), + ) } private fun showNumberPicker(timestamp: Timestamp) { @@ -211,5 +222,14 @@ class HistoryCardPresenter( color: PaletteColor, callback: ListHabitsBehavior.CheckMarkDialogCallback, ) + + fun showCheckmarkPopup( + selectedValue: Int, + notes: String, + preferences: Preferences, + color: PaletteColor, + location: ScreenLocation, + callback: ListHabitsBehavior.CheckMarkDialogCallback, + ) } } 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 a752e271c..8d7435540 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 @@ -22,6 +22,7 @@ package org.isoron.uhabits.core.ui.views import org.isoron.platform.gui.Canvas import org.isoron.platform.gui.Color import org.isoron.platform.gui.DataView +import org.isoron.platform.gui.ScreenLocation import org.isoron.platform.gui.TextAlign import org.isoron.platform.time.DayOfWeek import org.isoron.platform.time.LocalDate @@ -33,8 +34,8 @@ import kotlin.math.min import kotlin.math.round interface OnDateClickedListener { - fun onDateShortPress(date: LocalDate) {} - fun onDateLongPress(date: LocalDate) {} + fun onDateShortPress(location: ScreenLocation, date: LocalDate) {} + fun onDateLongPress(location: ScreenLocation, date: LocalDate) {} } class HistoryChart( @@ -90,10 +91,11 @@ class HistoryChart( if (x - padding < 0 || row == 0 || row > 7 || col == nColumns) return val clickedDate = topLeftDate.plus(offset) if (clickedDate.isNewerThan(today)) return + val location = ScreenLocation(x, y) if (isLongClick) { - onDateClickedListener.onDateLongPress(clickedDate) + onDateClickedListener.onDateLongPress(location, clickedDate) } else { - onDateClickedListener.onDateShortPress(clickedDate) + onDateClickedListener.onDateShortPress(location, clickedDate) } } 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 02637192a..c147fa524 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 @@ -31,6 +31,7 @@ import junit.framework.Assert.assertTrue import org.apache.commons.io.FileUtils import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.core.IsEqual.equalTo +import org.isoron.platform.gui.ScreenLocation import org.isoron.uhabits.core.BaseUnitTest import org.isoron.uhabits.core.models.Entry import org.isoron.uhabits.core.models.Frequency @@ -79,7 +80,7 @@ class ListHabitsBehaviorTest : BaseUnitTest() { @Test fun testOnEdit() { - behavior.onEdit(habit2, getToday()) + behavior.onEdit(ScreenLocation(0.0, 0.0), habit2, getToday()) verify(screen).showNumberPicker( eq(0.1), eq("miles"), 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 8a9d523ab..8373805b7 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 @@ -24,6 +24,7 @@ import com.nhaarman.mockitokotlin2.reset import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions import kotlinx.coroutines.runBlocking +import org.isoron.platform.gui.ScreenLocation import org.isoron.platform.gui.assertRenders import org.isoron.platform.time.DayOfWeek import org.isoron.platform.time.DayOfWeek.SUNDAY @@ -73,8 +74,7 @@ class HistoryChartTest { else -> OFF } }, - notesIndicators = MutableList(85) { - index: Int -> + notesIndicators = MutableList(85) { index: Int -> index % 3 == 0 } ) @@ -90,20 +90,32 @@ class HistoryChartTest { // Click top left date view.onClick(20.0, 46.0) - verify(dateClickedListener).onDateShortPress(LocalDate(2014, 10, 26)) + verify(dateClickedListener).onDateShortPress( + ScreenLocation(20.0, 46.0), + LocalDate(2014, 10, 26) + ) reset(dateClickedListener) view.onClick(2.0, 28.0) - verify(dateClickedListener).onDateShortPress(LocalDate(2014, 10, 26)) + verify(dateClickedListener).onDateShortPress( + ScreenLocation(2.0, 28.0), + LocalDate(2014, 10, 26) + ) reset(dateClickedListener) // Click date in the middle view.onClick(163.0, 113.0) - verify(dateClickedListener).onDateShortPress(LocalDate(2014, 12, 10)) + verify(dateClickedListener).onDateShortPress( + ScreenLocation(163.0, 113.0), + LocalDate(2014, 12, 10) + ) reset(dateClickedListener) // Click today view.onClick(336.0, 37.0) - verify(dateClickedListener).onDateShortPress(LocalDate(2015, 1, 25)) + verify(dateClickedListener).onDateShortPress( + ScreenLocation(336.0, 37.0), + LocalDate(2015, 1, 25) + ) reset(dateClickedListener) // Click header @@ -121,20 +133,32 @@ class HistoryChartTest { // Click top left date view.onLongClick(20.0, 46.0) - verify(dateClickedListener).onDateLongPress(LocalDate(2014, 10, 26)) + verify(dateClickedListener).onDateLongPress( + ScreenLocation(20.0, 46.0), + LocalDate(2014, 10, 26) + ) reset(dateClickedListener) view.onLongClick(2.0, 28.0) - verify(dateClickedListener).onDateLongPress(LocalDate(2014, 10, 26)) + verify(dateClickedListener).onDateLongPress( + ScreenLocation(2.0, 28.0), + LocalDate(2014, 10, 26) + ) reset(dateClickedListener) // Click date in the middle view.onLongClick(163.0, 113.0) - verify(dateClickedListener).onDateLongPress(LocalDate(2014, 12, 10)) + verify(dateClickedListener).onDateLongPress( + ScreenLocation(163.0, 113.0), + LocalDate(2014, 12, 10) + ) reset(dateClickedListener) // Click today view.onLongClick(336.0, 37.0) - verify(dateClickedListener).onDateLongPress(LocalDate(2015, 1, 25)) + verify(dateClickedListener).onDateLongPress( + ScreenLocation(336.0, 37.0), + LocalDate(2015, 1, 25) + ) reset(dateClickedListener) // Click header From f04e37e9050cf918f9b7643814ec893c61ba3992 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Fri, 15 Apr 2022 08:38:13 -0500 Subject: [PATCH 9/9] Remove CheckmarkDialog --- .../common/dialogs/CheckmarkDialog.kt | 119 ------------------ .../habits/list/ListHabitsScreen.kt | 21 ---- .../habits/show/ShowHabitActivity.kt | 20 --- .../src/main/res/layout/checkmark_dialog.xml | 95 -------------- .../src/main/res/values/styles.xml | 12 -- .../screens/habits/list/ListHabitsBehavior.kt | 10 -- .../screens/habits/show/views/HistoryCard.kt | 9 -- 7 files changed, 286 deletions(-) delete mode 100644 uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt delete 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 deleted file mode 100644 index 4e62b614b..000000000 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/dialogs/CheckmarkDialog.kt +++ /dev/null @@ -1,119 +0,0 @@ -package org.isoron.uhabits.activities.common.dialogs - -import android.content.Context -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.Button -import androidx.appcompat.app.AlertDialog -import org.isoron.platform.gui.toInt -import org.isoron.platform.time.JavaLocalDateFormatter -import org.isoron.platform.time.LocalDate -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.core.ui.views.Theme -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 java.util.Locale -import javax.inject.Inject - -class CheckmarkDialog -@Inject constructor( - @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