diff --git a/uhabits-android/src/main/AndroidManifest.xml b/uhabits-android/src/main/AndroidManifest.xml index 1d9dc6620..1f3aba1aa 100644 --- a/uhabits-android/src/main/AndroidManifest.xml +++ b/uhabits-android/src/main/AndroidManifest.xml @@ -42,6 +42,14 @@ android:value=".activities.habits.list.ListHabitsActivity" /> + + + + diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/HabitGroupPickerDialog.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/HabitGroupPickerDialog.kt new file mode 100644 index 000000000..aea309d83 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/list/HabitGroupPickerDialog.kt @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016-2021 Álinson Santos Xavier + * + * 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 . + */ + +package org.isoron.uhabits.activities.habits.list + +import android.app.Activity +import android.os.Bundle +import android.widget.ArrayAdapter +import android.widget.ListView +import android.widget.TextView +import org.isoron.uhabits.HabitsApplication +import org.isoron.uhabits.R +import org.isoron.uhabits.activities.AndroidThemeSwitcher +import org.isoron.uhabits.core.commands.AddToGroupCommand +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.HabitGroupList +import org.isoron.uhabits.core.models.HabitList +import org.isoron.uhabits.inject.HabitsApplicationComponent + +class HabitGroupPickerDialog : Activity() { + + private lateinit var habitGroupList: HabitGroupList + private lateinit var habitList: HabitList + private lateinit var selected: List + private lateinit var component: HabitsApplicationComponent + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + component = (applicationContext as HabitsApplication).component + AndroidThemeSwitcher(this, component.preferences).apply() + habitList = component.habitList + habitGroupList = component.habitGroupList + + val selectedIds = intent.getLongArrayExtra("selected")!! + selected = selectedIds.map { id -> + habitList.getById(id) ?: habitGroupList.getHabitByID(id)!! + } + + val groupIds = ArrayList() + val groupNames = ArrayList() + + for (hgr in habitGroupList) { + if (hgr.isArchived) continue + groupIds.add(hgr.id!!) + groupNames.add(hgr.name) + } + + if (groupNames.isEmpty()) { + setContentView(R.layout.widget_empty_activity) + findViewById(R.id.message).setText(R.string.no_habit_groups) + return + } + + setContentView(R.layout.widget_configure_activity) + val listView = findViewById(R.id.listView) + + with(listView) { + adapter = ArrayAdapter( + context, + android.R.layout.simple_list_item_1, + groupNames + ) + setOnItemClickListener { parent, view, position, id -> + performTransfer(groupIds[position]) + } + } + } + private fun performTransfer(toGroupId: Long) { + val hgr = habitGroupList.getById(toGroupId)!! + selected = selected.filter { it.groupId != hgr.id } + component.commandRunner.run( + AddToGroupCommand(habitList, hgr, selected) + ) + finish() + } +} 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 abfa0e48f..8feb12748 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 @@ -185,6 +185,11 @@ class ListHabitsScreen activity.startActivity(intent) } + override fun showHabitGroupPickerDialog(selected: List) { + val intent = intentFactory.startHabitGroupPickerActivity(activity, selected) + activity.startActivity(intent) + } + override fun showFAQScreen() { val intent = intentFactory.viewFAQ(activity) activity.startActivity(intent) 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 ddd9a3b58..35c5563bc 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 @@ -76,6 +76,7 @@ class ListHabitsSelectionMenu @Inject constructor( val itemArchive = menu.findItem(R.id.action_archive_habit) val itemUnarchive = menu.findItem(R.id.action_unarchive_habit) val itemRemoveFromGroup = menu.findItem(R.id.action_remove_from_group) + val itemAddToGroup = menu.findItem(R.id.action_add_to_group) val itemNotify = menu.findItem(R.id.action_notify) itemColor.isVisible = true @@ -83,6 +84,7 @@ class ListHabitsSelectionMenu @Inject constructor( itemArchive.isVisible = behavior.canArchive() itemUnarchive.isVisible = behavior.canUnarchive() itemRemoveFromGroup.isVisible = behavior.areSubHabits() + itemAddToGroup.isVisible = behavior.areHabits() itemNotify.isVisible = prefs.isDeveloper activeActionMode?.title = (listAdapter.selectedHabits.size + listAdapter.selectedHabitGroups.size).toString() return true @@ -113,6 +115,11 @@ class ListHabitsSelectionMenu @Inject constructor( return true } + R.id.action_add_to_group -> { + behavior.onAddToGroup() + return true + } + R.id.action_delete -> { behavior.onDeleteHabits() return true diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt index b6c6b9034..b426d9864 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentFactory.kt @@ -26,6 +26,7 @@ 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.list.HabitGroupPickerDialog import org.isoron.uhabits.activities.habits.show.ShowHabitActivity import org.isoron.uhabits.activities.habits.show.ShowHabitGroupActivity import org.isoron.uhabits.activities.intro.IntroActivity @@ -124,4 +125,11 @@ class IntentFactory intent.putExtra("habitGroupId", habitGroup.id) return intent } + + fun startHabitGroupPickerActivity(context: Context, selected: List): Intent { + val intent = Intent(context, HabitGroupPickerDialog::class.java) + val ids = selected.map { it.id!! }.toLongArray() + intent.putExtra("selected", ids) + return intent + } } diff --git a/uhabits-android/src/main/res/menu/list_habits_selection.xml b/uhabits-android/src/main/res/menu/list_habits_selection.xml index 4a3a986b5..3264edb19 100644 --- a/uhabits-android/src/main/res/menu/list_habits_selection.xml +++ b/uhabits-android/src/main/res/menu/list_habits_selection.xml @@ -41,6 +41,11 @@ android:title="@string/unarchive" app:showAsAction="never"/> + + Archive Unarchive Remove from group + Add to group Add habit Change color Habit created @@ -239,4 +240,5 @@ Extend day a few hours past midnight Wait until 3:00 AM to show a new day. Useful if you typically go to sleep after midnight. Requires app restart. Group contains no habits. + No habit groups diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/AddToGroupCommand.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/AddToGroupCommand.kt new file mode 100644 index 000000000..aaf014f5b --- /dev/null +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/commands/AddToGroupCommand.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2016-2021 Álinson Santos Xavier + * + * 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 . + */ +package org.isoron.uhabits.core.commands + +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.HabitGroup +import org.isoron.uhabits.core.models.HabitList + +data class AddToGroupCommand( + val habitList: HabitList, + val hgr: HabitGroup, + val selected: List +) : Command { + override fun run() { + for (h in selected) { + val oldGroup = h.group + (oldGroup?.habitList ?: habitList).remove(h) + h.groupId = hgr.id + h.groupUUID = hgr.uuid + h.group = hgr + hgr.habitList.add(h) + } + } +} 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 9f81cb487..7ee8d3d58 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 @@ -65,6 +65,10 @@ class ListHabitsSelectionMenuBehavior @Inject constructor( return (adapter.getSelectedHabits().all { it.isSubHabit() }) } + fun areHabits(): Boolean { + return adapter.getSelectedHabitGroups().isEmpty() + } + fun onArchiveHabits() { commandRunner.run(ArchiveHabitsCommand(habitList, adapter.getSelectedHabits())) commandRunner.run(ArchiveHabitGroupsCommand(habitGroupList, adapter.getSelectedHabitGroups())) @@ -142,6 +146,12 @@ class ListHabitsSelectionMenuBehavior @Inject constructor( adapter.clearSelection() } + fun onAddToGroup() { + adapter.performRemove(adapter.getSelectedHabits()) + screen.showHabitGroupPickerDialog(adapter.getSelectedHabits()) + adapter.clearSelection() + } + interface Adapter { fun clearSelection() fun getSelectedHabits(): List @@ -164,5 +174,6 @@ class ListHabitsSelectionMenuBehavior @Inject constructor( fun showEditHabitsScreen(selected: List) fun showEditHabitGroupScreen(selected: List) + fun showHabitGroupPickerDialog(selected: List) } }