Make HabitGroups simpler

No subgroups
This commit is contained in:
Dharanish
2024-05-28 19:39:53 +02:00
parent 262b49d025
commit 832d51a055
13 changed files with 361 additions and 80 deletions

View File

@@ -0,0 +1,232 @@
package org.isoron.uhabits.activities.habits.edit
import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Bundle
import android.text.Html
import android.text.Spanned
import android.text.format.DateFormat
import android.view.View
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.DialogFragment
import com.android.datetimepicker.time.RadialPickerLayout
import com.android.datetimepicker.time.TimePickerDialog
import org.isoron.platform.gui.toInt
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.AndroidThemeSwitcher
import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory
import org.isoron.uhabits.activities.common.dialogs.WeekdayPickerDialog
import org.isoron.uhabits.core.commands.CommandRunner
import org.isoron.uhabits.core.commands.CreateHabitGroupCommand
import org.isoron.uhabits.core.commands.EditHabitGroupCommand
import org.isoron.uhabits.core.models.HabitGroup
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.models.Reminder
import org.isoron.uhabits.core.models.WeekdayList
import org.isoron.uhabits.databinding.ActivityEditHabitGroupBinding
import org.isoron.uhabits.utils.ColorUtils
import org.isoron.uhabits.utils.dismissCurrentAndShow
import org.isoron.uhabits.utils.formatTime
import org.isoron.uhabits.utils.toFormattedString
class EditHabitGroupActivity : AppCompatActivity() {
private lateinit var themeSwitcher: AndroidThemeSwitcher
private lateinit var binding: ActivityEditHabitGroupBinding
private lateinit var commandRunner: CommandRunner
var habitGroupId = -1L
var color = PaletteColor(11)
var androidColor = 0
var reminderHour = -1
var reminderMin = -1
var reminderDays: WeekdayList = WeekdayList.EVERY_DAY
override fun onCreate(state: Bundle?) {
super.onCreate(state)
val component = (application as HabitsApplication).component
themeSwitcher = AndroidThemeSwitcher(this, component.preferences)
themeSwitcher.apply()
binding = ActivityEditHabitGroupBinding.inflate(layoutInflater)
setContentView(binding.root)
if (intent.hasExtra("habitGroupId")) {
binding.toolbar.title = getString(R.string.edit_habit_group)
habitGroupId = intent.getLongExtra("habitId", -1)
val hgr = component.habitGroupList.getById(habitGroupId)!!
color = hgr.color
hgr.reminder?.let {
reminderHour = it.hour
reminderMin = it.minute
reminderDays = it.days
}
binding.nameInput.setText(hgr.name)
binding.questionInput.setText(hgr.question)
binding.notesInput.setText(hgr.description)
}
if (state != null) {
habitGroupId = state.getLong("habitGroupId")
color = PaletteColor(state.getInt("paletteColor"))
reminderHour = state.getInt("reminderHour")
reminderMin = state.getInt("reminderMin")
reminderDays = WeekdayList(state.getInt("reminderDays"))
}
updateColors()
setSupportActionBar(binding.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
supportActionBar?.elevation = 10.0f
val colorPickerDialogFactory = ColorPickerDialogFactory(this)
binding.colorButton.setOnClickListener {
val picker = colorPickerDialogFactory.create(color, themeSwitcher.currentTheme)
picker.setListener { paletteColor ->
this.color = paletteColor
updateColors()
}
picker.dismissCurrentAndShow(supportFragmentManager, "colorPicker")
}
populateReminder()
binding.reminderTimePicker.setOnClickListener {
val currentHour = if (reminderHour >= 0) reminderHour else 8
val currentMin = if (reminderMin >= 0) reminderMin else 0
val is24HourMode = DateFormat.is24HourFormat(this)
val dialog = TimePickerDialog.newInstance(
object : TimePickerDialog.OnTimeSetListener {
override fun onTimeSet(view: RadialPickerLayout?, hourOfDay: Int, minute: Int) {
reminderHour = hourOfDay
reminderMin = minute
populateReminder()
}
override fun onTimeCleared(view: RadialPickerLayout?) {
reminderHour = -1
reminderMin = -1
reminderDays = WeekdayList.EVERY_DAY
populateReminder()
}
},
currentHour,
currentMin,
is24HourMode,
androidColor
)
dialog.dismissCurrentAndShow(supportFragmentManager, "timePicker")
}
binding.reminderDatePicker.setOnClickListener {
val dialog = WeekdayPickerDialog()
dialog.setListener { days: WeekdayList ->
reminderDays = days
if (reminderDays.isEmpty) reminderDays = WeekdayList.EVERY_DAY
populateReminder()
}
dialog.setSelectedDays(reminderDays)
dialog.dismissCurrentAndShow(supportFragmentManager, "dayPicker")
}
binding.buttonSave.setOnClickListener {
if (validate()) save()
}
for (fragment in supportFragmentManager.fragments) {
(fragment as DialogFragment).dismiss()
}
}
private fun save() {
val component = (application as HabitsApplication).component
val hgr = component.modelFactory.buildHabitGroup()
var original: HabitGroup? = null
if (habitGroupId >= 0) {
original = component.habitGroupList.getById(habitGroupId)!!
hgr.copyFrom(original)
}
hgr.name = binding.nameInput.text.trim().toString()
hgr.question = binding.questionInput.text.trim().toString()
hgr.description = binding.notesInput.text.trim().toString()
hgr.color = color
if (reminderHour >= 0) {
hgr.reminder = Reminder(reminderHour, reminderMin, reminderDays)
} else {
hgr.reminder = null
}
val command = if (habitGroupId >= 0) {
EditHabitGroupCommand(
component.habitGroupList,
habitGroupId,
hgr
)
} else {
CreateHabitGroupCommand(
component.modelFactory,
component.habitGroupList,
hgr
)
}
component.commandRunner.run(command)
finish()
}
private fun validate(): Boolean {
var isValid = true
if (binding.nameInput.text.isEmpty()) {
binding.nameInput.error = getFormattedValidationError(R.string.validation_cannot_be_blank)
isValid = false
}
return isValid
}
private fun populateReminder() {
if (reminderHour < 0) {
binding.reminderTimePicker.text = getString(R.string.reminder_off)
binding.reminderDatePicker.visibility = View.GONE
binding.reminderDivider.visibility = View.GONE
} else {
val time = formatTime(this, reminderHour, reminderMin)
binding.reminderTimePicker.text = time
binding.reminderDatePicker.visibility = View.VISIBLE
binding.reminderDivider.visibility = View.VISIBLE
binding.reminderDatePicker.text = reminderDays.toFormattedString(this)
}
}
private fun updateColors() {
androidColor = themeSwitcher.currentTheme.color(color).toInt()
binding.colorButton.backgroundTintList = ColorStateList.valueOf(androidColor)
if (!themeSwitcher.isNightMode) {
val darkerAndroidColor = ColorUtils.mixColors(Color.BLACK, androidColor, 0.15f)
window.statusBarColor = darkerAndroidColor
binding.toolbar.setBackgroundColor(androidColor)
}
}
private fun getFormattedValidationError(@StringRes resId: Int): Spanned {
val html = "<font color=#FFFFFF>${getString(resId)}</font>"
return Html.fromHtml(html)
}
override fun onSaveInstanceState(state: Bundle) {
super.onSaveInstanceState(state)
with(state) {
putLong("habitGroupId", habitGroupId)
putInt("paletteColor", color.paletteIndex)
putInt("androidColor", androidColor)
putInt("reminderHour", reminderHour)
putInt("reminderMin", reminderMin)
putInt("reminderDays", reminderDays.toInteger())
}
}
}

View File

@@ -25,10 +25,12 @@ import android.net.Uri
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.about.AboutActivity
import org.isoron.uhabits.activities.habits.edit.EditHabitActivity
import org.isoron.uhabits.activities.habits.edit.EditHabitGroupActivity
import org.isoron.uhabits.activities.habits.show.ShowHabitActivity
import org.isoron.uhabits.activities.intro.IntroActivity
import org.isoron.uhabits.activities.settings.SettingsActivity
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitGroup
import javax.inject.Inject
class IntentFactory
@@ -100,4 +102,14 @@ class IntentFactory
intent.putExtra("habitType", habitType)
return intent
}
fun startEditGroupActivity(context: Context): Intent {
return Intent(context, EditHabitGroupActivity::class.java)
}
fun startEditGroupActivity(context: Context, habitGroup: HabitGroup): Intent {
val intent = startEditGroupActivity(context)
intent.putExtra("habitGroupId", habitGroup.id)
return intent
}
}

