mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-15 13:38:52 -06:00
Add show habit group activity
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user