mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 19:56:32 +00:00
Improve group task display
This commit is contained in:
parent
149e5b01a7
commit
a7e3e11526
23 changed files with 119 additions and 75 deletions
|
|
@ -265,10 +265,9 @@
|
|||
<string name="notification_purchase_reward" >You purchased a reward</string>
|
||||
<string name="world_quest">World Quest</string>
|
||||
<string name="inn_description">Need a break? Check into Daniel’s Inn to pause some of Habitica’s more difficult game mechanics:\n\n
|
||||
• Missed Dailies won’t damage you\n
|
||||
• Tasks won’t lose streaks or decay in color\n
|
||||
• Bosses won’t do damage for your missed Dailies\n
|
||||
• Your boss damage or collection quest items will stay pending until check-out</string>
|
||||
• Your missed Dailies won\'t damage you (bosses will still do damage caused by other Party member\'s missed Dailies)
|
||||
• Your Task streaks and Habit counters will not reset
|
||||
• Your damage to the Quest boss or found collection items will remain pending until you check out of the Inn</string>
|
||||
<string name="empty_items">You don\'t have any %s</string>
|
||||
<string name="user_level_with_class">Lvl %1$d %2$s</string>
|
||||
<string name="user_level_with_class_unabbreviated">Level %1$d %2$s</string>
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ package com.habitrpg.android.habitica.data
|
|||
|
||||
import com.habitrpg.android.habitica.models.BaseMainObject
|
||||
import com.habitrpg.android.habitica.models.responses.BulkTaskScoringData
|
||||
import com.habitrpg.common.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.tasks.TaskList
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.common.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.common.habitica.models.tasks.TasksOrder
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
|
|
@ -15,8 +15,8 @@ import kotlinx.coroutines.flow.Flow
|
|||
import java.util.Date
|
||||
|
||||
interface TaskRepository : BaseRepository {
|
||||
fun getTasks(taskType: TaskType, userID: String? = null): Flow<List<Task>>
|
||||
fun getTasksFlowable(taskType: TaskType, userID: String? = null): Flowable<out List<Task>>
|
||||
fun getTasks(taskType: TaskType, userID: String? = null, includedGroupIDs: Array<String>): Flow<List<Task>>
|
||||
fun getTasksFlowable(taskType: TaskType, userID: String? = null, includedGroupIDs: Array<String>): Flowable<out List<Task>>
|
||||
fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList)
|
||||
|
||||
fun retrieveTasks(userId: String, tasksOrder: TasksOrder): Flowable<TaskList>
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ class TaskRepositoryImpl(
|
|||
) : BaseRepositoryImpl<TaskLocalRepository>(localRepository, apiClient, userID), TaskRepository {
|
||||
private var lastTaskAction: Long = 0
|
||||
|
||||
override fun getTasks(taskType: TaskType, userID: String?): Flow<List<Task>> =
|
||||
this.localRepository.getTasks(taskType, userID ?: this.userID)
|
||||
override fun getTasks(taskType: TaskType, userID: String?, includedGroupIDs: Array<String>): Flow<List<Task>> =
|
||||
this.localRepository.getTasks(taskType, userID ?: this.userID, includedGroupIDs)
|
||||
|
||||
override fun getTasksFlowable(taskType: TaskType, userID: String?): Flowable<out List<Task>> =
|
||||
this.localRepository.getTasksFlowable(taskType, userID ?: this.userID)
|
||||
override fun getTasksFlowable(taskType: TaskType, userID: String?, includedGroupIDs: Array<String>): Flowable<out List<Task>> =
|
||||
this.localRepository.getTasksFlowable(taskType, userID ?: this.userID, includedGroupIDs)
|
||||
|
||||
override fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList) {
|
||||
localRepository.saveTasks(userId, order, tasks)
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@ package com.habitrpg.android.habitica.data.local
|
|||
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.tasks.TaskList
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.common.habitica.models.tasks.TasksOrder
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface TaskLocalRepository : BaseLocalRepository {
|
||||
|
||||
fun getTasks(taskType: TaskType, userID: String): Flow<List<Task>>
|
||||
fun getTasksFlowable(taskType: TaskType, userID: String): Flowable<out List<Task>>
|
||||
fun getTasks(taskType: TaskType, userID: String, includedGroupIDs: Array<String>): Flow<List<Task>>
|
||||
fun getTasksFlowable(taskType: TaskType, userID: String, includedGroupIDs: Array<String>): Flowable<out List<Task>>
|
||||
fun getTasks(userId: String): Flow<List<Task>>
|
||||
|
||||
fun saveTasks(ownerID: String, tasksOrder: TasksOrder, tasks: TaskList)
|
||||
|
|
|
|||
|
|
@ -21,22 +21,30 @@ import kotlinx.coroutines.flow.filter
|
|||
|
||||
class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TaskLocalRepository {
|
||||
|
||||
override fun getTasks(taskType: TaskType, userID: String): Flow<List<Task>> {
|
||||
override fun getTasks(taskType: TaskType, userID: String, includedGroupIDs: Array<String>): Flow<List<Task>> {
|
||||
if (realm.isClosed) return emptyFlow()
|
||||
return realm.where(Task::class.java)
|
||||
.equalTo("typeValue", taskType.value)
|
||||
.beginGroup()
|
||||
.equalTo("userId", userID)
|
||||
.or()
|
||||
.`in`("group.groupID", includedGroupIDs)
|
||||
.endGroup()
|
||||
.sort("position", Sort.ASCENDING, "dateCreated", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { it.isLoaded }
|
||||
}
|
||||
|
||||
override fun getTasksFlowable(taskType: TaskType, userID: String): Flowable<out List<Task>> {
|
||||
override fun getTasksFlowable(taskType: TaskType, userID: String, includedGroupIDs: Array<String>): Flowable<out List<Task>> {
|
||||
if (realm.isClosed) return Flowable.empty()
|
||||
return RxJavaBridge.toV3Flowable(realm.where(Task::class.java)
|
||||
.equalTo("typeValue", taskType.value)
|
||||
.beginGroup()
|
||||
.equalTo("userId", userID)
|
||||
.or()
|
||||
.`in`("group.groupID", includedGroupIDs)
|
||||
.endGroup()
|
||||
.sort("position", Sort.ASCENDING, "dateCreated", Sort.DESCENDING)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
|
|
@ -53,17 +61,20 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
}
|
||||
|
||||
override fun saveTasks(ownerID: String, tasksOrder: TasksOrder, tasks: TaskList) {
|
||||
val sortedTasks = ArrayList<Task>()
|
||||
val sortedTasks = mutableListOf<Task>()
|
||||
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.habits))
|
||||
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.dailys))
|
||||
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.todos))
|
||||
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.rewards))
|
||||
for (task in tasks.tasks.values) {
|
||||
task.position = (sortedTasks.lastOrNull { it.type == task.type }?.position ?: -1) + 1
|
||||
sortedTasks.add(task)
|
||||
}
|
||||
removeOldTasks(ownerID, sortedTasks)
|
||||
|
||||
val allChecklistItems = ArrayList<ChecklistItem>()
|
||||
val allReminders = ArrayList<RemindersItem>()
|
||||
sortedTasks.forEach {
|
||||
if (it.userId.isBlank()) it.userId = ownerID
|
||||
it.checklist?.let { it1 -> allChecklistItems.addAll(it1) }
|
||||
it.reminders?.let { it1 -> allReminders.addAll(it1) }
|
||||
}
|
||||
|
|
@ -110,11 +121,6 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
taskMap.remove(taskId)
|
||||
}
|
||||
}
|
||||
for (task in taskMap.values) {
|
||||
task.position = position
|
||||
taskList.add(task)
|
||||
position++
|
||||
}
|
||||
return taskList
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import com.habitrpg.android.habitica.data.TaskRepository
|
|||
import com.habitrpg.android.habitica.extensions.withImmutableFlag
|
||||
import com.habitrpg.android.habitica.models.tasks.RemindersItem
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.android.habitica.receivers.NotificationPublisher
|
||||
import com.habitrpg.android.habitica.receivers.TaskReceiver
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.shared.habitica.HLogger
|
||||
import com.habitrpg.shared.habitica.LogLevel
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
|
|
@ -91,7 +91,7 @@ class TaskAlarmManager(
|
|||
*/
|
||||
private fun setAlarmForRemindersItem(reminderItemTask: Task, remindersItem: RemindersItem?) {
|
||||
val now = ZonedDateTime.now().withZoneSameLocal(ZoneId.systemDefault())?.toInstant()
|
||||
if (remindersItem == null || (remindersItem.getLocalZonedDateTimeInstant()?.isBefore(now) == true && reminderItemTask.nextDue?.first() != null)) {
|
||||
if (remindersItem == null || (remindersItem.getLocalZonedDateTimeInstant()?.isBefore(now) == true && reminderItemTask.nextDue?.firstOrNull() != null)) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ class TaskAlarmManager(
|
|||
intent.putExtra(TASK_NAME_INTENT_KEY, reminderItemTask.text)
|
||||
intent.putExtra(TASK_ID_INTENT_KEY, reminderItemTask.id)
|
||||
|
||||
val intentId = remindersItem.id?.hashCode() ?: 0 and 0xfffffff
|
||||
val intentId = remindersItem.id?.hashCode() ?: (0 and 0xfffffff)
|
||||
// Cancel alarm if already exists
|
||||
val previousSender = PendingIntent.getBroadcast(
|
||||
context,
|
||||
|
|
@ -130,7 +130,7 @@ class TaskAlarmManager(
|
|||
private fun removeAlarmForRemindersItem(remindersItem: RemindersItem) {
|
||||
val intent = Intent(context, TaskReceiver::class.java)
|
||||
intent.action = remindersItem.id
|
||||
val intentId = remindersItem.id?.hashCode() ?: 0 and 0xfffffff
|
||||
val intentId = remindersItem.id?.hashCode() ?: (0 and 0xfffffff)
|
||||
val sender = PendingIntent.getBroadcast(
|
||||
context,
|
||||
intentId,
|
||||
|
|
|
|||
|
|
@ -195,6 +195,10 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
val isGroupTask: Boolean
|
||||
get() = group?.groupID?.isNotBlank() == true
|
||||
|
||||
fun isAssignedToUser(userID: String): Boolean {
|
||||
return group?.assignedUsers?.contains(userID) == true
|
||||
}
|
||||
|
||||
val isPendingApproval: Boolean
|
||||
get() = (group?.approvalRequired == true && group?.approvalRequested == true && group?.approvalApproved == false)
|
||||
|
||||
|
|
|
|||
|
|
@ -40,4 +40,5 @@ open class Preferences : RealmObject(), AvatarPreferences, BaseObject {
|
|||
var pushNotifications: PushNotificationsPreference? = null
|
||||
var emailNotifications: EmailNotificationsPreference? = null
|
||||
var autoEquip: Boolean = true
|
||||
var tasks: UserTaskPreferences? = null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.habitrpg.android.habitica.models.user
|
||||
|
||||
import com.habitrpg.android.habitica.models.BaseObject
|
||||
import io.realm.RealmList
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.RealmClass
|
||||
|
||||
@RealmClass(embedded = true)
|
||||
open class UserTaskPreferences: RealmObject(), BaseObject {
|
||||
var confirmScoreNotes: Boolean = false
|
||||
var mirrorGroupTasks: RealmList<String> = RealmList()
|
||||
var groupByChallenge: Boolean = false
|
||||
}
|
||||
|
|
@ -18,9 +18,9 @@ import com.habitrpg.android.habitica.extensions.withImmutableFlag
|
|||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.TaskAlarmManager
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import io.reactivex.rxjava3.functions.BiFunction
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
|
@ -58,7 +58,7 @@ class NotificationPublisher : BroadcastReceiver() {
|
|||
}
|
||||
val checkDailies = intent.getBooleanExtra(CHECK_DAILIES, false)
|
||||
if (checkDailies) {
|
||||
taskRepository.getTasksFlowable(TaskType.DAILY).firstElement().zipWith(
|
||||
taskRepository.getTasksFlowable(TaskType.DAILY, null, emptyArray()).firstElement().zipWith(
|
||||
userRepository.getUserFlowable().firstElement(),
|
||||
BiFunction<List<Task>, User, Pair<List<Task>, User>> { tasks, user ->
|
||||
return@BiFunction Pair(tasks, user)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class ArmoireActivity : BaseActivity() {
|
|||
|
||||
userViewModel.user.observeOnce(this) { user ->
|
||||
gold = user?.stats?.gp
|
||||
val remaining = inventoryRepository.getArmoireRemainingCount() - 1
|
||||
val remaining = inventoryRepository.getArmoireRemainingCount()
|
||||
binding.equipmentCountView.text = getString(R.string.equipment_remaining, remaining)
|
||||
binding.noEquipmentView.visibility = if (remaining > 0) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ import com.habitrpg.android.habitica.components.UserComponent
|
|||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.databinding.WidgetConfigureHabitButtonBinding
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.ui.adapter.SkillTasksRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.widget.HabitButtonWidgetProvider
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
|
@ -82,7 +82,7 @@ class HabitButtonWidgetActivity : BaseActivity() {
|
|||
binding.recyclerView.adapter = adapter
|
||||
|
||||
CoroutineScope(Dispatchers.Main + job).launch {
|
||||
adapter?.data = taskRepository.getTasks(TaskType.HABIT, userId).firstOrNull() ?: listOf()
|
||||
adapter?.data = taskRepository.getTasks(TaskType.HABIT, userId, emptyArray()).firstOrNull() ?: listOf()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ import com.google.firebase.analytics.FirebaseAnalytics
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.android.habitica.extensions.setScaledPadding
|
||||
import com.habitrpg.android.habitica.helpers.SoundManager
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.habitrpg.android.habitica.ui.helpers.ToolbarColorHelper
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class BaseMainFragment<VB : ViewBinding> : BaseFragment<VB>() {
|
||||
|
|
@ -96,7 +96,7 @@ abstract class BaseMainFragment<VB : ViewBinding> : BaseFragment<VB>() {
|
|||
open fun updateToolbarInteractivity() {
|
||||
activity?.binding?.toolbarTitle?.background?.alpha = if (isTitleInteractive) 255 else 0
|
||||
if (isTitleInteractive) {
|
||||
activity?.binding?.toolbarTitle?.setScaledPadding(context, 16, 1, 16, 1)
|
||||
activity?.binding?.toolbarTitle?.setScaledPadding(context, 16, 4, 16, 4)
|
||||
} else {
|
||||
activity?.binding?.toolbarTitle?.setPadding(0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,22 +11,21 @@ import com.habitrpg.android.habitica.data.TaskRepository
|
|||
import com.habitrpg.android.habitica.databinding.FragmentRecyclerviewBinding
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.ui.adapter.SkillTasksRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class SkillTasksRecyclerViewFragment : BaseFragment<FragmentRecyclerviewBinding>() {
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
lateinit var userId: String
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
var taskType: TaskType? = null
|
||||
|
||||
override var binding: FragmentRecyclerviewBinding? = null
|
||||
|
|
@ -65,7 +64,8 @@ class SkillTasksRecyclerViewFragment : BaseFragment<FragmentRecyclerviewBinding>
|
|||
)
|
||||
binding?.recyclerView?.adapter = adapter
|
||||
|
||||
var tasks = taskRepository.getTasks(taskType ?: TaskType.HABIT)
|
||||
val additionalGroupIDs = userViewModel.mirrorGroupTasks.toTypedArray()
|
||||
var tasks = taskRepository.getTasks(taskType ?: TaskType.HABIT, userViewModel.userID, additionalGroupIDs)
|
||||
.map { it.filter { it.challengeID == null && it.group == null } }
|
||||
if (taskType == TaskType.TODO) {
|
||||
tasks = tasks.map { it.filter { !it.completed } }
|
||||
|
|
|
|||
|
|
@ -329,8 +329,9 @@ open class TaskRecyclerViewFragment : BaseFragment<FragmentRefreshRecyclerviewBi
|
|||
if (taskFlowJob?.isActive == true) {
|
||||
taskFlowJob?.cancel()
|
||||
}
|
||||
val additionalGroupIDs = viewModel.userViewModel.mirrorGroupTasks.toTypedArray()
|
||||
taskFlowJob = lifecycleScope.launch {
|
||||
taskRepository.getTasks(taskType, ownerID).collect {
|
||||
taskRepository.getTasks(taskType, ownerID, additionalGroupIDs).collect {
|
||||
recyclerAdapter?.updateUnfilteredData(it)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,17 +24,17 @@ import com.habitrpg.android.habitica.HabiticaBaseApplication
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.databinding.FragmentViewpagerBinding
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.android.habitica.extensions.setTintWith
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.TasksViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.navigation.HabiticaBottomNavigationViewListener
|
||||
import com.habitrpg.android.habitica.ui.views.tasks.TaskFilterDialog
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import java.util.Date
|
||||
import java.util.WeakHashMap
|
||||
|
||||
|
|
@ -80,9 +80,9 @@ class TasksFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchView.O
|
|||
val taskTypeValue = args.taskType
|
||||
if (args.ownerID?.isNotBlank() == true) {
|
||||
viewModel.canSwitchOwners.value = false
|
||||
viewModel.ownerID.value = args.ownerID ?: viewModel.userID
|
||||
viewModel.ownerID.value = args.ownerID ?: viewModel.userViewModel.userID
|
||||
} else {
|
||||
viewModel.ownerID.value = viewModel.userID
|
||||
viewModel.ownerID.value = viewModel.userViewModel.userID
|
||||
}
|
||||
if (taskTypeValue?.isNotBlank() == true) {
|
||||
val taskType = TaskType.from(taskTypeValue)
|
||||
|
|
|
|||
|
|
@ -7,16 +7,22 @@ import com.habitrpg.android.habitica.data.UserRepository
|
|||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.invitations.PartyInvite
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class MainUserViewModel(val userRepository: UserRepository) {
|
||||
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
lateinit var injectedUserID: String
|
||||
|
||||
val formattedUsername: CharSequence?
|
||||
get() = user.value?.formattedUsername
|
||||
val partyInvitations: List<PartyInvite>
|
||||
get() = user.value?.invitations?.parties ?: emptyList()
|
||||
val userID: String?
|
||||
get() = user.value?.id
|
||||
val userID: String
|
||||
get() = user.value?.id ?: injectedUserID
|
||||
val username: CharSequence
|
||||
get() = user.value?.username ?: ""
|
||||
val displayName: CharSequence
|
||||
|
|
@ -27,6 +33,8 @@ class MainUserViewModel(val userRepository: UserRepository) {
|
|||
get() = (user.value?.stats?.hp ?: 1.0) == 0.0
|
||||
val isUserInParty: Boolean
|
||||
get() = user.value?.hasParty == true
|
||||
val mirrorGroupTasks: List<String>
|
||||
get() = user.value?.preferences?.tasks?.mirrorGroupTasks ?: emptyList()
|
||||
|
||||
val user: LiveData<User?>
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,10 @@ import com.habitrpg.android.habitica.data.TaskRepository
|
|||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.common.habitica.models.responses.TaskDirection
|
||||
import com.habitrpg.common.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.realm.Case
|
||||
import io.realm.OrderedRealmCollection
|
||||
|
|
@ -24,7 +23,6 @@ import io.realm.Sort
|
|||
import kotlinx.coroutines.launch
|
||||
import java.util.Date
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class TasksViewModel : BaseViewModel() {
|
||||
private var compositeSubscription: CompositeDisposable = CompositeDisposable()
|
||||
|
|
@ -33,8 +31,6 @@ class TasksViewModel : BaseViewModel() {
|
|||
component.inject(this)
|
||||
}
|
||||
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
lateinit var userID: String
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
@Inject
|
||||
|
|
@ -53,7 +49,7 @@ class TasksViewModel : BaseViewModel() {
|
|||
|
||||
val isPersonalBoard: Boolean
|
||||
get() {
|
||||
return ownerID.value == userID
|
||||
return ownerID.value == userViewModel.userID
|
||||
}
|
||||
val ownerTitle: CharSequence
|
||||
get() {
|
||||
|
|
@ -65,7 +61,7 @@ class TasksViewModel : BaseViewModel() {
|
|||
viewModelScope.launch {
|
||||
userRepository.getTeamPlans()
|
||||
.collect {
|
||||
owners = listOf(Pair(userID, userViewModel.displayName)) + it.map {
|
||||
owners = listOf(Pair(userViewModel.userID, userViewModel.displayName)) + it.map {
|
||||
Pair(
|
||||
it.id,
|
||||
it.summary
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ import androidx.core.content.ContextCompat
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.common.habitica.extensions.dpToPx
|
||||
import com.habitrpg.common.habitica.extensions.isUsingNightModeResources
|
||||
import com.habitrpg.android.habitica.helpers.AmplitudeManager
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.tasks.ChecklistItem
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.common.habitica.extensions.dpToPx
|
||||
import com.habitrpg.common.habitica.extensions.isUsingNightModeResources
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import java.lang.ref.WeakReference
|
||||
|
|
@ -226,7 +226,7 @@ class YesterdailyDialog private constructor(
|
|||
}
|
||||
.firstElement()
|
||||
.zipWith(
|
||||
taskRepository.getTasksFlowable(TaskType.DAILY).firstElement()
|
||||
taskRepository.getTasksFlowable(TaskType.DAILY, null, emptyArray()).firstElement()
|
||||
.map {
|
||||
val taskMap = mutableMapOf<String, Int>()
|
||||
it.forEachIndexed { index, task -> taskMap[task.id ?: ""] = index }
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.google.gson.JsonDeserializationContext
|
|||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import com.habitrpg.android.habitica.extensions.getAsString
|
||||
|
|
@ -20,6 +21,13 @@ import io.realm.RealmList
|
|||
import java.lang.reflect.Type
|
||||
import java.util.Date
|
||||
|
||||
private val JsonPrimitive.asBooleanOrFalse: Boolean
|
||||
get() = if (isBoolean) {
|
||||
asBoolean
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
class TaskSerializer : JsonSerializer<Task>, JsonDeserializer<Task> {
|
||||
|
||||
private fun getIntListFromJsonArray(jsonArray: JsonArray): List<Int> {
|
||||
|
|
@ -116,11 +124,11 @@ class TaskSerializer : JsonSerializer<Task>, JsonDeserializer<Task> {
|
|||
if (obj.has("group")) {
|
||||
val groupObject = obj.getAsJsonObject("group")
|
||||
val group: TaskGroupPlan = context.deserialize(groupObject, TaskGroupPlan::class.java)
|
||||
if (group.groupID?.isNotBlank() == true) {
|
||||
if (group.groupID?.isNotBlank() == true && groupObject.has("approval")) {
|
||||
val approvalObject = groupObject.getAsJsonObject("approval")
|
||||
if (approvalObject.has("requested")) group.approvalRequested = approvalObject.getAsJsonPrimitive("requested").asBoolean
|
||||
if (approvalObject.has("approved")) group.approvalApproved = approvalObject.getAsJsonPrimitive("approved").asBoolean
|
||||
if (approvalObject.has("required")) group.approvalRequired = approvalObject.getAsJsonPrimitive("required").asBoolean
|
||||
if (approvalObject.has("requested")) group.approvalRequested = approvalObject.getAsJsonPrimitive("requested").asBooleanOrFalse
|
||||
if (approvalObject.has("approved")) group.approvalApproved = approvalObject.getAsJsonPrimitive("approved").asBooleanOrFalse
|
||||
if (approvalObject.has("required")) group.approvalRequired = approvalObject.getAsJsonPrimitive("required").asBooleanOrFalse
|
||||
task.group = group
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,29 +5,32 @@ import android.appwidget.AppWidgetManager
|
|||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RemoteViews
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.common.habitica.extensions.dpToPx
|
||||
import com.habitrpg.android.habitica.extensions.withImmutableFlag
|
||||
import com.habitrpg.common.habitica.helpers.HealthFormatter
|
||||
import com.habitrpg.common.habitica.helpers.NumberAbbreviator
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.common.habitica.views.AvatarView
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.common.habitica.extensions.dpToPx
|
||||
import com.habitrpg.common.habitica.helpers.HealthFormatter
|
||||
import com.habitrpg.common.habitica.helpers.NumberAbbreviator
|
||||
import com.habitrpg.common.habitica.views.AvatarView
|
||||
|
||||
class AvatarStatsWidgetProvider : BaseWidgetProvider() {
|
||||
|
||||
private lateinit var avatarView: AvatarView
|
||||
private var user: User? = null
|
||||
private var appWidgetManager: AppWidgetManager? = null
|
||||
|
||||
private var showManaBar: Boolean = true
|
||||
private var showAvatar: Boolean = true
|
||||
|
||||
|
||||
override fun layoutResourceId(): Int {
|
||||
return R.layout.widget_avatar_stats
|
||||
}
|
||||
|
|
@ -41,6 +44,10 @@ class AvatarStatsWidgetProvider : BaseWidgetProvider() {
|
|||
|
||||
override fun onEnabled(context: Context) {
|
||||
super.onEnabled(context)
|
||||
avatarView = AvatarView(context, showBackground = true, showMount = true, showPet = true)
|
||||
val layoutParams = ViewGroup.LayoutParams(140.dpToPx(context), 147.dpToPx(context))
|
||||
avatarView.layoutParams = layoutParams
|
||||
|
||||
this.setUp()
|
||||
userRepository.getUserFlowable().subscribe({
|
||||
user = it
|
||||
|
|
@ -54,6 +61,11 @@ class AvatarStatsWidgetProvider : BaseWidgetProvider() {
|
|||
appWidgetIds: IntArray
|
||||
) {
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
if (!this::avatarView.isInitialized) {
|
||||
avatarView = AvatarView(context, showBackground = true, showMount = true, showPet = true)
|
||||
val layoutParams = ViewGroup.LayoutParams(140.dpToPx(context), 147.dpToPx(context))
|
||||
avatarView.layoutParams = layoutParams
|
||||
}
|
||||
this.setUp()
|
||||
this.appWidgetManager = appWidgetManager
|
||||
this.context = context
|
||||
|
|
@ -74,7 +86,7 @@ class AvatarStatsWidgetProvider : BaseWidgetProvider() {
|
|||
columns: Int,
|
||||
rows: Int
|
||||
): RemoteViews {
|
||||
showAvatar = columns > 3
|
||||
showAvatar = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) columns > 4 else columns > 3
|
||||
if (showAvatar) {
|
||||
remoteViews.setViewVisibility(R.id.avatar_view, View.VISIBLE)
|
||||
} else {
|
||||
|
|
@ -141,10 +153,6 @@ class AvatarStatsWidgetProvider : BaseWidgetProvider() {
|
|||
remoteViews.setTextViewText(R.id.lvl_tv, context.getString(R.string.user_level, user.stats?.lvl ?: 0))
|
||||
|
||||
if (showAvatar) {
|
||||
val avatarView =
|
||||
AvatarView(context, showBackground = true, showMount = true, showPet = true)
|
||||
val layoutParams = ViewGroup.LayoutParams(140.dpToPx(context), 147.dpToPx(context))
|
||||
avatarView.layoutParams = layoutParams
|
||||
avatarView.setAvatar(user)
|
||||
val finalRemoteViews = remoteViews
|
||||
avatarView.onAvatarImageReady { bitmap ->
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ import com.habitrpg.android.habitica.R
|
|||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import com.habitrpg.common.habitica.helpers.MarkdownParser
|
||||
import com.habitrpg.common.habitica.models.tasks.TaskType
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
|
@ -46,7 +46,7 @@ abstract class TaskListFactory internal constructor(
|
|||
return
|
||||
}
|
||||
CoroutineScope(Dispatchers.Main + job).launch {
|
||||
val tasks = taskRepository.getTasks(taskType).firstOrNull()?.filter { task ->
|
||||
val tasks = taskRepository.getTasks(taskType, null, emptyArray()).firstOrNull()?.filter { task ->
|
||||
task.type == TaskType.TODO && !task.completed || task.isDisplayedActive
|
||||
} ?: return@launch
|
||||
taskList = taskRepository.getTaskCopies(tasks)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
NAME=4.0.1
|
||||
CODE=4360
|
||||
CODE=4370
|
||||
Loading…
Reference in a new issue