From bda3e42e2b94defcc70e238b00e3073b4ac096dd Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Tue, 22 Dec 2020 12:59:44 -0600 Subject: [PATCH] Create view-model and presenter for TargetCard; reduce boilerplate --- .../habits/show/views/SubtitleCardTest.java | 68 ------------ .../habits/show/views/SubtitleCardTest.kt | 54 +++++++++ .../org/isoron/uhabits/activities/DataView.kt | 45 ++++++++ .../isoron/uhabits/activities/Presenter.kt | 68 ++++++++++++ .../habits/show/ShowHabitPresenter.kt | 88 +-------------- .../habits/show/ShowHabitRootView.kt | 6 +- .../habits/show/ShowHabitViewModel.kt | 3 - .../activities/habits/show/views/NotesCard.kt | 38 ++++--- .../habits/show/views/OverviewCard.kt | 36 +----- .../habits/show/views/SubtitleCard.kt | 27 +---- .../habits/show/views/TargetCard.kt | 105 ++++++++++++++---- .../isoron/uhabits/widgets/BaseWidget.java | 5 + .../isoron/uhabits/widgets/TargetWidget.kt | 20 ++-- .../src/main/res/layout/show_habit.xml | 2 +- 14 files changed, 300 insertions(+), 265 deletions(-) delete mode 100644 android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.java create mode 100644 android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.kt create mode 100644 android/uhabits-android/src/main/java/org/isoron/uhabits/activities/DataView.kt create mode 100644 android/uhabits-android/src/main/java/org/isoron/uhabits/activities/Presenter.kt diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.java deleted file mode 100644 index 63aa74407..000000000 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2016 Á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.habits.show.views; - -import androidx.test.filters.*; -import androidx.test.runner.*; -import android.view.*; - -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import org.isoron.uhabits.*; -import org.isoron.uhabits.core.models.*; -import org.junit.*; -import org.junit.runner.*; - -@RunWith(AndroidJUnit4.class) -@MediumTest -public class SubtitleCardTest extends BaseViewTest -{ - public static final String PATH = "habits/show/SubtitleCard/"; - - private SubtitleCard view; - - private Habit habit; - - @Before - @Override - public void setUp() - { - super.setUp(); - - habit = fixtures.createLongHabit(); - habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); - - view = LayoutInflater - .from(targetContext) - .inflate(R.layout.show_habit, null) - .findViewById(R.id.subtitleCard); - - view.setHabit(habit); - view.refreshData(); - - measureView(view, 800, 200); - } - - @Test - public void testRender() throws Exception - { - assertRenders(view, PATH + "render.png"); - } -} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.kt new file mode 100644 index 000000000..617f33cd3 --- /dev/null +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardTest.kt @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 Á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.habits.show.views + +import android.view.* +import androidx.test.ext.junit.runners.* +import androidx.test.filters.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.habits.show.* +import org.junit.* +import org.junit.runner.* + +@RunWith(AndroidJUnit4::class) +@MediumTest +class SubtitleCardTest : BaseViewTest() { + val PATH = "habits/show/SubtitleCard/" + private lateinit var view: SubtitleCard + + @Before + override fun setUp() { + super.setUp() + view = LayoutInflater + .from(targetContext) + .inflate(R.layout.show_habit, null) + .findViewById(R.id.subtitleCard) + view.onData(ShowHabitViewModel( + question = "Did you meditate this morning?", + reminderText = "8:30 AM", + frequencyText = "3 times in 7 days", + )) + measureView(view, 800f, 200f) + } + + @Test + fun testRender() { + assertRenders(view, PATH + "render.png") + } +} \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/DataView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/DataView.kt new file mode 100644 index 000000000..6332fb92a --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/DataView.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016-2020 Á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 + +import android.content.* +import android.util.* +import android.widget.* + +abstract class DataView( + context: Context, + attrs: AttributeSet, +) : LinearLayout(context, attrs), Presenter.Listener { + + lateinit var presenter: Presenter + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + presenter.addListener(this) + presenter.requestData(this) + } + + override fun onDetachedFromWindow() { + presenter.removeListener(this) + super.onDetachedFromWindow() + } + + abstract override fun onData(data: T) +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/Presenter.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/Presenter.kt new file mode 100644 index 000000000..57290c015 --- /dev/null +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/Presenter.kt @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2016-2020 Á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 + +import org.isoron.uhabits.core.commands.* + +abstract class Presenter( + val commandRunner: CommandRunner, +) : CommandRunner.Listener { + + private val listeners = mutableListOf>() + private var data: M? = null + + fun onResume() { + commandRunner.addListener(this) + data = refresh() + notifyListeners() + } + + abstract fun refresh(): M + + fun onPause() { + commandRunner.removeListener(this) + } + + fun addListener(listener: Listener) { + listeners.add(listener) + } + + fun removeListener(listener: Listener) { + listeners.remove(listener) + } + + fun requestData(listener: Listener) { + if (data == null) data = refresh() + listener.onData(data!!) + } + + override fun onCommandExecuted(command: Command?, refreshKey: Long?) { + data = refresh() + notifyListeners() + } + + private fun notifyListeners() { + for (l in listeners) l.onData(data!!) + } + + interface Listener { + fun onData(data: T) + } +} \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitPresenter.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitPresenter.kt index e117953e9..a0ba4b7b2 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitPresenter.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitPresenter.kt @@ -23,6 +23,7 @@ import android.annotation.* import android.content.* import org.isoron.androidbase.activities.* import org.isoron.uhabits.* +import org.isoron.uhabits.activities.* import org.isoron.uhabits.activities.habits.list.views.* import org.isoron.uhabits.core.commands.* import org.isoron.uhabits.core.models.* @@ -36,47 +37,14 @@ import javax.inject.* class ShowHabitPresenter @Inject constructor( val habit: Habit, - val commandRunner: CommandRunner, val preferences: Preferences, + commandRunner: CommandRunner, @ActivityContext val context: Context, -) : CommandRunner.Listener { +) : Presenter(commandRunner) { - private val listeners = mutableListOf() - private var data = ShowHabitViewModel() private val resources = context.resources - fun onResume() { - commandRunner.addListener(this) - refresh() - notifyListeners() - } - - fun onPause() { - commandRunner.removeListener(this) - } - - fun addListener(listener: Listener) { - listeners.add(listener) - } - - fun removeListener(listener: Listener) { - listeners.remove(listener) - } - - fun requestData(listener: Listener) { - listener.onData(data) - } - - override fun onCommandExecuted(command: Command?, refreshKey: Long?) { - refresh() - notifyListeners() - } - - private fun notifyListeners() { - for (l in listeners) l.onData(data) - } - - private fun refresh() { + override fun refresh(): ShowHabitViewModel { val today = DateUtils.getTodayWithOffset() val lastMonth = today.minus(30) val lastYear = today.minus(365) @@ -92,46 +60,7 @@ class ShowHabitPresenter val scoreLastMonth = scores.getValue(lastMonth).toFloat() val scoreLastYear = scores.getValue(lastYear).toFloat() - val checkmarks = habit.checkmarks - val valueToday = checkmarks.todayValue / 1e3 - val valueThisWeek = checkmarks.getThisWeekValue(preferences.firstWeekday) / 1e3 - val valueThisMonth = checkmarks.thisMonthValue / 1e3 - val valueThisQuarter = checkmarks.thisQuarterValue / 1e3 - val valueThisYear = checkmarks.thisYearValue / 1e3 - - val cal = DateUtils.getStartOfTodayCalendarWithOffset() - val daysInMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH) - val daysInQuarter = 91 - val daysInYear = cal.getActualMaximum(Calendar.DAY_OF_YEAR) - - val targetToday = habit.getTargetValue() / habit.frequency.denominator - val targetThisWeek = targetToday * 7 - val targetThisMonth = targetToday * daysInMonth - val targetThisQuarter = targetToday * daysInQuarter - val targetThisYear = targetToday * daysInYear - - val targetCompleted = ArrayList() - if (habit.frequency.denominator <= 1) targetCompleted.add(valueToday) - if (habit.frequency.denominator <= 7) targetCompleted.add(valueThisWeek) - targetCompleted.add(valueThisMonth) - targetCompleted.add(valueThisQuarter) - targetCompleted.add(valueThisYear) - - val targetTotal = ArrayList() - if (habit.frequency.denominator <= 1) targetTotal.add(targetToday) - if (habit.frequency.denominator <= 7) targetTotal.add(targetThisWeek) - targetTotal.add(targetThisMonth) - targetTotal.add(targetThisQuarter) - targetTotal.add(targetThisYear) - - val targetLabels = ArrayList() - if (habit.frequency.denominator <= 1) targetLabels.add(resources.getString(R.string.today)) - if (habit.frequency.denominator <= 7) targetLabels.add(resources.getString(R.string.week)) - targetLabels.add(resources.getString(R.string.month)) - targetLabels.add(resources.getString(R.string.quarter)) - targetLabels.add(resources.getString(R.string.year)) - - data = ShowHabitViewModel( + return ShowHabitViewModel( title = habit.name, description = habit.description, question = habit.question, @@ -144,9 +73,6 @@ class ShowHabitPresenter targetText = "${habit.targetValue.toShortString()} ${habit.unit}", frequencyText = habit.frequency.format(), reminderText = reminderText, - targetCompleted = targetCompleted, - targetTotal = targetTotal, - targetLabels = targetLabels, ) } @@ -184,8 +110,4 @@ class ShowHabitPresenter resources.getString(R.string.days), ) } - - interface Listener { - fun onData(data: ShowHabitViewModel) - } } \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitRootView.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitRootView.kt index 488555689..a26d8ae3d 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitRootView.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitRootView.kt @@ -23,6 +23,7 @@ import android.view.* import org.isoron.androidbase.activities.* import org.isoron.androidbase.utils.* import org.isoron.uhabits.* +import org.isoron.uhabits.activities.* import org.isoron.uhabits.activities.habits.show.views.* import org.isoron.uhabits.core.models.* import org.isoron.uhabits.databinding.* @@ -35,7 +36,8 @@ class ShowHabitRootView @ActivityContext context: Context, private val habit: Habit, private val presenter: ShowHabitPresenter, -) : BaseRootView(context), ShowHabitPresenter.Listener { + targetCardPresenter: TargetCardPresenter, +) : BaseRootView(context), Presenter.Listener { private var controller: Controller = object : Controller {} private var binding = ShowHabitBinding.inflate(LayoutInflater.from(context)) @@ -47,7 +49,7 @@ class ShowHabitRootView binding.overviewCard.presenter = presenter binding.notesCard.presenter = presenter binding.subtitleCard.presenter = presenter - binding.targetCard.presenter = presenter + binding.targetCard.presenter = targetCardPresenter binding.scoreCard.habit = habit binding.historyCard.habit = habit diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitViewModel.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitViewModel.kt index 80050c18a..ad2fa0704 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitViewModel.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitViewModel.kt @@ -34,7 +34,4 @@ data class ShowHabitViewModel( val targetText: String = "", val frequencyText: String = "", val reminderText: String = "", - val targetCompleted: List = listOf(), - val targetTotal: List = listOf(), - val targetLabels: List = listOf(), ) \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt index 86d9f55ed..b9ad17f1f 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/NotesCard.kt @@ -1,30 +1,34 @@ +/* + * Copyright (C) 2016-2020 Á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.habits.show.views import android.content.* import android.util.* import android.view.* -import android.widget.* +import org.isoron.uhabits.activities.* import org.isoron.uhabits.activities.habits.show.* import org.isoron.uhabits.databinding.* -class NotesCard( - context: Context, - attrs: AttributeSet -) : LinearLayout(context, attrs), ShowHabitPresenter.Listener { +class NotesCard(context: Context, attrs: AttributeSet) : DataView(context, attrs) { private val binding = ShowHabitNotesBinding.inflate(LayoutInflater.from(context), this) - lateinit var presenter: ShowHabitPresenter - - override fun onAttachedToWindow() { - super.onAttachedToWindow() - presenter.addListener(this) - presenter.requestData(this) - } - - override fun onDetachedFromWindow() { - presenter.removeListener(this) - super.onDetachedFromWindow() - } override fun onData(data: ShowHabitViewModel) { if (data.description.isEmpty()) { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt index e12c777f4..5a7515823 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt @@ -21,48 +21,16 @@ package org.isoron.uhabits.activities.habits.show.views import android.content.* import android.util.* import android.view.* -import android.widget.* import org.isoron.androidbase.utils.* import org.isoron.uhabits.* +import org.isoron.uhabits.activities.* import org.isoron.uhabits.activities.habits.show.* import org.isoron.uhabits.databinding.* import org.isoron.uhabits.utils.* -class OverviewCard : LinearLayout, ShowHabitPresenter.Listener { +class OverviewCard(context: Context, attrs: AttributeSet) : DataView(context, attrs) { private val binding = ShowHabitOverviewBinding.inflate(LayoutInflater.from(context), this) - lateinit var presenter: ShowHabitPresenter - - constructor(context: Context) : super(context) { - init() - } - - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { - init() - } - - private fun init() { - if (isInEditMode) initEditMode() - } - - override fun onAttachedToWindow() { - super.onAttachedToWindow() - presenter.addListener(this) - presenter.requestData(this) - } - - override fun onDetachedFromWindow() { - presenter.removeListener(this) - super.onDetachedFromWindow() - } - - private fun initEditMode() { - onData(ShowHabitViewModel( - scoreToday = 0.6f, - scoreMonthDiff = 0.42f, - scoreYearDiff = 0.75f, - )) - } private fun formatPercentageDiff(percentageDiff: Float): String { return String.format("%s%.0f%%", if (percentageDiff >= 0) "+" else "\u2212", diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt index 76907eaa6..c7d0a77f6 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt @@ -21,44 +21,21 @@ package org.isoron.uhabits.activities.habits.show.views import android.content.* import android.util.* import android.view.* -import android.widget.* import org.isoron.androidbase.utils.* +import org.isoron.uhabits.activities.* import org.isoron.uhabits.activities.habits.show.* -import org.isoron.uhabits.core.models.* import org.isoron.uhabits.databinding.* import org.isoron.uhabits.utils.* -class SubtitleCard( - context: Context, - attrs: AttributeSet, -) : LinearLayout(context, attrs), ShowHabitPresenter.Listener { +class SubtitleCard(context: Context, attrs: AttributeSet) : DataView(context, attrs) { private val binding = ShowHabitSubtitleBinding.inflate(LayoutInflater.from(context), this) - lateinit var presenter: ShowHabitPresenter init { val fontAwesome = InterfaceUtils.getFontAwesome(context) binding.targetIcon.typeface = fontAwesome binding.frequencyIcon.typeface = fontAwesome binding.reminderIcon.typeface = fontAwesome - if (isInEditMode) onData(ShowHabitViewModel( - isNumerical = false, - frequencyText = "Every day", - question = "How many steps did you walk today?", - color = PaletteColor(1), - - )) - } - - override fun onAttachedToWindow() { - super.onAttachedToWindow() - presenter.addListener(this) - presenter.requestData(this) - } - - override fun onDetachedFromWindow() { - presenter.removeListener(this) - super.onDetachedFromWindow() } override fun onData(data: ShowHabitViewModel) { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt index 6971b02f3..1f02c23d7 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt @@ -21,36 +21,95 @@ package org.isoron.uhabits.activities.habits.show.views import android.content.* import android.util.* import android.view.* -import android.widget.* -import org.isoron.uhabits.activities.habits.show.* +import org.isoron.androidbase.activities.* +import org.isoron.uhabits.* +import org.isoron.uhabits.activities.* +import org.isoron.uhabits.core.commands.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.preferences.* +import org.isoron.uhabits.core.utils.* import org.isoron.uhabits.databinding.* import org.isoron.uhabits.utils.* +import java.util.* +import javax.inject.* -class TargetCard( - context: Context, - attrs: AttributeSet, -) : LinearLayout(context, attrs), ShowHabitPresenter.Listener { +data class TargetCardViewModel( + val color: PaletteColor, + val values: List = listOf(), + val targets: List = listOf(), + val labels: List = listOf(), +) - private val binding = ShowHabitTargetBinding.inflate(LayoutInflater.from(context), this) - lateinit var presenter: ShowHabitPresenter - - override fun onAttachedToWindow() { - super.onAttachedToWindow() - presenter.addListener(this) - presenter.requestData(this) - } +class TargetCardView(context: Context, attrs: AttributeSet) : DataView(context, attrs) { - override fun onDetachedFromWindow() { - presenter.removeListener(this) - super.onDetachedFromWindow() - } + private val binding = ShowHabitTargetBinding.inflate(LayoutInflater.from(context), this) - override fun onData(data: ShowHabitViewModel) { + override fun onData(data: TargetCardViewModel) { val androidColor = data.color.toThemedAndroidColor(context) - binding.targetChart.setValues(data.targetCompleted) - binding.targetChart.setTargets(data.targetTotal) - binding.targetChart.setLabels(data.targetLabels) + binding.targetChart.setValues(data.values) + binding.targetChart.setTargets(data.targets) + binding.targetChart.setLabels(data.labels) binding.title.setTextColor(androidColor) binding.targetChart.setColor(androidColor) } -} \ No newline at end of file +} + +@ActivityScope +class TargetCardPresenter +@Inject constructor( + val habit: Habit, + val preferences: Preferences, + @ActivityContext val context: Context, + commandRunner: CommandRunner, +) : Presenter(commandRunner) { + + val resources = context.resources + + override fun refresh(): TargetCardViewModel { + val checkmarks = habit.checkmarks + val valueToday = checkmarks.todayValue / 1e3 + val valueThisWeek = checkmarks.getThisWeekValue(preferences.firstWeekday) / 1e3 + val valueThisMonth = checkmarks.thisMonthValue / 1e3 + val valueThisQuarter = checkmarks.thisQuarterValue / 1e3 + val valueThisYear = checkmarks.thisYearValue / 1e3 + + val cal = DateUtils.getStartOfTodayCalendarWithOffset() + val daysInMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH) + val daysInQuarter = 91 + val daysInYear = cal.getActualMaximum(Calendar.DAY_OF_YEAR) + + val targetToday = habit.getTargetValue() / habit.frequency.denominator + val targetThisWeek = targetToday * 7 + val targetThisMonth = targetToday * daysInMonth + val targetThisQuarter = targetToday * daysInQuarter + val targetThisYear = targetToday * daysInYear + + val values = ArrayList() + if (habit.frequency.denominator <= 1) values.add(valueToday) + if (habit.frequency.denominator <= 7) values.add(valueThisWeek) + values.add(valueThisMonth) + values.add(valueThisQuarter) + values.add(valueThisYear) + + val targets = ArrayList() + if (habit.frequency.denominator <= 1) targets.add(targetToday) + if (habit.frequency.denominator <= 7) targets.add(targetThisWeek) + targets.add(targetThisMonth) + targets.add(targetThisQuarter) + targets.add(targetThisYear) + + val labels = ArrayList() + if (habit.frequency.denominator <= 1) labels.add(resources.getString(R.string.today)) + if (habit.frequency.denominator <= 7) labels.add(resources.getString(R.string.week)) + labels.add(resources.getString(R.string.month)) + labels.add(resources.getString(R.string.quarter)) + labels.add(resources.getString(R.string.year)) + + return TargetCardViewModel( + color = habit.color, + values = values, + labels = labels, + targets = targets, + ) + } +} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidget.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidget.java index 043892101..3a4b0ee32 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidget.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/BaseWidget.java @@ -28,6 +28,7 @@ import android.widget.*; import androidx.annotation.NonNull; import org.isoron.uhabits.*; +import org.isoron.uhabits.core.commands.*; import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.intents.*; @@ -49,6 +50,9 @@ public abstract class BaseWidget @NonNull private final Context context; + @NonNull + protected final CommandRunner commandRunner; + @NonNull private WidgetDimensions dimensions; @@ -62,6 +66,7 @@ public abstract class BaseWidget widgetPrefs = app.getComponent().getWidgetPreferences(); prefs = app.getComponent().getPreferences(); + commandRunner = app.getComponent().getCommandRunner(); pendingIntentFactory = app.getComponent().getPendingIntentFactory(); dimensions = new WidgetDimensions(getDefaultWidth(), getDefaultHeight(), getDefaultWidth(), getDefaultHeight()); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt index d197cee24..8890354d0 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/TargetWidget.kt @@ -26,6 +26,7 @@ import android.view.ViewGroup.LayoutParams.* import org.isoron.uhabits.activities.common.views.* import org.isoron.uhabits.activities.habits.show.views.* import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.utils.* import org.isoron.uhabits.widgets.views.* class TargetWidget( @@ -38,15 +39,16 @@ class TargetWidget( pendingIntentFactory.showHabit(habit) override fun refreshData(view: View) { -// val widgetView = view as GraphWidgetView -// widgetView.setBackgroundAlpha(preferedBackgroundAlpha) -// if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f) -// val chart = (widgetView.dataView as TargetChart) -// with(TargetCard.RefreshTask(context, habit, prefs.firstWeekday, chart, null)) { -// onPreExecute() -// doInBackground() -// onPostExecute() -// } + val widgetView = view as GraphWidgetView + widgetView.setBackgroundAlpha(preferedBackgroundAlpha) + if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f) + val chart = (widgetView.dataView as TargetChart) + val presenter = TargetCardPresenter(habit, prefs, context, commandRunner) + val data = presenter.refresh() + chart.setColor(data.color.toThemedAndroidColor(context)) + chart.setTargets(data.targets) + chart.setLabels(data.labels) + chart.setValues(data.values) } override fun buildView(): View { diff --git a/android/uhabits-android/src/main/res/layout/show_habit.xml b/android/uhabits-android/src/main/res/layout/show_habit.xml index ac3f0b14e..7cec786b9 100644 --- a/android/uhabits-android/src/main/res/layout/show_habit.xml +++ b/android/uhabits-android/src/main/res/layout/show_habit.xml @@ -57,7 +57,7 @@ style="@style/Card" android:paddingTop="12dp"/> -