mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-15 05:28:51 -06:00
Add show habit group activity
This commit is contained in:
@@ -80,6 +80,14 @@
|
|||||||
android:value=".activities.habits.list.ListHabitsActivity" />
|
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".activities.habits.show.ShowHabitGroupActivity"
|
||||||
|
android:label="@string/title_activity_show_habit">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.settings.SettingsActivity"
|
android:name=".activities.settings.SettingsActivity"
|
||||||
android:label="@string/settings">
|
android:label="@string/settings">
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ package org.isoron.uhabits.activities
|
|||||||
|
|
||||||
import org.isoron.uhabits.AndroidDirFinder
|
import org.isoron.uhabits.AndroidDirFinder
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
|
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitGroupMenuPresenter
|
||||||
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuPresenter
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuPresenter
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -33,3 +34,13 @@ constructor(
|
|||||||
return androidDirFinder.getFilesDir("CSV")!!
|
return androidDirFinder.getFilesDir("CSV")!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HabitGroupsDirFinder @Inject
|
||||||
|
constructor(
|
||||||
|
private val androidDirFinder: AndroidDirFinder
|
||||||
|
) : ShowHabitGroupMenuPresenter.System, ListHabitsBehavior.DirFinder {
|
||||||
|
|
||||||
|
override fun getCSVOutputDir(): File {
|
||||||
|
return androidDirFinder.getFilesDir("CSV")!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import org.isoron.uhabits.core.commands.DeleteHabitsCommand
|
|||||||
import org.isoron.uhabits.core.commands.EditHabitCommand
|
import org.isoron.uhabits.core.commands.EditHabitCommand
|
||||||
import org.isoron.uhabits.core.commands.UnarchiveHabitsCommand
|
import org.isoron.uhabits.core.commands.UnarchiveHabitsCommand
|
||||||
import org.isoron.uhabits.core.models.Habit
|
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.PaletteColor
|
||||||
import org.isoron.uhabits.core.preferences.Preferences
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
import org.isoron.uhabits.core.tasks.TaskRunner
|
import org.isoron.uhabits.core.tasks.TaskRunner
|
||||||
@@ -188,6 +189,11 @@ class ListHabitsScreen
|
|||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showHabitGroupScreen(hgr: HabitGroup) {
|
||||||
|
val intent = intentFactory.startShowHabitGroupActivity(activity, hgr)
|
||||||
|
activity.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
fun showImportScreen() {
|
fun showImportScreen() {
|
||||||
val intent = intentFactory.openDocument()
|
val intent = intentFactory.openDocument()
|
||||||
activity.startActivityForResult(intent, REQUEST_OPEN_DOCUMENT)
|
activity.startActivityForResult(intent, REQUEST_OPEN_DOCUMENT)
|
||||||
|
|||||||
@@ -102,6 +102,14 @@ class HabitCardListAdapter @Inject constructor(
|
|||||||
return cache.getHabitByPosition(position)
|
return cache.getHabitByPosition(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getHabit(position: Int): Habit? {
|
||||||
|
return cache.getHabitByPosition(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getHabitGroup(position: Int): HabitGroup? {
|
||||||
|
return cache.getHabitGroupByPosition(position)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
return cache.itemCount
|
return cache.itemCount
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,8 +114,15 @@ class HabitCardListController @Inject constructor(
|
|||||||
*/
|
*/
|
||||||
internal inner class NormalMode : Mode {
|
internal inner class NormalMode : Mode {
|
||||||
override fun onItemClick(position: Int) {
|
override fun onItemClick(position: Int) {
|
||||||
val habit = adapter.getItem(position) ?: return
|
val habit = adapter.getHabit(position)
|
||||||
|
if (habit != null) {
|
||||||
behavior.onClickHabit(habit)
|
behavior.onClickHabit(habit)
|
||||||
|
} else {
|
||||||
|
val hgr = adapter.getHabitGroup(position)
|
||||||
|
if (hgr != null) {
|
||||||
|
behavior.onClickHabitGroup(hgr)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(position: Int): Boolean {
|
override fun onItemLongClick(position: Int): Boolean {
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
package org.isoron.uhabits.activities.habits.show
|
||||||
|
|
||||||
|
import android.content.ContentUris
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.isoron.uhabits.AndroidDirFinder
|
||||||
|
import org.isoron.uhabits.HabitsApplication
|
||||||
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.activities.AndroidThemeSwitcher
|
||||||
|
import org.isoron.uhabits.activities.HabitGroupsDirFinder
|
||||||
|
import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog
|
||||||
|
import org.isoron.uhabits.core.commands.Command
|
||||||
|
import org.isoron.uhabits.core.commands.CommandRunner
|
||||||
|
import org.isoron.uhabits.core.models.HabitGroup
|
||||||
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
|
import org.isoron.uhabits.core.ui.callbacks.OnConfirmedCallback
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitGroupMenuPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitGroupPresenter
|
||||||
|
import org.isoron.uhabits.intents.IntentFactory
|
||||||
|
import org.isoron.uhabits.utils.dismissCurrentAndShow
|
||||||
|
import org.isoron.uhabits.utils.dismissCurrentDialog
|
||||||
|
import org.isoron.uhabits.utils.showMessage
|
||||||
|
import org.isoron.uhabits.utils.showSendFileScreen
|
||||||
|
import org.isoron.uhabits.widgets.WidgetUpdater
|
||||||
|
|
||||||
|
class ShowHabitGroupActivity : AppCompatActivity(), CommandRunner.Listener {
|
||||||
|
|
||||||
|
private lateinit var commandRunner: CommandRunner
|
||||||
|
private lateinit var menu: ShowHabitGroupMenu
|
||||||
|
private lateinit var view: ShowHabitGroupView
|
||||||
|
private lateinit var habitGroup: HabitGroup
|
||||||
|
private lateinit var preferences: Preferences
|
||||||
|
private lateinit var themeSwitcher: AndroidThemeSwitcher
|
||||||
|
private lateinit var widgetUpdater: WidgetUpdater
|
||||||
|
|
||||||
|
private val scope = CoroutineScope(Dispatchers.Main)
|
||||||
|
private lateinit var presenter: ShowHabitGroupPresenter
|
||||||
|
private val screen = Screen()
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
val appComponent = (applicationContext as HabitsApplication).component
|
||||||
|
val habitGroupList = appComponent.habitGroupList
|
||||||
|
habitGroup = habitGroupList.getById(ContentUris.parseId(intent.data!!))!!
|
||||||
|
preferences = appComponent.preferences
|
||||||
|
commandRunner = appComponent.commandRunner
|
||||||
|
widgetUpdater = appComponent.widgetUpdater
|
||||||
|
|
||||||
|
themeSwitcher = AndroidThemeSwitcher(this, preferences)
|
||||||
|
themeSwitcher.apply()
|
||||||
|
|
||||||
|
presenter = ShowHabitGroupPresenter(
|
||||||
|
commandRunner = commandRunner,
|
||||||
|
habitGroup = habitGroup,
|
||||||
|
preferences = preferences,
|
||||||
|
screen = screen
|
||||||
|
)
|
||||||
|
|
||||||
|
view = ShowHabitGroupView(this)
|
||||||
|
|
||||||
|
val menuPresenter = ShowHabitGroupMenuPresenter(
|
||||||
|
commandRunner = commandRunner,
|
||||||
|
habitGroup = habitGroup,
|
||||||
|
habitGroupList = habitGroupList,
|
||||||
|
screen = screen,
|
||||||
|
system = HabitGroupsDirFinder(AndroidDirFinder(this)),
|
||||||
|
taskRunner = appComponent.taskRunner
|
||||||
|
)
|
||||||
|
|
||||||
|
menu = ShowHabitGroupMenu(
|
||||||
|
activity = this,
|
||||||
|
presenter = menuPresenter,
|
||||||
|
preferences = preferences
|
||||||
|
)
|
||||||
|
|
||||||
|
view.setListener(presenter)
|
||||||
|
setContentView(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(m: Menu): Boolean {
|
||||||
|
return menu.onCreateOptionsMenu(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
return menu.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
commandRunner.addListener(this)
|
||||||
|
screen.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
dismissCurrentDialog()
|
||||||
|
commandRunner.removeListener(this)
|
||||||
|
super.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCommandFinished(command: Command) {
|
||||||
|
screen.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class Screen : ShowHabitGroupMenuPresenter.Screen, ShowHabitGroupPresenter.Screen {
|
||||||
|
override fun updateWidgets() {
|
||||||
|
widgetUpdater.updateWidgets()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
scope.launch {
|
||||||
|
view.setState(
|
||||||
|
ShowHabitGroupPresenter.buildState(
|
||||||
|
habitGroup = habitGroup,
|
||||||
|
preferences = preferences,
|
||||||
|
theme = themeSwitcher.currentTheme
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showEditHabitGroupScreen(habitGroup: HabitGroup) {
|
||||||
|
startActivity(IntentFactory().startEditGroupActivity(this@ShowHabitGroupActivity, habitGroup))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showMessage(m: ShowHabitGroupMenuPresenter.Message?) {
|
||||||
|
when (m) {
|
||||||
|
ShowHabitGroupMenuPresenter.Message.COULD_NOT_EXPORT -> {
|
||||||
|
showMessage(resources.getString(R.string.could_not_export))
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showSendFileScreen(filename: String) {
|
||||||
|
this@ShowHabitGroupActivity.showSendFileScreen(filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showDeleteConfirmationScreen(callback: OnConfirmedCallback) {
|
||||||
|
ConfirmDeleteDialog(this@ShowHabitGroupActivity, callback, 1).dismissCurrentAndShow()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
this@ShowHabitGroupActivity.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package org.isoron.uhabits.activities.habits.show
|
||||||
|
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitGroupMenuPresenter
|
||||||
|
|
||||||
|
class ShowHabitGroupMenu(
|
||||||
|
val activity: ShowHabitGroupActivity,
|
||||||
|
val presenter: ShowHabitGroupMenuPresenter,
|
||||||
|
val preferences: Preferences
|
||||||
|
) {
|
||||||
|
fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
activity.menuInflater.inflate(R.menu.show_habit_group, menu)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.action_edit_habit_group -> {
|
||||||
|
presenter.onEditHabit()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
R.id.action_delete -> {
|
||||||
|
presenter.onDeleteHabit()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package org.isoron.uhabits.activities.habits.show
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitGroupPresenter
|
||||||
|
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitGroupState
|
||||||
|
import org.isoron.uhabits.databinding.ShowHabitGroupBinding
|
||||||
|
import org.isoron.uhabits.utils.setupToolbar
|
||||||
|
|
||||||
|
class ShowHabitGroupView(context: Context) : FrameLayout(context) {
|
||||||
|
private val binding = ShowHabitGroupBinding.inflate(LayoutInflater.from(context))
|
||||||
|
|
||||||
|
init {
|
||||||
|
addView(binding.root)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setState(data: ShowHabitGroupState) {
|
||||||
|
setupToolbar(
|
||||||
|
binding.toolbar,
|
||||||
|
title = data.title,
|
||||||
|
color = data.color,
|
||||||
|
theme = data.theme
|
||||||
|
)
|
||||||
|
binding.subtitleCard.setState(data.subtitle)
|
||||||
|
binding.overviewCard.setState(data.overview)
|
||||||
|
binding.notesCard.setState(data.notes)
|
||||||
|
binding.streakCard.setState(data.streaks)
|
||||||
|
binding.scoreCard.setState(data.scores)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setListener(presenter: ShowHabitGroupPresenter) {
|
||||||
|
binding.scoreCard.setListener(presenter.scoreCardPresenter)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import org.isoron.uhabits.activities.about.AboutActivity
|
|||||||
import org.isoron.uhabits.activities.habits.edit.EditHabitActivity
|
import org.isoron.uhabits.activities.habits.edit.EditHabitActivity
|
||||||
import org.isoron.uhabits.activities.habits.edit.EditHabitGroupActivity
|
import org.isoron.uhabits.activities.habits.edit.EditHabitGroupActivity
|
||||||
import org.isoron.uhabits.activities.habits.show.ShowHabitActivity
|
import org.isoron.uhabits.activities.habits.show.ShowHabitActivity
|
||||||
|
import org.isoron.uhabits.activities.habits.show.ShowHabitGroupActivity
|
||||||
import org.isoron.uhabits.activities.intro.IntroActivity
|
import org.isoron.uhabits.activities.intro.IntroActivity
|
||||||
import org.isoron.uhabits.activities.settings.SettingsActivity
|
import org.isoron.uhabits.activities.settings.SettingsActivity
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
@@ -67,6 +68,11 @@ class IntentFactory
|
|||||||
data = Uri.parse(habit.uriString)
|
data = Uri.parse(habit.uriString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun startShowHabitGroupActivity(context: Context, habitGroup: HabitGroup) =
|
||||||
|
Intent(context, ShowHabitGroupActivity::class.java).apply {
|
||||||
|
data = Uri.parse(habitGroup.uriString)
|
||||||
|
}
|
||||||
|
|
||||||
fun viewFAQ(context: Context) =
|
fun viewFAQ(context: Context) =
|
||||||
buildViewIntent(context.getString(R.string.helpURL))
|
buildViewIntent(context.getString(R.string.helpURL))
|
||||||
|
|
||||||
|
|||||||
35
uhabits-android/src/main/res/menu/show_habit_group.xml
Normal file
35
uhabits-android/src/main/res/menu/show_habit_group.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
||||||
|
~
|
||||||
|
~ 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_delete"
|
||||||
|
android:title="@string/delete"
|
||||||
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_edit_habit_group"
|
||||||
|
android:icon="?iconEdit"
|
||||||
|
android:title="@string/edit"
|
||||||
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
@@ -74,12 +74,12 @@ class StreakList {
|
|||||||
from: Timestamp,
|
from: Timestamp,
|
||||||
to: Timestamp
|
to: Timestamp
|
||||||
) {
|
) {
|
||||||
|
if (habitList.isEmpty) return
|
||||||
var current = from
|
var current = from
|
||||||
var streakRunning = false
|
var streakRunning = false
|
||||||
var streakStart = from
|
var streakStart = from
|
||||||
while (current <= to) {
|
while (current <= to) {
|
||||||
if (habitList.all { it.streaks.isInStreaks(current) } && !streakRunning
|
if (habitList.all { it.streaks.isInStreaks(current) } && !streakRunning) {
|
||||||
) {
|
|
||||||
streakStart = current
|
streakStart = current
|
||||||
streakRunning = true
|
streakRunning = true
|
||||||
} else if (streakRunning) {
|
} 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.commands.CreateRepetitionCommand
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
||||||
import org.isoron.uhabits.core.models.Habit
|
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.HabitList
|
||||||
import org.isoron.uhabits.core.models.HabitType
|
import org.isoron.uhabits.core.models.HabitType
|
||||||
import org.isoron.uhabits.core.models.NumericalHabitType.AT_LEAST
|
import org.isoron.uhabits.core.models.NumericalHabitType.AT_LEAST
|
||||||
@@ -51,6 +52,10 @@ open class ListHabitsBehavior @Inject constructor(
|
|||||||
screen.showHabitScreen(h)
|
screen.showHabitScreen(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onClickHabitGroup(hgr: HabitGroup) {
|
||||||
|
screen.showHabitGroupScreen(hgr)
|
||||||
|
}
|
||||||
|
|
||||||
fun onEdit(habit: Habit, timestamp: Timestamp?) {
|
fun onEdit(habit: Habit, timestamp: Timestamp?) {
|
||||||
val entry = habit.computedEntries.get(timestamp!!)
|
val entry = habit.computedEntries.get(timestamp!!)
|
||||||
if (habit.type == HabitType.NUMERICAL) {
|
if (habit.type == HabitType.NUMERICAL) {
|
||||||
@@ -178,6 +183,7 @@ open class ListHabitsBehavior @Inject constructor(
|
|||||||
|
|
||||||
interface Screen {
|
interface Screen {
|
||||||
fun showHabitScreen(h: Habit)
|
fun showHabitScreen(h: Habit)
|
||||||
|
fun showHabitGroupScreen(hgr: HabitGroup)
|
||||||
fun showIntroScreen()
|
fun showIntroScreen()
|
||||||
fun showMessage(m: Message)
|
fun showMessage(m: Message)
|
||||||
fun showNumberPopup(
|
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
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
import org.isoron.uhabits.core.models.Habit
|
||||||
|
import org.isoron.uhabits.core.models.HabitGroup
|
||||||
|
|
||||||
data class NotesCardState(
|
data class NotesCardState(
|
||||||
val description: String
|
val description: String
|
||||||
@@ -30,5 +31,9 @@ class NotesCardPresenter {
|
|||||||
fun buildState(habit: Habit) = NotesCardState(
|
fun buildState(habit: Habit) = NotesCardState(
|
||||||
description = habit.description
|
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.Entry
|
||||||
import org.isoron.uhabits.core.models.Habit
|
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.PaletteColor
|
||||||
import org.isoron.uhabits.core.ui.views.Theme
|
import org.isoron.uhabits.core.ui.views.Theme
|
||||||
import org.isoron.uhabits.core.utils.DateUtils
|
import org.isoron.uhabits.core.utils.DateUtils
|
||||||
@@ -57,5 +58,27 @@ class OverviewCardPresenter {
|
|||||||
theme = theme
|
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
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
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.PaletteColor
|
||||||
import org.isoron.uhabits.core.models.Score
|
import org.isoron.uhabits.core.models.Score
|
||||||
import org.isoron.uhabits.core.preferences.Preferences
|
import org.isoron.uhabits.core.preferences.Preferences
|
||||||
@@ -83,6 +84,45 @@ class ScoreCardPresenter(
|
|||||||
theme = theme
|
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) {
|
fun onSpinnerPosition(position: Int) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
package org.isoron.uhabits.core.ui.screens.habits.show.views
|
||||||
|
|
||||||
import org.isoron.uhabits.core.models.Habit
|
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.PaletteColor
|
||||||
import org.isoron.uhabits.core.models.Streak
|
import org.isoron.uhabits.core.models.Streak
|
||||||
import org.isoron.uhabits.core.ui.views.Theme
|
import org.isoron.uhabits.core.ui.views.Theme
|
||||||
@@ -39,5 +40,13 @@ class StreakCartPresenter {
|
|||||||
theme = theme
|
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.Frequency
|
||||||
import org.isoron.uhabits.core.models.Habit
|
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.NumericalHabitType
|
||||||
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.Reminder
|
||||||
@@ -54,5 +55,17 @@ class SubtitleCardPresenter {
|
|||||||
unit = habit.unit,
|
unit = habit.unit,
|
||||||
theme = theme
|
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