diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitGroupActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitGroupActivity.kt index 50fc5ef78..03761f26c 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitGroupActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitGroupActivity.kt @@ -56,7 +56,7 @@ class EditHabitGroupActivity : AppCompatActivity() { if (intent.hasExtra("habitGroupId")) { binding.toolbar.title = getString(R.string.edit_habit_group) - habitGroupId = intent.getLongExtra("habitId", -1) + habitGroupId = intent.getLongExtra("habitGroupId", -1) val hgr = component.habitGroupList.getById(habitGroupId)!! color = hgr.color hgr.reminder?.let { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt index 4441cdbdc..cd10b4285 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.kt @@ -41,6 +41,7 @@ import org.isoron.uhabits.core.commands.ChangeHabitColorCommand import org.isoron.uhabits.core.commands.Command import org.isoron.uhabits.core.commands.CommandRunner import org.isoron.uhabits.core.commands.CreateHabitCommand +import org.isoron.uhabits.core.commands.DeleteHabitGroupsCommand import org.isoron.uhabits.core.commands.DeleteHabitsCommand import org.isoron.uhabits.core.commands.EditHabitCommand import org.isoron.uhabits.core.commands.UnarchiveHabitsCommand @@ -179,6 +180,11 @@ class ListHabitsScreen activity.startActivity(intent) } + override fun showEditHabitGroupScreen(selected: List) { + val intent = intentFactory.startEditGroupActivity(activity, selected[0]) + activity.startActivity(intent) + } + override fun showFAQScreen() { val intent = intentFactory.viewFAQ(activity) activity.startActivity(intent) @@ -318,6 +324,12 @@ class ListHabitsScreen command.selected.size ) } + is DeleteHabitGroupsCommand -> { + return activity.resources.getQuantityString( + R.plurals.toast_habits_deleted, + command.selected.size + ) + } is EditHabitCommand -> { return activity.resources.getQuantityString(R.plurals.toast_habits_changed, 1) } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt index 03e50fa6d..bf54b3ce6 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsSelectionMenu.kt @@ -82,7 +82,7 @@ class ListHabitsSelectionMenu @Inject constructor( itemArchive.isVisible = behavior.canArchive() itemUnarchive.isVisible = behavior.canUnarchive() itemNotify.isVisible = prefs.isDeveloper - activeActionMode?.title = listAdapter.selectedHabits.size.toString() + activeActionMode?.title = (listAdapter.selectedHabits.size + listAdapter.selectedHabitGroups.size).toString() return true } override fun onDestroyActionMode(mode: ActionMode?) { diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.kt index 264978c66..8d1080ea5 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListAdapter.kt @@ -79,11 +79,12 @@ class HabitCardListAdapter @Inject constructor( */ override fun clearSelection() { selectedHabits.clear() + selectedHabitGroups.clear() notifyDataSetChanged() observable.notifyListeners() } - override fun getSelected(): List { + override fun getSelectedHabits(): List { return ArrayList(selectedHabits) } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitGroupActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitGroupActivity.kt index 97bab67c2..d204f7a48 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitGroupActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitGroupActivity.kt @@ -8,11 +8,9 @@ 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 @@ -68,9 +66,7 @@ class ShowHabitGroupActivity : AppCompatActivity(), CommandRunner.Listener { commandRunner = commandRunner, habitGroup = habitGroup, habitGroupList = habitGroupList, - screen = screen, - system = HabitGroupsDirFinder(AndroidDirFinder(this)), - taskRunner = appComponent.taskRunner + screen = screen ) menu = ShowHabitGroupMenu( diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitGroupMenu.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitGroupMenu.kt index 4ee4eedb5..1dc4bbd03 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitGroupMenu.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/ShowHabitGroupMenu.kt @@ -19,11 +19,11 @@ class ShowHabitGroupMenu( fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.action_edit_habit_group -> { - presenter.onEditHabit() + presenter.onEditHabitGroup() return true } R.id.action_delete -> { - presenter.onDeleteHabit() + presenter.onDeleteHabitGroup() return true } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsSelectionMenuBehavior.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsSelectionMenuBehavior.kt index 49df8afab..231fa4c45 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsSelectionMenuBehavior.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsSelectionMenuBehavior.kt @@ -18,13 +18,17 @@ */ package org.isoron.uhabits.core.ui.screens.habits.list +import org.isoron.uhabits.core.commands.ArchiveHabitGroupsCommand import org.isoron.uhabits.core.commands.ArchiveHabitsCommand import org.isoron.uhabits.core.commands.ChangeHabitColorCommand +import org.isoron.uhabits.core.commands.ChangeHabitGroupColorCommand import org.isoron.uhabits.core.commands.CommandRunner +import org.isoron.uhabits.core.commands.DeleteHabitGroupsCommand import org.isoron.uhabits.core.commands.DeleteHabitsCommand import org.isoron.uhabits.core.commands.UnarchiveHabitsCommand import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.HabitGroup +import org.isoron.uhabits.core.models.HabitGroupList import org.isoron.uhabits.core.models.HabitList import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.ui.callbacks.OnColorPickedCallback @@ -33,33 +37,55 @@ import javax.inject.Inject class ListHabitsSelectionMenuBehavior @Inject constructor( private val habitList: HabitList, + private val habitGroupList: HabitGroupList, private val screen: Screen, private val adapter: Adapter, var commandRunner: CommandRunner ) { fun canArchive(): Boolean { - for (habit in adapter.getSelected()) if (habit.isArchived) return false + for (habit in adapter.getSelectedHabits()) if (habit.isArchived) return false + for (hgr in adapter.getSelectedHabitGroups()) if (hgr.isArchived) return false return true } fun canEdit(): Boolean { - return adapter.getSelected().size == 1 + return (adapter.getSelectedHabits().size + adapter.getSelectedHabitGroups().size == 1) } fun canUnarchive(): Boolean { - for (habit in adapter.getSelected()) if (!habit.isArchived) return false + for (habit in adapter.getSelectedHabits()) if (!habit.isArchived) return false + for (hgr in adapter.getSelectedHabitGroups()) if (!hgr.isArchived) return false return true } fun onArchiveHabits() { - commandRunner.run(ArchiveHabitsCommand(habitList, adapter.getSelected())) + commandRunner.run(ArchiveHabitsCommand(habitList, adapter.getSelectedHabits())) + commandRunner.run(ArchiveHabitGroupsCommand(habitGroupList, adapter.getSelectedHabitGroups())) adapter.clearSelection() } fun onChangeColor() { - val (color) = adapter.getSelected()[0] + val color = if (adapter.getSelectedHabits().isNotEmpty()) { + adapter.getSelectedHabits()[0].color + } else { + adapter.getSelectedHabitGroups()[0].color + } + screen.showColorPicker(color) { selectedColor: PaletteColor -> - commandRunner.run(ChangeHabitColorCommand(habitList, adapter.getSelected(), selectedColor)) + commandRunner.run( + ChangeHabitColorCommand( + habitList, + adapter.getSelectedHabits(), + selectedColor + ) + ) + commandRunner.run( + ChangeHabitGroupColorCommand( + habitGroupList, + adapter.getSelectedHabitGroups(), + selectedColor + ) + ) adapter.clearSelection() } } @@ -67,28 +93,36 @@ class ListHabitsSelectionMenuBehavior @Inject constructor( fun onDeleteHabits() { screen.showDeleteConfirmationScreen( { - adapter.performRemove(adapter.getSelected()) - commandRunner.run(DeleteHabitsCommand(habitList, adapter.getSelected())) + adapter.performRemove(adapter.getSelectedHabits()) + adapter.performRemoveHabitGroup(adapter.getSelectedHabitGroups()) + commandRunner.run(DeleteHabitsCommand(habitList, adapter.getSelectedHabits())) + commandRunner.run(DeleteHabitGroupsCommand(habitGroupList, adapter.getSelectedHabitGroups())) adapter.clearSelection() }, - adapter.getSelected().size + adapter.getSelectedHabits().size + adapter.getSelectedHabitGroups().size ) } fun onEditHabits() { - val selected = adapter.getSelected() - if (selected.isNotEmpty()) screen.showEditHabitsScreen(selected) + val selected = adapter.getSelectedHabits() + if (selected.isNotEmpty()) { + screen.showEditHabitsScreen(selected) + } else { + val selectedGroup = adapter.getSelectedHabitGroups() + screen.showEditHabitGroupScreen(selectedGroup) + } + adapter.clearSelection() } fun onUnarchiveHabits() { - commandRunner.run(UnarchiveHabitsCommand(habitList, adapter.getSelected())) + commandRunner.run(UnarchiveHabitsCommand(habitList, adapter.getSelectedHabits())) adapter.clearSelection() } interface Adapter { fun clearSelection() - fun getSelected(): List + fun getSelectedHabits(): List fun getSelectedHabitGroups(): List fun performRemove(selected: List) fun performRemoveHabitGroup(selected: List) @@ -106,5 +140,7 @@ class ListHabitsSelectionMenuBehavior @Inject constructor( ) fun showEditHabitsScreen(selected: List) + + fun showEditHabitGroupScreen(selected: List) } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitGroupMenuPresenter.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitGroupMenuPresenter.kt index 196d9a8a1..0d468dd5e 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitGroupMenuPresenter.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitGroupMenuPresenter.kt @@ -4,7 +4,6 @@ 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 @@ -12,15 +11,13 @@ 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 + private val screen: Screen ) { - fun onEditHabit() { + fun onEditHabitGroup() { screen.showEditHabitGroupScreen(habitGroup) } - fun onDeleteHabit() { + fun onDeleteHabitGroup() { screen.showDeleteConfirmationScreen { commandRunner.run(DeleteHabitGroupsCommand(habitGroupList, listOf(habitGroup))) screen.close() diff --git a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsSelectionMenuBehaviorTest.kt b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsSelectionMenuBehaviorTest.kt index b60ee037c..edb08d934 100644 --- a/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsSelectionMenuBehaviorTest.kt +++ b/uhabits-core/src/jvmTest/java/org/isoron/uhabits/core/ui/screens/habits/list/ListHabitsSelectionMenuBehaviorTest.kt @@ -52,27 +52,27 @@ class ListHabitsSelectionMenuBehaviorTest : BaseUnitTest() { @Test @Throws(Exception::class) fun canArchive() { - whenever(adapter.getSelected()).thenReturn(listOf(habit1, habit2)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit1, habit2)) assertFalse(behavior.canArchive()) - whenever(adapter.getSelected()).thenReturn(listOf(habit2, habit3)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit2, habit3)) assertTrue(behavior.canArchive()) } @Test @Throws(Exception::class) fun canEdit() { - whenever(adapter.getSelected()).thenReturn(listOf(habit1)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit1)) assertTrue(behavior.canEdit()) - whenever(adapter.getSelected()).thenReturn(listOf(habit1, habit2)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit1, habit2)) assertFalse(behavior.canEdit()) } @Test @Throws(Exception::class) fun canUnarchive() { - whenever(adapter.getSelected()).thenReturn(listOf(habit1, habit2)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit1, habit2)) assertFalse(behavior.canUnarchive()) - whenever(adapter.getSelected()).thenReturn(listOf(habit1)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit1)) assertTrue(behavior.canUnarchive()) } @@ -80,7 +80,7 @@ class ListHabitsSelectionMenuBehaviorTest : BaseUnitTest() { @Throws(Exception::class) fun onArchiveHabits() { assertFalse(habit2.isArchived) - whenever(adapter.getSelected()).thenReturn(listOf(habit2)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit2)) behavior.onArchiveHabits() assertTrue(habit2.isArchived) } @@ -90,7 +90,7 @@ class ListHabitsSelectionMenuBehaviorTest : BaseUnitTest() { fun onChangeColor() { assertThat(habit1.color, equalTo(PaletteColor(8))) assertThat(habit2.color, equalTo(PaletteColor(8))) - whenever(adapter.getSelected()).thenReturn(listOf(habit1, habit2)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit1, habit2)) behavior.onChangeColor() verify(screen) .showColorPicker(eq(PaletteColor(8)), colorPickerCallback.capture()) @@ -103,7 +103,7 @@ class ListHabitsSelectionMenuBehaviorTest : BaseUnitTest() { fun onDeleteHabits() { val id = habit1.id!! habitList.getById(id)!! - whenever(adapter.getSelected()).thenReturn(listOf(habit1)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit1)) behavior.onDeleteHabits() verify(screen).showDeleteConfirmationScreen(deleteCallback.capture(), eq(1)) deleteCallback.lastValue.onConfirmed() @@ -114,7 +114,7 @@ class ListHabitsSelectionMenuBehaviorTest : BaseUnitTest() { @Throws(Exception::class) fun onEditHabits() { val selected: List = listOf(habit1, habit2) - whenever(adapter.getSelected()).thenReturn(selected) + whenever(adapter.getSelectedHabits()).thenReturn(selected) behavior.onEditHabits() verify(screen).showEditHabitsScreen(selected) } @@ -123,7 +123,7 @@ class ListHabitsSelectionMenuBehaviorTest : BaseUnitTest() { @Throws(Exception::class) fun onUnarchiveHabits() { assertTrue(habit1.isArchived) - whenever(adapter.getSelected()).thenReturn(listOf(habit1)) + whenever(adapter.getSelectedHabits()).thenReturn(listOf(habit1)) behavior.onUnarchiveHabits() assertFalse(habit1.isArchived) }