mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
ShowHabitActivity: Move presenters and view models to uhabits-core
This commit is contained in:
@@ -23,8 +23,8 @@ import androidx.test.ext.junit.runners.*;
|
|||||||
import androidx.test.filters.*;
|
import androidx.test.filters.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.activities.habits.show.views.*;
|
|
||||||
import org.isoron.uhabits.core.models.*;
|
import org.isoron.uhabits.core.models.*;
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.*;
|
||||||
import org.isoron.uhabits.utils.*;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.junit.runner.*;
|
import org.junit.runner.*;
|
||||||
@@ -49,8 +49,8 @@ public class ScoreChartTest extends BaseViewTest
|
|||||||
|
|
||||||
fixtures.purgeHabits(habitList);
|
fixtures.purgeHabits(habitList);
|
||||||
habit = fixtures.createLongHabit();
|
habit = fixtures.createLongHabit();
|
||||||
presenter = new ScoreCardPresenter(habit, prefs.getFirstWeekday());
|
presenter = new ScoreCardPresenter();
|
||||||
ScoreCardViewModel model = presenter.present(0);
|
ScoreCardViewModel model = presenter.present(habit, prefs.getFirstWeekday(), 0);
|
||||||
|
|
||||||
view = new ScoreChart(targetContext);
|
view = new ScoreChart(targetContext);
|
||||||
view.setScores(model.getScores());
|
view.setScores(model.getScores());
|
||||||
@@ -84,7 +84,7 @@ public class ScoreChartTest extends BaseViewTest
|
|||||||
@Test
|
@Test
|
||||||
public void testRender_withMonthlyBucket() throws Throwable
|
public void testRender_withMonthlyBucket() throws Throwable
|
||||||
{
|
{
|
||||||
ScoreCardViewModel model = presenter.present(2);
|
ScoreCardViewModel model = presenter.present(habit, prefs.getFirstWeekday(), 2);
|
||||||
view.setScores(model.getScores());
|
view.setScores(model.getScores());
|
||||||
view.setBucketSize(model.getBucketSize());
|
view.setBucketSize(model.getBucketSize());
|
||||||
view.invalidate();
|
view.invalidate();
|
||||||
@@ -102,7 +102,7 @@ public class ScoreChartTest extends BaseViewTest
|
|||||||
@Test
|
@Test
|
||||||
public void testRender_withYearlyBucket() throws Throwable
|
public void testRender_withYearlyBucket() throws Throwable
|
||||||
{
|
{
|
||||||
ScoreCardViewModel model = presenter.present(4);
|
ScoreCardViewModel model = presenter.present(habit, prefs.getFirstWeekday(), 4);
|
||||||
view.setScores(model.getScores());
|
view.setScores(model.getScores());
|
||||||
view.setBucketSize(model.getBucketSize());
|
view.setBucketSize(model.getBucketSize());
|
||||||
view.invalidate();
|
view.invalidate();
|
||||||
|
|||||||
@@ -24,15 +24,16 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.FrequencyCardPresenter
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class FrequencyCardTest : BaseViewTest() {
|
class FrequencyCardViewTest : BaseViewTest() {
|
||||||
val PATH = "habits/show/FrequencyCard/"
|
val PATH = "habits/show/FrequencyCard/"
|
||||||
private lateinit var view: FrequencyCard
|
private lateinit var view: FrequencyCardView
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
@@ -41,8 +42,8 @@ class FrequencyCardTest : BaseViewTest() {
|
|||||||
view = LayoutInflater
|
view = LayoutInflater
|
||||||
.from(targetContext)
|
.from(targetContext)
|
||||||
.inflate(R.layout.show_habit, null)
|
.inflate(R.layout.show_habit, null)
|
||||||
.findViewById<View>(R.id.frequencyCard) as FrequencyCard
|
.findViewById<View>(R.id.frequencyCard) as FrequencyCardView
|
||||||
view.update(FrequencyCardPresenter(habit, 0).present())
|
view.update(FrequencyCardPresenter().present(habit = habit, firstWeekday = 0))
|
||||||
measureView(view, 800f, 600f)
|
measureView(view, 800f, 600f)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,14 +24,15 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.HistoryCardPresenter
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class HistoryCardTest : BaseViewTest() {
|
class HistoryCardViewTest : BaseViewTest() {
|
||||||
private lateinit var view: HistoryCard
|
private lateinit var view: HistoryCardView
|
||||||
val PATH = "habits/show/HistoryCard/"
|
val PATH = "habits/show/HistoryCard/"
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -41,13 +42,13 @@ class HistoryCardTest : BaseViewTest() {
|
|||||||
view = LayoutInflater
|
view = LayoutInflater
|
||||||
.from(targetContext)
|
.from(targetContext)
|
||||||
.inflate(R.layout.show_habit, null)
|
.inflate(R.layout.show_habit, null)
|
||||||
.findViewById<View>(R.id.historyCard) as HistoryCard
|
.findViewById<View>(R.id.historyCard) as HistoryCardView
|
||||||
view.update(
|
view.update(
|
||||||
HistoryCardPresenter(
|
HistoryCardPresenter().present(
|
||||||
habit = habit,
|
habit = habit,
|
||||||
firstWeekday = 1,
|
firstWeekday = 1,
|
||||||
isSkipEnabled = false
|
isSkipEnabled = false
|
||||||
).present()
|
)
|
||||||
)
|
)
|
||||||
measureView(view, 800f, 600f)
|
measureView(view, 800f, 600f)
|
||||||
}
|
}
|
||||||
@@ -25,6 +25,7 @@ import androidx.test.filters.MediumTest
|
|||||||
import org.hamcrest.Matchers.equalTo
|
import org.hamcrest.Matchers.equalTo
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.NotesCardViewModel
|
||||||
import org.junit.Assert.assertThat
|
import org.junit.Assert.assertThat
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import androidx.test.filters.MediumTest
|
|||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.OverviewCardViewModel
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|||||||
@@ -24,15 +24,16 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class ScoreCardTest : BaseViewTest() {
|
class ScoreCardViewTest : BaseViewTest() {
|
||||||
val PATH = "habits/show/ScoreCard/"
|
val PATH = "habits/show/ScoreCard/"
|
||||||
private lateinit var view: ScoreCard
|
private lateinit var view: ScoreCardView
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
@@ -41,8 +42,14 @@ class ScoreCardTest : BaseViewTest() {
|
|||||||
view = LayoutInflater
|
view = LayoutInflater
|
||||||
.from(targetContext)
|
.from(targetContext)
|
||||||
.inflate(R.layout.show_habit, null)
|
.inflate(R.layout.show_habit, null)
|
||||||
.findViewById<View>(R.id.scoreCard) as ScoreCard
|
.findViewById<View>(R.id.scoreCard) as ScoreCardView
|
||||||
view.update(ScoreCardPresenter(habit, 0).present(0))
|
view.update(
|
||||||
|
ScoreCardPresenter().present(
|
||||||
|
habit = habit,
|
||||||
|
firstWeekday = 0,
|
||||||
|
spinnerPosition = 0,
|
||||||
|
)
|
||||||
|
)
|
||||||
measureView(view, 800f, 600f)
|
measureView(view, 800f, 600f)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,6 +24,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.StreakCardViewModel
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.models.Frequency
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.isoron.uhabits.core.models.Reminder
|
||||||
|
import org.isoron.uhabits.core.models.WeekdayList.EVERY_DAY
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.SubtitleCardViewModel
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@@ -44,11 +48,12 @@ class SubtitleCardViewTest : BaseViewTest() {
|
|||||||
view.update(
|
view.update(
|
||||||
SubtitleCardViewModel(
|
SubtitleCardViewModel(
|
||||||
color = PaletteColor(7),
|
color = PaletteColor(7),
|
||||||
frequencyText = "3 times in 7 days",
|
frequency = Frequency(3, 7),
|
||||||
isNumerical = false,
|
isNumerical = false,
|
||||||
question = "Did you meditate this morning?",
|
question = "Did you meditate this morning?",
|
||||||
reminderText = "8:30 AM",
|
reminder = Reminder(8, 30, EVERY_DAY),
|
||||||
targetText = "",
|
unit = "",
|
||||||
|
targetValue = 0.0,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
measureView(view, 800f, 200f)
|
measureView(view, 800f, 200f)
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ import android.util.*;
|
|||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.activities.common.views.*;
|
import org.isoron.uhabits.activities.common.views.*;
|
||||||
import org.isoron.uhabits.activities.habits.show.views.*;
|
|
||||||
import org.isoron.uhabits.core.commands.*;
|
import org.isoron.uhabits.core.commands.*;
|
||||||
import org.isoron.uhabits.core.models.*;
|
import org.isoron.uhabits.core.models.*;
|
||||||
import org.isoron.uhabits.core.preferences.*;
|
import org.isoron.uhabits.core.preferences.*;
|
||||||
import org.isoron.uhabits.core.tasks.*;
|
import org.isoron.uhabits.core.tasks.*;
|
||||||
import org.isoron.uhabits.core.ui.callbacks.*;
|
import org.isoron.uhabits.core.ui.callbacks.*;
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.*;
|
||||||
import org.isoron.uhabits.utils.*;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.jetbrains.annotations.*;
|
import org.jetbrains.annotations.*;
|
||||||
|
|
||||||
@@ -179,11 +179,11 @@ public class HistoryEditorDialog extends AppCompatDialogFragment
|
|||||||
@Override
|
@Override
|
||||||
public void doInBackground()
|
public void doInBackground()
|
||||||
{
|
{
|
||||||
HistoryCardViewModel model = new HistoryCardPresenter(
|
HistoryCardViewModel model = new HistoryCardPresenter().present(
|
||||||
habit,
|
habit,
|
||||||
prefs.getFirstWeekday(),
|
prefs.getFirstWeekday(),
|
||||||
prefs.isSkipEnabled()
|
prefs.isSkipEnabled()
|
||||||
).present();
|
);
|
||||||
checkmarks = model.getEntries();
|
checkmarks = model.getEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,16 +34,22 @@ import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialogFactory
|
|||||||
import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory
|
import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory
|
||||||
import org.isoron.uhabits.core.commands.Command
|
import org.isoron.uhabits.core.commands.Command
|
||||||
import org.isoron.uhabits.core.commands.CommandRunner
|
import org.isoron.uhabits.core.commands.CommandRunner
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitBehavior
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitBehavior
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuBehavior
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuBehavior
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitPresenter
|
||||||
import org.isoron.uhabits.intents.IntentFactory
|
import org.isoron.uhabits.intents.IntentFactory
|
||||||
|
|
||||||
class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
||||||
|
|
||||||
|
private val presenter = ShowHabitPresenter()
|
||||||
|
|
||||||
private lateinit var commandRunner: CommandRunner
|
private lateinit var commandRunner: CommandRunner
|
||||||
private lateinit var menu: ShowHabitMenu
|
private lateinit var menu: ShowHabitMenu
|
||||||
private lateinit var presenter: ShowHabitPresenter
|
|
||||||
private lateinit var view: ShowHabitView
|
private lateinit var view: ShowHabitView
|
||||||
|
private lateinit var habit: Habit
|
||||||
|
private lateinit var preferences: Preferences
|
||||||
|
|
||||||
private val scope = CoroutineScope(Dispatchers.Main)
|
private val scope = CoroutineScope(Dispatchers.Main)
|
||||||
|
|
||||||
@@ -52,17 +58,12 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
|||||||
|
|
||||||
val appComponent = (applicationContext as HabitsApplication).component
|
val appComponent = (applicationContext as HabitsApplication).component
|
||||||
val habitList = appComponent.habitList
|
val habitList = appComponent.habitList
|
||||||
val habit = habitList.getById(ContentUris.parseId(intent.data!!))!!
|
habit = habitList.getById(ContentUris.parseId(intent.data!!))!!
|
||||||
val preferences = appComponent.preferences
|
preferences = appComponent.preferences
|
||||||
commandRunner = appComponent.commandRunner
|
commandRunner = appComponent.commandRunner
|
||||||
AndroidThemeSwitcher(this, preferences).apply()
|
AndroidThemeSwitcher(this, preferences).apply()
|
||||||
|
|
||||||
view = ShowHabitView(this)
|
view = ShowHabitView(this)
|
||||||
presenter = ShowHabitPresenter(
|
|
||||||
context = this,
|
|
||||||
habit = habit,
|
|
||||||
preferences = appComponent.preferences,
|
|
||||||
)
|
|
||||||
|
|
||||||
val screen = ShowHabitScreen(
|
val screen = ShowHabitScreen(
|
||||||
activity = this,
|
activity = this,
|
||||||
@@ -129,7 +130,12 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
|
|||||||
|
|
||||||
fun refresh() {
|
fun refresh() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
view.update(presenter.present())
|
view.update(
|
||||||
|
presenter.present(
|
||||||
|
habit = habit,
|
||||||
|
preferences = preferences,
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,45 +22,10 @@ package org.isoron.uhabits.activities.habits.show
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import org.isoron.uhabits.activities.habits.show.views.BarCardPresenter
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitViewModel
|
||||||
import org.isoron.uhabits.activities.habits.show.views.BarCardViewModel
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.FrequencyCardPresenter
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.FrequencyCardViewModel
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.HistoryCardPresenter
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.HistoryCardViewModel
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.NotesCardPresenter
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.NotesCardViewModel
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.OverviewCardPresenter
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.OverviewCardViewModel
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.ScoreCardPresenter
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.ScoreCardViewModel
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.StreakCardViewModel
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.StreakCartPresenter
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.SubtitleCardPresenter
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.SubtitleCardViewModel
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.TargetCardPresenter
|
|
||||||
import org.isoron.uhabits.activities.habits.show.views.TargetCardViewModel
|
|
||||||
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.databinding.ShowHabitBinding
|
import org.isoron.uhabits.databinding.ShowHabitBinding
|
||||||
import org.isoron.uhabits.utils.setupToolbar
|
import org.isoron.uhabits.utils.setupToolbar
|
||||||
|
|
||||||
data class ShowHabitViewModel(
|
|
||||||
val title: String = "",
|
|
||||||
val isNumerical: Boolean = false,
|
|
||||||
val color: PaletteColor = PaletteColor(1),
|
|
||||||
val subtitle: SubtitleCardViewModel,
|
|
||||||
val overview: OverviewCardViewModel,
|
|
||||||
val notes: NotesCardViewModel,
|
|
||||||
val target: TargetCardViewModel,
|
|
||||||
val streaks: StreakCardViewModel,
|
|
||||||
val scores: ScoreCardViewModel,
|
|
||||||
val frequency: FrequencyCardViewModel,
|
|
||||||
val history: HistoryCardViewModel,
|
|
||||||
val bar: BarCardViewModel,
|
|
||||||
)
|
|
||||||
|
|
||||||
class ShowHabitView(context: Context) : FrameLayout(context) {
|
class ShowHabitView(context: Context) : FrameLayout(context) {
|
||||||
private val binding = ShowHabitBinding.inflate(LayoutInflater.from(context))
|
private val binding = ShowHabitBinding.inflate(LayoutInflater.from(context))
|
||||||
|
|
||||||
@@ -96,58 +61,3 @@ class ShowHabitView(context: Context) : FrameLayout(context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ShowHabitPresenter(
|
|
||||||
val habit: Habit,
|
|
||||||
val context: Context,
|
|
||||||
val preferences: Preferences,
|
|
||||||
) {
|
|
||||||
private val subtitleCardPresenter = SubtitleCardPresenter(habit, context)
|
|
||||||
private val overviewCardPresenter = OverviewCardPresenter(habit)
|
|
||||||
private val notesCardPresenter = NotesCardPresenter(habit)
|
|
||||||
private val targetCardPresenter = TargetCardPresenter(
|
|
||||||
habit = habit,
|
|
||||||
firstWeekday = preferences.firstWeekday,
|
|
||||||
resources = context.resources,
|
|
||||||
)
|
|
||||||
private val streakCartPresenter = StreakCartPresenter(habit)
|
|
||||||
private val scoreCardPresenter = ScoreCardPresenter(
|
|
||||||
habit = habit,
|
|
||||||
firstWeekday = preferences.firstWeekday,
|
|
||||||
)
|
|
||||||
private val frequencyCardPresenter = FrequencyCardPresenter(
|
|
||||||
habit = habit,
|
|
||||||
firstWeekday = preferences.firstWeekday,
|
|
||||||
)
|
|
||||||
private val historyCardViewModel = HistoryCardPresenter(
|
|
||||||
habit = habit,
|
|
||||||
firstWeekday = preferences.firstWeekday,
|
|
||||||
isSkipEnabled = preferences.isSkipEnabled,
|
|
||||||
)
|
|
||||||
private val barCardPresenter = BarCardPresenter(
|
|
||||||
habit = habit,
|
|
||||||
firstWeekday = preferences.firstWeekday,
|
|
||||||
)
|
|
||||||
|
|
||||||
suspend fun present(): ShowHabitViewModel {
|
|
||||||
return ShowHabitViewModel(
|
|
||||||
title = habit.name,
|
|
||||||
color = habit.color,
|
|
||||||
isNumerical = habit.isNumerical,
|
|
||||||
subtitle = subtitleCardPresenter.present(),
|
|
||||||
overview = overviewCardPresenter.present(),
|
|
||||||
notes = notesCardPresenter.present(),
|
|
||||||
target = targetCardPresenter.present(),
|
|
||||||
streaks = streakCartPresenter.present(),
|
|
||||||
scores = scoreCardPresenter.present(
|
|
||||||
spinnerPosition = preferences.scoreCardSpinnerPosition
|
|
||||||
),
|
|
||||||
frequency = frequencyCardPresenter.present(),
|
|
||||||
history = historyCardViewModel.present(),
|
|
||||||
bar = barCardPresenter.present(
|
|
||||||
boolSpinnerPosition = preferences.barCardBoolSpinnerPosition,
|
|
||||||
numericalSpinnerPosition = preferences.barCardNumericalSpinnerPosition,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -24,25 +24,11 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.activities.habits.show.views.ScoreCardPresenter.Companion.getTruncateField
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.BarCardViewModel
|
||||||
import org.isoron.uhabits.core.models.Entry
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
|
||||||
import org.isoron.uhabits.core.models.groupedSum
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils
|
|
||||||
import org.isoron.uhabits.databinding.ShowHabitBarBinding
|
import org.isoron.uhabits.databinding.ShowHabitBarBinding
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
|
||||||
data class BarCardViewModel(
|
class BarCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
val entries: List<Entry>,
|
|
||||||
val bucketSize: Int,
|
|
||||||
val color: PaletteColor,
|
|
||||||
val isNumerical: Boolean,
|
|
||||||
val numericalSpinnerPosition: Int,
|
|
||||||
val boolSpinnerPosition: Int,
|
|
||||||
)
|
|
||||||
|
|
||||||
class BarCard(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
|
||||||
|
|
||||||
private var binding = ShowHabitBarBinding.inflate(LayoutInflater.from(context), this)
|
private var binding = ShowHabitBarBinding.inflate(LayoutInflater.from(context), this)
|
||||||
var onNumericalSpinnerPosition: (position: Int) -> Unit = {}
|
var onNumericalSpinnerPosition: (position: Int) -> Unit = {}
|
||||||
@@ -94,37 +80,3 @@ class BarCard(context: Context, attrs: AttributeSet) : LinearLayout(context, att
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BarCardPresenter(
|
|
||||||
val habit: Habit,
|
|
||||||
val firstWeekday: Int,
|
|
||||||
) {
|
|
||||||
val numericalBucketSizes = intArrayOf(1, 7, 31, 92, 365)
|
|
||||||
val boolBucketSizes = intArrayOf(7, 31, 92, 365)
|
|
||||||
|
|
||||||
fun present(
|
|
||||||
numericalSpinnerPosition: Int,
|
|
||||||
boolSpinnerPosition: Int,
|
|
||||||
): BarCardViewModel {
|
|
||||||
val bucketSize = if (habit.isNumerical) {
|
|
||||||
numericalBucketSizes[numericalSpinnerPosition]
|
|
||||||
} else {
|
|
||||||
boolBucketSizes[boolSpinnerPosition]
|
|
||||||
}
|
|
||||||
val today = DateUtils.getToday()
|
|
||||||
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
|
|
||||||
val entries = habit.computedEntries.getByInterval(oldest, today).groupedSum(
|
|
||||||
truncateField = getTruncateField(bucketSize),
|
|
||||||
firstWeekday = firstWeekday,
|
|
||||||
isNumerical = habit.isNumerical,
|
|
||||||
)
|
|
||||||
return BarCardViewModel(
|
|
||||||
entries = entries,
|
|
||||||
bucketSize = bucketSize,
|
|
||||||
color = habit.color,
|
|
||||||
isNumerical = habit.isNumerical,
|
|
||||||
numericalSpinnerPosition = numericalSpinnerPosition,
|
|
||||||
boolSpinnerPosition = boolSpinnerPosition,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,20 +22,11 @@ import android.content.Context
|
|||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.FrequencyCardViewModel
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
|
||||||
import org.isoron.uhabits.core.models.Timestamp
|
|
||||||
import org.isoron.uhabits.databinding.ShowHabitFrequencyBinding
|
import org.isoron.uhabits.databinding.ShowHabitFrequencyBinding
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
import java.util.HashMap
|
|
||||||
|
|
||||||
data class FrequencyCardViewModel(
|
class FrequencyCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
val frequency: HashMap<Timestamp, Array<Int>>,
|
|
||||||
val firstWeekday: Int,
|
|
||||||
val color: PaletteColor,
|
|
||||||
)
|
|
||||||
|
|
||||||
class FrequencyCard(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
|
||||||
|
|
||||||
private var binding = ShowHabitFrequencyBinding.inflate(LayoutInflater.from(context), this)
|
private var binding = ShowHabitFrequencyBinding.inflate(LayoutInflater.from(context), this)
|
||||||
|
|
||||||
@@ -47,16 +38,3 @@ class FrequencyCard(context: Context, attrs: AttributeSet) : LinearLayout(contex
|
|||||||
binding.frequencyChart.setColor(androidColor)
|
binding.frequencyChart.setColor(androidColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FrequencyCardPresenter(
|
|
||||||
val habit: Habit,
|
|
||||||
val firstWeekday: Int,
|
|
||||||
) {
|
|
||||||
fun present() = FrequencyCardViewModel(
|
|
||||||
color = habit.color,
|
|
||||||
frequency = habit.originalEntries.computeWeekdayFrequency(
|
|
||||||
isNumerical = habit.isNumerical
|
|
||||||
),
|
|
||||||
firstWeekday = firstWeekday,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -22,21 +22,11 @@ import android.content.Context
|
|||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.HistoryCardViewModel
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils
|
|
||||||
import org.isoron.uhabits.databinding.ShowHabitHistoryBinding
|
import org.isoron.uhabits.databinding.ShowHabitHistoryBinding
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
|
||||||
data class HistoryCardViewModel(
|
class HistoryCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
val entries: IntArray,
|
|
||||||
val color: PaletteColor,
|
|
||||||
val firstWeekday: Int,
|
|
||||||
val isNumerical: Boolean,
|
|
||||||
val isSkipEnabled: Boolean,
|
|
||||||
)
|
|
||||||
|
|
||||||
class HistoryCard(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
|
||||||
|
|
||||||
private var binding = ShowHabitHistoryBinding.inflate(LayoutInflater.from(context), this)
|
private var binding = ShowHabitHistoryBinding.inflate(LayoutInflater.from(context), this)
|
||||||
|
|
||||||
@@ -58,23 +48,3 @@ class HistoryCard(context: Context, attrs: AttributeSet) : LinearLayout(context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HistoryCardPresenter(
|
|
||||||
val habit: Habit,
|
|
||||||
val firstWeekday: Int,
|
|
||||||
val isSkipEnabled: Boolean,
|
|
||||||
) {
|
|
||||||
fun present(): HistoryCardViewModel {
|
|
||||||
val today = DateUtils.getTodayWithOffset()
|
|
||||||
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
|
|
||||||
val entries = habit.computedEntries.getByInterval(oldest, today).map { it.value }.toIntArray()
|
|
||||||
|
|
||||||
return HistoryCardViewModel(
|
|
||||||
entries = entries,
|
|
||||||
color = habit.color,
|
|
||||||
firstWeekday = firstWeekday,
|
|
||||||
isNumerical = habit.isNumerical,
|
|
||||||
isSkipEnabled = isSkipEnabled,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,11 +23,9 @@ import android.content.Context
|
|||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.NotesCardViewModel
|
||||||
import org.isoron.uhabits.databinding.ShowHabitNotesBinding
|
import org.isoron.uhabits.databinding.ShowHabitNotesBinding
|
||||||
|
|
||||||
data class NotesCardViewModel(val description: String)
|
|
||||||
|
|
||||||
class NotesCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
class NotesCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
private val binding = ShowHabitNotesBinding.inflate(LayoutInflater.from(context), this)
|
private val binding = ShowHabitNotesBinding.inflate(LayoutInflater.from(context), this)
|
||||||
fun update(data: NotesCardViewModel) {
|
fun update(data: NotesCardViewModel) {
|
||||||
@@ -40,9 +38,3 @@ class NotesCardView(context: Context, attrs: AttributeSet) : LinearLayout(contex
|
|||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotesCardPresenter(val habit: Habit) {
|
|
||||||
fun present() = NotesCardViewModel(
|
|
||||||
description = habit.description,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -22,25 +22,12 @@ import android.content.Context
|
|||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.invoke
|
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.OverviewCardViewModel
|
||||||
import org.isoron.uhabits.core.models.Habit
|
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils
|
|
||||||
import org.isoron.uhabits.databinding.ShowHabitOverviewBinding
|
import org.isoron.uhabits.databinding.ShowHabitOverviewBinding
|
||||||
import org.isoron.uhabits.utils.StyledResources
|
import org.isoron.uhabits.utils.StyledResources
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
|
||||||
data class OverviewCardViewModel(
|
|
||||||
val color: PaletteColor,
|
|
||||||
val scoreMonthDiff: Float,
|
|
||||||
val scoreYearDiff: Float,
|
|
||||||
val scoreToday: Float,
|
|
||||||
val totalCount: Long,
|
|
||||||
)
|
|
||||||
|
|
||||||
class OverviewCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
class OverviewCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
|
|
||||||
private val binding = ShowHabitOverviewBinding.inflate(LayoutInflater.from(context), this)
|
private val binding = ShowHabitOverviewBinding.inflate(LayoutInflater.from(context), this)
|
||||||
@@ -71,26 +58,3 @@ class OverviewCardView(context: Context, attrs: AttributeSet) : LinearLayout(con
|
|||||||
postInvalidate()
|
postInvalidate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverviewCardPresenter(val habit: Habit) {
|
|
||||||
suspend fun present(): OverviewCardViewModel = Dispatchers.IO {
|
|
||||||
val today = DateUtils.getTodayWithOffset()
|
|
||||||
val lastMonth = today.minus(30)
|
|
||||||
val lastYear = today.minus(365)
|
|
||||||
val scores = habit.scores
|
|
||||||
val scoreToday = scores.get(today).value.toFloat()
|
|
||||||
val scoreLastMonth = scores.get(lastMonth).value.toFloat()
|
|
||||||
val scoreLastYear = scores.get(lastYear).value.toFloat()
|
|
||||||
val totalCount = habit.originalEntries.getKnown()
|
|
||||||
.filter { it.value == YES_MANUAL }
|
|
||||||
.count()
|
|
||||||
.toLong()
|
|
||||||
return@IO OverviewCardViewModel(
|
|
||||||
color = habit.color,
|
|
||||||
scoreToday = scoreToday,
|
|
||||||
scoreMonthDiff = scoreToday - scoreLastMonth,
|
|
||||||
scoreYearDiff = scoreToday - scoreLastYear,
|
|
||||||
totalCount = totalCount,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.AdapterView
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
|
||||||
import org.isoron.uhabits.core.models.Score
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.DAY
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.MONTH
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.QUARTER
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.WEEK_NUMBER
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.YEAR
|
|
||||||
import org.isoron.uhabits.databinding.ShowHabitScoreBinding
|
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
|
||||||
|
|
||||||
data class ScoreCardViewModel(
|
|
||||||
val scores: List<Score>,
|
|
||||||
val bucketSize: Int,
|
|
||||||
val spinnerPosition: Int,
|
|
||||||
val color: PaletteColor,
|
|
||||||
)
|
|
||||||
|
|
||||||
class ScoreCard(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
|
||||||
private var binding = ShowHabitScoreBinding.inflate(LayoutInflater.from(context), this)
|
|
||||||
|
|
||||||
var onSpinnerPosition: (position: Int) -> Unit = {}
|
|
||||||
|
|
||||||
fun update(data: ScoreCardViewModel) {
|
|
||||||
val androidColor = data.color.toThemedAndroidColor(context)
|
|
||||||
binding.title.setTextColor(androidColor)
|
|
||||||
binding.spinner.setSelection(data.spinnerPosition)
|
|
||||||
binding.scoreView.setScores(data.scores)
|
|
||||||
binding.scoreView.reset()
|
|
||||||
binding.scoreView.setBucketSize(data.bucketSize)
|
|
||||||
binding.scoreView.setColor(androidColor)
|
|
||||||
|
|
||||||
binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
||||||
onSpinnerPosition(position)
|
|
||||||
}
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ScoreCardPresenter(
|
|
||||||
val habit: Habit,
|
|
||||||
val firstWeekday: Int,
|
|
||||||
) {
|
|
||||||
companion object {
|
|
||||||
val BUCKET_SIZES = intArrayOf(1, 7, 31, 92, 365)
|
|
||||||
fun getTruncateField(bucketSize: Int): DateUtils.TruncateField {
|
|
||||||
when (bucketSize) {
|
|
||||||
1 -> return DAY
|
|
||||||
7 -> return WEEK_NUMBER
|
|
||||||
31 -> return MONTH
|
|
||||||
92 -> return QUARTER
|
|
||||||
365 -> return YEAR
|
|
||||||
else -> return MONTH
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun present(spinnerPosition: Int): ScoreCardViewModel {
|
|
||||||
val bucketSize = BUCKET_SIZES[spinnerPosition]
|
|
||||||
val today = DateUtils.getTodayWithOffset()
|
|
||||||
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
|
|
||||||
|
|
||||||
val field = getTruncateField(bucketSize)
|
|
||||||
val scores = habit.scores.getByInterval(oldest, today).groupBy {
|
|
||||||
DateUtils.truncate(field, it.timestamp, firstWeekday)
|
|
||||||
}.map { (timestamp, scores) ->
|
|
||||||
Score(
|
|
||||||
timestamp,
|
|
||||||
scores.map {
|
|
||||||
it.value
|
|
||||||
}.average()
|
|
||||||
)
|
|
||||||
}.sortedBy {
|
|
||||||
it.timestamp
|
|
||||||
}.reversed()
|
|
||||||
|
|
||||||
return ScoreCardViewModel(
|
|
||||||
color = habit.color,
|
|
||||||
scores = scores,
|
|
||||||
bucketSize = bucketSize,
|
|
||||||
spinnerPosition = spinnerPosition,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardViewModel
|
||||||
|
import org.isoron.uhabits.databinding.ShowHabitScoreBinding
|
||||||
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
|
||||||
|
class ScoreCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
|
private var binding = ShowHabitScoreBinding.inflate(LayoutInflater.from(context), this)
|
||||||
|
|
||||||
|
var onSpinnerPosition: (position: Int) -> Unit = {}
|
||||||
|
|
||||||
|
fun update(data: ScoreCardViewModel) {
|
||||||
|
val androidColor = data.color.toThemedAndroidColor(context)
|
||||||
|
binding.title.setTextColor(androidColor)
|
||||||
|
binding.spinner.setSelection(data.spinnerPosition)
|
||||||
|
binding.scoreView.setScores(data.scores)
|
||||||
|
binding.scoreView.reset()
|
||||||
|
binding.scoreView.setBucketSize(data.bucketSize)
|
||||||
|
binding.scoreView.setColor(androidColor)
|
||||||
|
|
||||||
|
binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(
|
||||||
|
parent: AdapterView<*>?,
|
||||||
|
view: View?,
|
||||||
|
position: Int,
|
||||||
|
id: Long
|
||||||
|
) {
|
||||||
|
onSpinnerPosition(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,19 +22,10 @@ import android.content.Context
|
|||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import kotlinx.coroutines.Dispatchers
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.StreakCardViewModel
|
||||||
import kotlinx.coroutines.invoke
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
|
||||||
import org.isoron.uhabits.core.models.Streak
|
|
||||||
import org.isoron.uhabits.databinding.ShowHabitStreakBinding
|
import org.isoron.uhabits.databinding.ShowHabitStreakBinding
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
|
||||||
data class StreakCardViewModel(
|
|
||||||
val color: PaletteColor,
|
|
||||||
val bestStreaks: List<Streak>
|
|
||||||
)
|
|
||||||
|
|
||||||
class StreakCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
class StreakCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
private val binding = ShowHabitStreakBinding.inflate(LayoutInflater.from(context), this)
|
private val binding = ShowHabitStreakBinding.inflate(LayoutInflater.from(context), this)
|
||||||
fun update(data: StreakCardViewModel) {
|
fun update(data: StreakCardViewModel) {
|
||||||
@@ -45,12 +36,3 @@ class StreakCardView(context: Context, attrs: AttributeSet) : LinearLayout(conte
|
|||||||
postInvalidate()
|
postInvalidate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StreakCartPresenter(val habit: Habit) {
|
|
||||||
suspend fun present(): StreakCardViewModel = Dispatchers.IO {
|
|
||||||
return@IO StreakCardViewModel(
|
|
||||||
color = habit.color,
|
|
||||||
bestStreaks = habit.streaks.getBest(10),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -28,23 +28,13 @@ import android.widget.LinearLayout
|
|||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.habits.list.views.toShortString
|
import org.isoron.uhabits.activities.habits.list.views.toShortString
|
||||||
import org.isoron.uhabits.core.models.Frequency
|
import org.isoron.uhabits.core.models.Frequency
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.SubtitleCardViewModel
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
|
||||||
import org.isoron.uhabits.databinding.ShowHabitSubtitleBinding
|
import org.isoron.uhabits.databinding.ShowHabitSubtitleBinding
|
||||||
import org.isoron.uhabits.utils.InterfaceUtils
|
import org.isoron.uhabits.utils.InterfaceUtils
|
||||||
import org.isoron.uhabits.utils.formatTime
|
import org.isoron.uhabits.utils.formatTime
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
data class SubtitleCardViewModel(
|
|
||||||
val color: PaletteColor,
|
|
||||||
val frequencyText: String,
|
|
||||||
val isNumerical: Boolean,
|
|
||||||
val question: String,
|
|
||||||
val reminderText: String,
|
|
||||||
val targetText: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
|
|
||||||
private val binding = ShowHabitSubtitleBinding.inflate(LayoutInflater.from(context), this)
|
private val binding = ShowHabitSubtitleBinding.inflate(LayoutInflater.from(context), this)
|
||||||
@@ -56,13 +46,19 @@ class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(con
|
|||||||
binding.reminderIcon.typeface = fontAwesome
|
binding.reminderIcon.typeface = fontAwesome
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
fun update(data: SubtitleCardViewModel) {
|
fun update(data: SubtitleCardViewModel) {
|
||||||
val color = data.color.toThemedAndroidColor(context)
|
val color = data.color.toThemedAndroidColor(context)
|
||||||
binding.frequencyLabel.text = data.frequencyText
|
val reminder = data.reminder
|
||||||
|
binding.frequencyLabel.text = data.frequency.format(resources)
|
||||||
binding.questionLabel.setTextColor(color)
|
binding.questionLabel.setTextColor(color)
|
||||||
binding.questionLabel.text = data.question
|
binding.questionLabel.text = data.question
|
||||||
binding.reminderLabel.text = data.reminderText
|
binding.reminderLabel.text = if (reminder != null) {
|
||||||
binding.targetText.text = data.targetText
|
formatTime(context, reminder.hour, reminder.minute)
|
||||||
|
} else {
|
||||||
|
resources.getString(R.string.reminder_off)
|
||||||
|
}
|
||||||
|
binding.targetText.text = "${data.targetValue.toShortString()} ${data.unit}"
|
||||||
|
|
||||||
binding.questionLabel.visibility = View.VISIBLE
|
binding.questionLabel.visibility = View.VISIBLE
|
||||||
binding.targetIcon.visibility = View.VISIBLE
|
binding.targetIcon.visibility = View.VISIBLE
|
||||||
@@ -77,32 +73,9 @@ class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(con
|
|||||||
|
|
||||||
postInvalidate()
|
postInvalidate()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class SubtitleCardPresenter(
|
|
||||||
val habit: Habit,
|
|
||||||
val context: Context,
|
|
||||||
) {
|
|
||||||
val resources: Resources = context.resources
|
|
||||||
|
|
||||||
fun present(): SubtitleCardViewModel {
|
|
||||||
val reminderText = if (habit.hasReminder()) {
|
|
||||||
formatTime(context, habit.reminder!!.hour, habit.reminder!!.minute)!!
|
|
||||||
} else {
|
|
||||||
resources.getString(R.string.reminder_off)
|
|
||||||
}
|
|
||||||
return SubtitleCardViewModel(
|
|
||||||
color = habit.color,
|
|
||||||
frequencyText = habit.frequency.format(),
|
|
||||||
isNumerical = habit.isNumerical,
|
|
||||||
question = habit.question,
|
|
||||||
reminderText = reminderText,
|
|
||||||
targetText = "${habit.targetValue.toShortString()} ${habit.unit}",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("StringFormatMatches")
|
@SuppressLint("StringFormatMatches")
|
||||||
private fun Frequency.format(): String {
|
private fun Frequency.format(resources: Resources): String {
|
||||||
val num = this.numerator
|
val num = this.numerator
|
||||||
val den = this.denominator
|
val den = this.denominator
|
||||||
if (num == den) {
|
if (num == den) {
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.isoron.uhabits.activities.habits.show.views
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.TargetCardViewModel
|
||||||
|
import org.isoron.uhabits.databinding.ShowHabitTargetBinding
|
||||||
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
|
|
||||||
|
class TargetCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
||||||
|
private val binding = ShowHabitTargetBinding.inflate(LayoutInflater.from(context), this)
|
||||||
|
fun update(data: TargetCardViewModel) {
|
||||||
|
val androidColor = data.color.toThemedAndroidColor(context)
|
||||||
|
binding.targetChart.setValues(data.values)
|
||||||
|
binding.targetChart.setTargets(data.targets)
|
||||||
|
binding.targetChart.setLabels(data.intervals.map { intervalToLabel(resources, it) })
|
||||||
|
binding.title.setTextColor(androidColor)
|
||||||
|
binding.targetChart.setColor(androidColor)
|
||||||
|
postInvalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun intervalToLabel(resources: Resources, interval: Int) = when (interval) {
|
||||||
|
1 -> resources.getString(R.string.today)
|
||||||
|
7 -> resources.getString(R.string.week)
|
||||||
|
30 -> resources.getString(R.string.month)
|
||||||
|
91 -> resources.getString(R.string.quarter)
|
||||||
|
else -> resources.getString(R.string.year)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,8 +23,8 @@ import android.app.PendingIntent
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import org.isoron.uhabits.activities.common.views.HistoryChart
|
import org.isoron.uhabits.activities.common.views.HistoryChart
|
||||||
import org.isoron.uhabits.activities.habits.show.views.HistoryCardPresenter
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.HistoryCardPresenter
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
import org.isoron.uhabits.widgets.views.GraphWidgetView
|
import org.isoron.uhabits.widgets.views.GraphWidgetView
|
||||||
|
|
||||||
@@ -43,11 +43,11 @@ class HistoryWidget(
|
|||||||
val widgetView = view as GraphWidgetView
|
val widgetView = view as GraphWidgetView
|
||||||
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
|
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
|
||||||
if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f)
|
if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f)
|
||||||
val model = HistoryCardPresenter(
|
val model = HistoryCardPresenter().present(
|
||||||
habit = habit,
|
habit = habit,
|
||||||
isSkipEnabled = prefs.isSkipEnabled,
|
isSkipEnabled = prefs.isSkipEnabled,
|
||||||
firstWeekday = prefs.firstWeekday,
|
firstWeekday = prefs.firstWeekday,
|
||||||
).present()
|
)
|
||||||
(widgetView.dataView as HistoryChart).apply {
|
(widgetView.dataView as HistoryChart).apply {
|
||||||
setFirstWeekday(model.firstWeekday)
|
setFirstWeekday(model.firstWeekday)
|
||||||
setSkipEnabled(model.isSkipEnabled)
|
setSkipEnabled(model.isSkipEnabled)
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ package org.isoron.uhabits.widgets
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import org.isoron.uhabits.activities.common.views.ScoreChart
|
import org.isoron.uhabits.activities.common.views.ScoreChart
|
||||||
import org.isoron.uhabits.activities.habits.show.views.ScoreCardPresenter
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
import org.isoron.uhabits.widgets.views.GraphWidgetView
|
import org.isoron.uhabits.widgets.views.GraphWidgetView
|
||||||
|
|
||||||
@@ -37,8 +37,12 @@ class ScoreWidget(
|
|||||||
pendingIntentFactory.showHabit(habit)
|
pendingIntentFactory.showHabit(habit)
|
||||||
|
|
||||||
override fun refreshData(view: View) {
|
override fun refreshData(view: View) {
|
||||||
val presenter = ScoreCardPresenter(habit, prefs.firstWeekday)
|
val presenter = ScoreCardPresenter()
|
||||||
val viewModel = presenter.present(prefs.scoreCardSpinnerPosition)
|
val viewModel = presenter.present(
|
||||||
|
habit = habit,
|
||||||
|
firstWeekday = prefs.firstWeekday,
|
||||||
|
spinnerPosition = prefs.scoreCardSpinnerPosition
|
||||||
|
)
|
||||||
val widgetView = view as GraphWidgetView
|
val widgetView = view as GraphWidgetView
|
||||||
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
|
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
|
||||||
if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f)
|
if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f)
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ import android.view.ViewGroup.LayoutParams
|
|||||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.isoron.uhabits.activities.common.views.TargetChart
|
import org.isoron.uhabits.activities.common.views.TargetChart
|
||||||
import org.isoron.uhabits.activities.habits.show.views.TargetCardPresenter
|
import org.isoron.uhabits.activities.habits.show.views.TargetCardView.Companion.intervalToLabel
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.TargetCardPresenter
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
import org.isoron.uhabits.utils.toThemedAndroidColor
|
||||||
import org.isoron.uhabits.widgets.views.GraphWidgetView
|
import org.isoron.uhabits.widgets.views.GraphWidgetView
|
||||||
|
|
||||||
@@ -44,11 +45,11 @@ class TargetWidget(
|
|||||||
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
|
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
|
||||||
if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f)
|
if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f)
|
||||||
val chart = (widgetView.dataView as TargetChart)
|
val chart = (widgetView.dataView as TargetChart)
|
||||||
val presenter = TargetCardPresenter(habit, prefs.firstWeekday, context.resources)
|
val presenter = TargetCardPresenter()
|
||||||
val data = presenter.present()
|
val data = presenter.present(habit, prefs.firstWeekday)
|
||||||
chart.setColor(data.color.toThemedAndroidColor(context))
|
chart.setColor(data.color.toThemedAndroidColor(context))
|
||||||
chart.setTargets(data.targets)
|
chart.setTargets(data.targets)
|
||||||
chart.setLabels(data.labels)
|
chart.setLabels(data.intervals.map { intervalToLabel(context.resources, it) })
|
||||||
chart.setValues(data.values)
|
chart.setValues(data.values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,17 +62,17 @@
|
|||||||
style="@style/Card"
|
style="@style/Card"
|
||||||
android:paddingTop="12dp"/>
|
android:paddingTop="12dp"/>
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.show.views.ScoreCard
|
<org.isoron.uhabits.activities.habits.show.views.ScoreCardView
|
||||||
android:id="@+id/scoreCard"
|
android:id="@+id/scoreCard"
|
||||||
style="@style/Card"
|
style="@style/Card"
|
||||||
android:gravity="center"/>
|
android:gravity="center"/>
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.show.views.BarCard
|
<org.isoron.uhabits.activities.habits.show.views.BarCardView
|
||||||
android:id="@+id/barCard"
|
android:id="@+id/barCard"
|
||||||
style="@style/Card"
|
style="@style/Card"
|
||||||
android:gravity="center"/>
|
android:gravity="center"/>
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.show.views.HistoryCard
|
<org.isoron.uhabits.activities.habits.show.views.HistoryCardView
|
||||||
android:id="@+id/historyCard"
|
android:id="@+id/historyCard"
|
||||||
style="@style/Card"
|
style="@style/Card"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
android:id="@+id/streakCard"
|
android:id="@+id/streakCard"
|
||||||
style="@style/Card"/>
|
style="@style/Card"/>
|
||||||
|
|
||||||
<org.isoron.uhabits.activities.habits.show.views.FrequencyCard
|
<org.isoron.uhabits.activities.habits.show.views.FrequencyCardView
|
||||||
android:id="@+id/frequencyCard"
|
android:id="@+id/frequencyCard"
|
||||||
style="@style/Card"/>
|
style="@style/Card"/>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.core.ui.screens.habits.show
|
||||||
|
|
||||||
|
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.ui.screens.habits.show.views.BarCardPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.BarCardViewModel
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.FrequencyCardPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.FrequencyCardViewModel
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.HistoryCardPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.HistoryCardViewModel
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.NotesCardPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.NotesCardViewModel
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.OverviewCardPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.OverviewCardViewModel
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardViewModel
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.StreakCardViewModel
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.StreakCartPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.SubtitleCardPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.SubtitleCardViewModel
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.TargetCardPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.views.TargetCardViewModel
|
||||||
|
|
||||||
|
data class ShowHabitViewModel(
|
||||||
|
val title: String = "",
|
||||||
|
val isNumerical: Boolean = false,
|
||||||
|
val color: PaletteColor = PaletteColor(1),
|
||||||
|
val subtitle: SubtitleCardViewModel,
|
||||||
|
val overview: OverviewCardViewModel,
|
||||||
|
val notes: NotesCardViewModel,
|
||||||
|
val target: TargetCardViewModel,
|
||||||
|
val streaks: StreakCardViewModel,
|
||||||
|
val scores: ScoreCardViewModel,
|
||||||
|
val frequency: FrequencyCardViewModel,
|
||||||
|
val history: HistoryCardViewModel,
|
||||||
|
val bar: BarCardViewModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
class ShowHabitPresenter {
|
||||||
|
fun present(
|
||||||
|
habit: Habit,
|
||||||
|
preferences: Preferences,
|
||||||
|
): ShowHabitViewModel {
|
||||||
|
return ShowHabitViewModel(
|
||||||
|
title = habit.name,
|
||||||
|
color = habit.color,
|
||||||
|
isNumerical = habit.isNumerical,
|
||||||
|
subtitle = SubtitleCardPresenter().present(
|
||||||
|
habit = habit,
|
||||||
|
),
|
||||||
|
overview = OverviewCardPresenter().present(
|
||||||
|
habit = habit,
|
||||||
|
),
|
||||||
|
notes = NotesCardPresenter().present(
|
||||||
|
habit = habit,
|
||||||
|
),
|
||||||
|
target = TargetCardPresenter().present(
|
||||||
|
habit = habit,
|
||||||
|
firstWeekday = preferences.firstWeekday,
|
||||||
|
),
|
||||||
|
streaks = StreakCartPresenter().present(
|
||||||
|
habit = habit,
|
||||||
|
),
|
||||||
|
scores = ScoreCardPresenter().present(
|
||||||
|
spinnerPosition = preferences.scoreCardSpinnerPosition,
|
||||||
|
habit = habit,
|
||||||
|
firstWeekday = preferences.firstWeekday,
|
||||||
|
),
|
||||||
|
frequency = FrequencyCardPresenter().present(
|
||||||
|
habit = habit,
|
||||||
|
firstWeekday = preferences.firstWeekday,
|
||||||
|
),
|
||||||
|
history = HistoryCardPresenter().present(
|
||||||
|
habit = habit,
|
||||||
|
firstWeekday = preferences.firstWeekday,
|
||||||
|
isSkipEnabled = preferences.isSkipEnabled,
|
||||||
|
),
|
||||||
|
bar = BarCardPresenter().present(
|
||||||
|
habit = habit,
|
||||||
|
firstWeekday = preferences.firstWeekday,
|
||||||
|
boolSpinnerPosition = preferences.barCardBoolSpinnerPosition,
|
||||||
|
numericalSpinnerPosition = preferences.barCardNumericalSpinnerPosition,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.models.Entry
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.isoron.uhabits.core.models.groupedSum
|
||||||
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
|
|
||||||
|
data class BarCardViewModel(
|
||||||
|
val boolSpinnerPosition: Int,
|
||||||
|
val bucketSize: Int,
|
||||||
|
val color: PaletteColor,
|
||||||
|
val entries: List<Entry>,
|
||||||
|
val isNumerical: Boolean,
|
||||||
|
val numericalSpinnerPosition: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
class BarCardPresenter {
|
||||||
|
val numericalBucketSizes = intArrayOf(1, 7, 31, 92, 365)
|
||||||
|
val boolBucketSizes = intArrayOf(7, 31, 92, 365)
|
||||||
|
|
||||||
|
fun present(
|
||||||
|
habit: Habit,
|
||||||
|
firstWeekday: Int,
|
||||||
|
numericalSpinnerPosition: Int,
|
||||||
|
boolSpinnerPosition: Int,
|
||||||
|
): BarCardViewModel {
|
||||||
|
val bucketSize = if (habit.isNumerical) {
|
||||||
|
numericalBucketSizes[numericalSpinnerPosition]
|
||||||
|
} else {
|
||||||
|
boolBucketSizes[boolSpinnerPosition]
|
||||||
|
}
|
||||||
|
val today = DateUtils.getToday()
|
||||||
|
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
|
||||||
|
val entries = habit.computedEntries.getByInterval(oldest, today).groupedSum(
|
||||||
|
truncateField = ScoreCardPresenter.getTruncateField(bucketSize),
|
||||||
|
firstWeekday = firstWeekday,
|
||||||
|
isNumerical = habit.isNumerical,
|
||||||
|
)
|
||||||
|
return BarCardViewModel(
|
||||||
|
entries = entries,
|
||||||
|
bucketSize = bucketSize,
|
||||||
|
color = habit.color,
|
||||||
|
isNumerical = habit.isNumerical,
|
||||||
|
numericalSpinnerPosition = numericalSpinnerPosition,
|
||||||
|
boolSpinnerPosition = boolSpinnerPosition,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.isoron.uhabits.core.models.Timestamp
|
||||||
|
import java.util.HashMap
|
||||||
|
|
||||||
|
data class FrequencyCardViewModel(
|
||||||
|
val color: PaletteColor,
|
||||||
|
val firstWeekday: Int,
|
||||||
|
val frequency: HashMap<Timestamp, Array<Int>>,
|
||||||
|
)
|
||||||
|
|
||||||
|
class FrequencyCardPresenter {
|
||||||
|
fun present(
|
||||||
|
habit: Habit,
|
||||||
|
firstWeekday: Int,
|
||||||
|
) = FrequencyCardViewModel(
|
||||||
|
color = habit.color,
|
||||||
|
frequency = habit.originalEntries.computeWeekdayFrequency(
|
||||||
|
isNumerical = habit.isNumerical
|
||||||
|
),
|
||||||
|
firstWeekday = firstWeekday,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
|
|
||||||
|
data class HistoryCardViewModel(
|
||||||
|
val color: PaletteColor,
|
||||||
|
val entries: IntArray,
|
||||||
|
val firstWeekday: Int,
|
||||||
|
val isNumerical: Boolean,
|
||||||
|
val isSkipEnabled: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
class HistoryCardPresenter {
|
||||||
|
fun present(
|
||||||
|
habit: Habit,
|
||||||
|
firstWeekday: Int,
|
||||||
|
isSkipEnabled: Boolean,
|
||||||
|
): HistoryCardViewModel {
|
||||||
|
val today = DateUtils.getTodayWithOffset()
|
||||||
|
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
|
||||||
|
val entries =
|
||||||
|
habit.computedEntries.getByInterval(oldest, today).map { it.value }.toIntArray()
|
||||||
|
|
||||||
|
return HistoryCardViewModel(
|
||||||
|
entries = entries,
|
||||||
|
color = habit.color,
|
||||||
|
firstWeekday = firstWeekday,
|
||||||
|
isNumerical = habit.isNumerical,
|
||||||
|
isSkipEnabled = isSkipEnabled,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
|
||||||
|
data class NotesCardViewModel(
|
||||||
|
val description: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
class NotesCardPresenter {
|
||||||
|
fun present(habit: Habit) = NotesCardViewModel(
|
||||||
|
description = habit.description,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.models.Entry
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
|
|
||||||
|
data class OverviewCardViewModel(
|
||||||
|
val color: PaletteColor,
|
||||||
|
val scoreMonthDiff: Float,
|
||||||
|
val scoreYearDiff: Float,
|
||||||
|
val scoreToday: Float,
|
||||||
|
val totalCount: Long,
|
||||||
|
)
|
||||||
|
|
||||||
|
class OverviewCardPresenter {
|
||||||
|
fun present(habit: Habit): OverviewCardViewModel {
|
||||||
|
val today = DateUtils.getTodayWithOffset()
|
||||||
|
val lastMonth = today.minus(30)
|
||||||
|
val lastYear = today.minus(365)
|
||||||
|
val scores = habit.scores
|
||||||
|
val scoreToday = scores.get(today).value.toFloat()
|
||||||
|
val scoreLastMonth = scores.get(lastMonth).value.toFloat()
|
||||||
|
val scoreLastYear = scores.get(lastYear).value.toFloat()
|
||||||
|
val totalCount = habit.originalEntries.getKnown()
|
||||||
|
.filter { it.value == Entry.YES_MANUAL }
|
||||||
|
.count()
|
||||||
|
.toLong()
|
||||||
|
return OverviewCardViewModel(
|
||||||
|
color = habit.color,
|
||||||
|
scoreToday = scoreToday,
|
||||||
|
scoreMonthDiff = scoreToday - scoreLastMonth,
|
||||||
|
scoreYearDiff = scoreToday - scoreLastYear,
|
||||||
|
totalCount = totalCount,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.isoron.uhabits.core.models.Score
|
||||||
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
|
|
||||||
|
data class ScoreCardViewModel(
|
||||||
|
val scores: List<Score>,
|
||||||
|
val bucketSize: Int,
|
||||||
|
val spinnerPosition: Int,
|
||||||
|
val color: PaletteColor,
|
||||||
|
)
|
||||||
|
|
||||||
|
class ScoreCardPresenter {
|
||||||
|
companion object {
|
||||||
|
val BUCKET_SIZES = intArrayOf(1, 7, 31, 92, 365)
|
||||||
|
fun getTruncateField(bucketSize: Int): DateUtils.TruncateField {
|
||||||
|
when (bucketSize) {
|
||||||
|
1 -> return DateUtils.TruncateField.DAY
|
||||||
|
7 -> return DateUtils.TruncateField.WEEK_NUMBER
|
||||||
|
31 -> return DateUtils.TruncateField.MONTH
|
||||||
|
92 -> return DateUtils.TruncateField.QUARTER
|
||||||
|
365 -> return DateUtils.TruncateField.YEAR
|
||||||
|
else -> return DateUtils.TruncateField.MONTH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun present(
|
||||||
|
habit: Habit,
|
||||||
|
firstWeekday: Int,
|
||||||
|
spinnerPosition: Int,
|
||||||
|
): ScoreCardViewModel {
|
||||||
|
val bucketSize = BUCKET_SIZES[spinnerPosition]
|
||||||
|
val today = DateUtils.getTodayWithOffset()
|
||||||
|
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
|
||||||
|
|
||||||
|
val field = getTruncateField(bucketSize)
|
||||||
|
val scores = habit.scores.getByInterval(oldest, today).groupBy {
|
||||||
|
DateUtils.truncate(field, it.timestamp, firstWeekday)
|
||||||
|
}.map { (timestamp, scores) ->
|
||||||
|
Score(
|
||||||
|
timestamp,
|
||||||
|
scores.map {
|
||||||
|
it.value
|
||||||
|
}.average()
|
||||||
|
)
|
||||||
|
}.sortedBy {
|
||||||
|
it.timestamp
|
||||||
|
}.reversed()
|
||||||
|
|
||||||
|
return ScoreCardViewModel(
|
||||||
|
color = habit.color,
|
||||||
|
scores = scores,
|
||||||
|
bucketSize = bucketSize,
|
||||||
|
spinnerPosition = spinnerPosition,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.isoron.uhabits.core.models.Streak
|
||||||
|
|
||||||
|
data class StreakCardViewModel(
|
||||||
|
val color: PaletteColor,
|
||||||
|
val bestStreaks: List<Streak>
|
||||||
|
)
|
||||||
|
|
||||||
|
class StreakCartPresenter {
|
||||||
|
fun present(habit: Habit): StreakCardViewModel {
|
||||||
|
return StreakCardViewModel(
|
||||||
|
color = habit.color,
|
||||||
|
bestStreaks = habit.streaks.getBest(10),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
|
import org.isoron.uhabits.core.models.Frequency
|
||||||
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
|
import org.isoron.uhabits.core.models.Reminder
|
||||||
|
|
||||||
|
data class SubtitleCardViewModel(
|
||||||
|
val color: PaletteColor,
|
||||||
|
val frequency: Frequency,
|
||||||
|
val isNumerical: Boolean,
|
||||||
|
val question: String,
|
||||||
|
val reminder: Reminder?,
|
||||||
|
val targetValue: Double,
|
||||||
|
val unit: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
class SubtitleCardPresenter {
|
||||||
|
fun present(
|
||||||
|
habit: Habit,
|
||||||
|
): SubtitleCardViewModel = SubtitleCardViewModel(
|
||||||
|
color = habit.color,
|
||||||
|
frequency = habit.frequency,
|
||||||
|
isNumerical = habit.isNumerical,
|
||||||
|
question = habit.question,
|
||||||
|
reminder = habit.reminder,
|
||||||
|
targetValue = habit.targetValue,
|
||||||
|
unit = habit.unit,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
* Copyright (C) 2016-2020 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -16,27 +16,13 @@
|
|||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.habits.show.views
|
|
||||||
|
|
||||||
import android.content.Context
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
import android.content.res.Resources
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.invoke
|
|
||||||
import org.isoron.uhabits.R
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
import org.isoron.uhabits.core.models.PaletteColor
|
import org.isoron.uhabits.core.models.PaletteColor
|
||||||
import org.isoron.uhabits.core.models.groupedSum
|
import org.isoron.uhabits.core.models.groupedSum
|
||||||
import org.isoron.uhabits.core.utils.DateUtils
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.DAY
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.MONTH
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.QUARTER
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.WEEK_NUMBER
|
|
||||||
import org.isoron.uhabits.core.utils.DateUtils.TruncateField.YEAR
|
|
||||||
import org.isoron.uhabits.databinding.ShowHabitTargetBinding
|
|
||||||
import org.isoron.uhabits.utils.toThemedAndroidColor
|
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
|
|
||||||
@@ -44,55 +30,41 @@ data class TargetCardViewModel(
|
|||||||
val color: PaletteColor,
|
val color: PaletteColor,
|
||||||
val values: List<Double> = listOf(),
|
val values: List<Double> = listOf(),
|
||||||
val targets: List<Double> = listOf(),
|
val targets: List<Double> = listOf(),
|
||||||
val labels: List<String> = listOf(),
|
val intervals: List<Int> = listOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
class TargetCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
class TargetCardPresenter {
|
||||||
private val binding = ShowHabitTargetBinding.inflate(LayoutInflater.from(context), this)
|
fun present(
|
||||||
fun update(data: TargetCardViewModel) {
|
habit: Habit,
|
||||||
val androidColor = data.color.toThemedAndroidColor(context)
|
firstWeekday: Int,
|
||||||
binding.targetChart.setValues(data.values)
|
): TargetCardViewModel {
|
||||||
binding.targetChart.setTargets(data.targets)
|
|
||||||
binding.targetChart.setLabels(data.labels)
|
|
||||||
binding.title.setTextColor(androidColor)
|
|
||||||
binding.targetChart.setColor(androidColor)
|
|
||||||
postInvalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TargetCardPresenter(
|
|
||||||
val habit: Habit,
|
|
||||||
val firstWeekday: Int,
|
|
||||||
val resources: Resources,
|
|
||||||
) {
|
|
||||||
suspend fun present(): TargetCardViewModel = Dispatchers.IO {
|
|
||||||
val today = DateUtils.getTodayWithOffset()
|
val today = DateUtils.getTodayWithOffset()
|
||||||
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
|
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
|
||||||
val entries = habit.computedEntries.getByInterval(oldest, today)
|
val entries = habit.computedEntries.getByInterval(oldest, today)
|
||||||
|
|
||||||
val valueToday = entries.groupedSum(
|
val valueToday = entries.groupedSum(
|
||||||
truncateField = DAY,
|
truncateField = DateUtils.TruncateField.DAY,
|
||||||
isNumerical = habit.isNumerical
|
isNumerical = habit.isNumerical
|
||||||
).firstOrNull()?.value ?: 0
|
).firstOrNull()?.value ?: 0
|
||||||
|
|
||||||
val valueThisWeek = entries.groupedSum(
|
val valueThisWeek = entries.groupedSum(
|
||||||
truncateField = WEEK_NUMBER,
|
truncateField = DateUtils.TruncateField.WEEK_NUMBER,
|
||||||
firstWeekday = firstWeekday,
|
firstWeekday = firstWeekday,
|
||||||
isNumerical = habit.isNumerical
|
isNumerical = habit.isNumerical
|
||||||
).firstOrNull()?.value ?: 0
|
).firstOrNull()?.value ?: 0
|
||||||
|
|
||||||
val valueThisMonth = entries.groupedSum(
|
val valueThisMonth = entries.groupedSum(
|
||||||
truncateField = MONTH,
|
truncateField = DateUtils.TruncateField.MONTH,
|
||||||
isNumerical = habit.isNumerical
|
isNumerical = habit.isNumerical
|
||||||
).firstOrNull()?.value ?: 0
|
).firstOrNull()?.value ?: 0
|
||||||
|
|
||||||
val valueThisQuarter = entries.groupedSum(
|
val valueThisQuarter = entries.groupedSum(
|
||||||
truncateField = QUARTER,
|
truncateField = DateUtils.TruncateField.QUARTER,
|
||||||
isNumerical = habit.isNumerical
|
isNumerical = habit.isNumerical
|
||||||
).firstOrNull()?.value ?: 0
|
).firstOrNull()?.value ?: 0
|
||||||
|
|
||||||
val valueThisYear = entries.groupedSum(
|
val valueThisYear = entries.groupedSum(
|
||||||
truncateField = YEAR,
|
truncateField = DateUtils.TruncateField.YEAR,
|
||||||
isNumerical = habit.isNumerical
|
isNumerical = habit.isNumerical
|
||||||
).firstOrNull()?.value ?: 0
|
).firstOrNull()?.value ?: 0
|
||||||
|
|
||||||
@@ -121,18 +93,18 @@ class TargetCardPresenter(
|
|||||||
targets.add(targetThisQuarter)
|
targets.add(targetThisQuarter)
|
||||||
targets.add(targetThisYear)
|
targets.add(targetThisYear)
|
||||||
|
|
||||||
val labels = ArrayList<String>()
|
val intervals = ArrayList<Int>()
|
||||||
if (habit.frequency.denominator <= 1) labels.add(resources.getString(R.string.today))
|
if (habit.frequency.denominator <= 1) intervals.add(1)
|
||||||
if (habit.frequency.denominator <= 7) labels.add(resources.getString(R.string.week))
|
if (habit.frequency.denominator <= 7) intervals.add(7)
|
||||||
labels.add(resources.getString(R.string.month))
|
intervals.add(30)
|
||||||
labels.add(resources.getString(R.string.quarter))
|
intervals.add(91)
|
||||||
labels.add(resources.getString(R.string.year))
|
intervals.add(365)
|
||||||
|
|
||||||
return@IO TargetCardViewModel(
|
return TargetCardViewModel(
|
||||||
color = habit.color,
|
color = habit.color,
|
||||||
values = values,
|
values = values,
|
||||||
labels = labels,
|
|
||||||
targets = targets,
|
targets = targets,
|
||||||
|
intervals = intervals,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user