Add show habit group activity

This commit is contained in:
Dharanish
2024-07-03 09:14:16 +02:00
parent cac62c0278
commit a2cf78f823
19 changed files with 524 additions and 4 deletions

View File

@@ -74,12 +74,12 @@ class StreakList {
from: Timestamp,
to: Timestamp
) {
if (habitList.isEmpty) return
var current = from
var streakRunning = false
var streakStart = from
while (current <= to) {
if (habitList.all { it.streaks.isInStreaks(current) } && !streakRunning
) {
if (habitList.all { it.streaks.isInStreaks(current) } && !streakRunning) {
streakStart = current
streakRunning = true
} else if (streakRunning) {

View File

@@ -22,6 +22,7 @@ import org.isoron.uhabits.core.commands.CommandRunner
import org.isoron.uhabits.core.commands.CreateRepetitionCommand
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitGroup
import org.isoron.uhabits.core.models.HabitList
import org.isoron.uhabits.core.models.HabitType
import org.isoron.uhabits.core.models.NumericalHabitType.AT_LEAST
@@ -51,6 +52,10 @@ open class ListHabitsBehavior @Inject constructor(
screen.showHabitScreen(h)
}
fun onClickHabitGroup(hgr: HabitGroup) {
screen.showHabitGroupScreen(hgr)
}
fun onEdit(habit: Habit, timestamp: Timestamp?) {
val entry = habit.computedEntries.get(timestamp!!)
if (habit.type == HabitType.NUMERICAL) {
@@ -178,6 +183,7 @@ open class ListHabitsBehavior @Inject constructor(
interface Screen {
fun showHabitScreen(h: Habit)
fun showHabitGroupScreen(hgr: HabitGroup)
fun showIntroScreen()
fun showMessage(m: Message)
fun showNumberPopup(

View File

@@ -0,0 +1,78 @@
package org.isoron.uhabits.core.ui.screens.habits.show
import org.isoron.uhabits.core.commands.CommandRunner
import org.isoron.uhabits.core.models.HabitGroup
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.ui.screens.habits.show.views.NotesCardPresenter
import org.isoron.uhabits.core.ui.screens.habits.show.views.NotesCardState
import org.isoron.uhabits.core.ui.screens.habits.show.views.OverviewCardPresenter
import org.isoron.uhabits.core.ui.screens.habits.show.views.OverviewCardState
import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter
import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardState
import org.isoron.uhabits.core.ui.screens.habits.show.views.StreakCardState
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.SubtitleCardState
import org.isoron.uhabits.core.ui.views.Theme
data class ShowHabitGroupState(
val title: String = "",
val color: PaletteColor = PaletteColor(1),
val subtitle: SubtitleCardState,
val overview: OverviewCardState,
val notes: NotesCardState,
val streaks: StreakCardState,
val scores: ScoreCardState,
val theme: Theme
)
class ShowHabitGroupPresenter(
val habitGroup: HabitGroup,
val preferences: Preferences,
val screen: Screen,
val commandRunner: CommandRunner
) {
val scoreCardPresenter = ScoreCardPresenter(
preferences = preferences,
screen = screen
)
companion object {
fun buildState(
habitGroup: HabitGroup,
preferences: Preferences,
theme: Theme
): ShowHabitGroupState {
return ShowHabitGroupState(
title = habitGroup.name,
color = habitGroup.color,
theme = theme,
subtitle = SubtitleCardPresenter.buildState(
habitGroup = habitGroup,
theme = theme
),
overview = OverviewCardPresenter.buildState(
habitGroup = habitGroup,
theme = theme
),
notes = NotesCardPresenter.buildState(
habitGroup = habitGroup
),
streaks = StreakCartPresenter.buildState(
habitGroup = habitGroup,
theme = theme
),
scores = ScoreCardPresenter.buildState(
spinnerPosition = preferences.scoreCardSpinnerPosition,
habitGroup = habitGroup,
firstWeekday = preferences.firstWeekdayInt,
theme = theme
)
)
}
}
interface Screen :
ScoreCardPresenter.Screen
}

View File

@@ -0,0 +1,46 @@
package org.isoron.uhabits.core.ui.screens.habits.show
import org.isoron.uhabits.core.commands.CommandRunner
import org.isoron.uhabits.core.commands.DeleteHabitGroupsCommand
import org.isoron.uhabits.core.models.HabitGroup
import org.isoron.uhabits.core.models.HabitGroupList
import org.isoron.uhabits.core.tasks.TaskRunner
import org.isoron.uhabits.core.ui.callbacks.OnConfirmedCallback
import java.io.File
class ShowHabitGroupMenuPresenter(
private val commandRunner: CommandRunner,
private val habitGroup: HabitGroup,
private val habitGroupList: HabitGroupList,
private val screen: Screen,
private val system: System,
private val taskRunner: TaskRunner
) {
fun onEditHabit() {
screen.showEditHabitGroupScreen(habitGroup)
}
fun onDeleteHabit() {
screen.showDeleteConfirmationScreen {
commandRunner.run(DeleteHabitGroupsCommand(habitGroupList, listOf(habitGroup)))
screen.close()
}
}
enum class Message {
COULD_NOT_EXPORT
}
interface Screen {
fun showEditHabitGroupScreen(habitGroup: HabitGroup)
fun showMessage(m: Message?)
fun showSendFileScreen(filename: String)
fun showDeleteConfirmationScreen(callback: OnConfirmedCallback)
fun close()
fun refresh()
}
interface System {
fun getCSVOutputDir(): File
}
}

View File

@@ -20,6 +20,7 @@
package org.isoron.uhabits.core.ui.screens.habits.show.views
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitGroup
data class NotesCardState(
val description: String
@@ -30,5 +31,9 @@ class NotesCardPresenter {
fun buildState(habit: Habit) = NotesCardState(
description = habit.description
)
fun buildState(habitGroup: HabitGroup) = NotesCardState(
description = habitGroup.description
)
}
}

View File

@@ -21,6 +21,7 @@ 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.HabitGroup
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.ui.views.Theme
import org.isoron.uhabits.core.utils.DateUtils
@@ -57,5 +58,27 @@ class OverviewCardPresenter {
theme = theme
)
}
fun buildState(habitGroup: HabitGroup, theme: Theme): OverviewCardState {
val today = DateUtils.getTodayWithOffset()
val lastMonth = today.minus(30)
val lastYear = today.minus(365)
val scores = habitGroup.scores
val scoreToday = scores[today].value.toFloat()
val scoreLastMonth = scores[lastMonth].value.toFloat()
val scoreLastYear = scores[lastYear].value.toFloat()
val totalCount = habitGroup.habitList.sumOf { habit ->
habit.originalEntries.getKnown().count { it.value == Entry.YES_MANUAL }
.toLong()
}
return OverviewCardState(
color = habitGroup.color,
scoreToday = scoreToday,
scoreMonthDiff = scoreToday - scoreLastMonth,
scoreYearDiff = scoreToday - scoreLastYear,
totalCount = totalCount,
theme = theme
)
}
}
}

View File

@@ -20,6 +20,7 @@
package org.isoron.uhabits.core.ui.screens.habits.show.views
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitGroup
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.models.Score
import org.isoron.uhabits.core.preferences.Preferences
@@ -83,6 +84,45 @@ class ScoreCardPresenter(
theme = theme
)
}
fun buildState(
habitGroup: HabitGroup,
firstWeekday: Int,
spinnerPosition: Int,
theme: Theme
): ScoreCardState {
val bucketSize = BUCKET_SIZES[spinnerPosition]
val today = DateUtils.getTodayWithOffset()
val oldest = if (habitGroup.habitList.isEmpty) {
today
} else {
habitGroup.habitList.minOf {
it.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
}
}
val field = getTruncateField(bucketSize)
val scores = habitGroup.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 ScoreCardState(
color = habitGroup.color,
scores = scores,
bucketSize = bucketSize,
spinnerPosition = spinnerPosition,
theme = theme
)
}
}
fun onSpinnerPosition(position: Int) {

View File

@@ -20,6 +20,7 @@
package org.isoron.uhabits.core.ui.screens.habits.show.views
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitGroup
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.models.Streak
import org.isoron.uhabits.core.ui.views.Theme
@@ -39,5 +40,13 @@ class StreakCartPresenter {
theme = theme
)
}
fun buildState(habitGroup: HabitGroup, theme: Theme): StreakCardState {
return StreakCardState(
color = habitGroup.color,
bestStreaks = habitGroup.streaks.getBest(10),
theme = theme
)
}
}
}

View File

@@ -21,6 +21,7 @@ package org.isoron.uhabits.core.ui.screens.habits.show.views
import org.isoron.uhabits.core.models.Frequency
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitGroup
import org.isoron.uhabits.core.models.NumericalHabitType
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.models.Reminder
@@ -54,5 +55,17 @@ class SubtitleCardPresenter {
unit = habit.unit,
theme = theme
)
fun buildState(
habitGroup: HabitGroup,
theme: Theme
): SubtitleCardState = SubtitleCardState(
color = habitGroup.color,
frequency = Frequency.DAILY,
isNumerical = false,
question = habitGroup.question,
reminder = habitGroup.reminder,
theme = theme
)
}
}