View File

@@ -0,0 +1,72 @@
<!--
~ 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/>.
-->
<RelativeLayout
android:id="@+id/container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
style="@style/Toolbar"
app:popupTheme="?toolbarPopupTheme"
android:layout_alignParentTop="true"/>
<ScrollView
android:id="@+id/scrollView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/toolbar"
android:background="?windowBackgroundColor"
android:clipToPadding="false">
<LinearLayout
style="@style/CardList"
android:clipToPadding="false">
<org.isoron.uhabits.activities.habits.show.views.SubtitleCardView
android:id="@+id/subtitleCard"
style="@style/ShowHabit.Subtitle"/>
<org.isoron.uhabits.activities.habits.show.views.NotesCardView
android:id="@+id/notesCard"
style="@style/Card"
android:gravity="center" />
<org.isoron.uhabits.activities.habits.show.views.OverviewCardView
android:id="@+id/overviewCard"
style="@style/Card"
android:paddingTop="12dp"/>
<org.isoron.uhabits.activities.habits.show.views.ScoreCardView
android:id="@+id/scoreCard"
style="@style/Card"
android:gravity="center"/>
<org.isoron.uhabits.activities.habits.show.views.StreakCardView
android:id="@+id/streakCard"
style="@style/Card"/>
</LinearLayout>
</ScrollView>
</RelativeLayout>