diff --git a/Habitica/res/drawable-hdpi/assign.png b/Habitica/res/drawable-hdpi/assign.png
new file mode 100644
index 000000000..7350842d7
Binary files /dev/null and b/Habitica/res/drawable-hdpi/assign.png differ
diff --git a/Habitica/res/drawable-mdpi/assign.png b/Habitica/res/drawable-mdpi/assign.png
new file mode 100644
index 000000000..20b6a498e
Binary files /dev/null and b/Habitica/res/drawable-mdpi/assign.png differ
diff --git a/Habitica/res/drawable-night-hdpi/assign.png b/Habitica/res/drawable-night-hdpi/assign.png
new file mode 100644
index 000000000..df03c6189
Binary files /dev/null and b/Habitica/res/drawable-night-hdpi/assign.png differ
diff --git a/Habitica/res/drawable-night-mdpi/assign.png b/Habitica/res/drawable-night-mdpi/assign.png
new file mode 100644
index 000000000..dd618cb06
Binary files /dev/null and b/Habitica/res/drawable-night-mdpi/assign.png differ
diff --git a/Habitica/res/drawable-night-xhdpi/assign.png b/Habitica/res/drawable-night-xhdpi/assign.png
new file mode 100644
index 000000000..521040778
Binary files /dev/null and b/Habitica/res/drawable-night-xhdpi/assign.png differ
diff --git a/Habitica/res/drawable-night-xxhdpi/assign.png b/Habitica/res/drawable-night-xxhdpi/assign.png
new file mode 100644
index 000000000..b336e5fbe
Binary files /dev/null and b/Habitica/res/drawable-night-xxhdpi/assign.png differ
diff --git a/Habitica/res/drawable-xhdpi/assign.png b/Habitica/res/drawable-xhdpi/assign.png
new file mode 100644
index 000000000..bb10ca5ef
Binary files /dev/null and b/Habitica/res/drawable-xhdpi/assign.png differ
diff --git a/Habitica/res/drawable-xxhdpi/assign.png b/Habitica/res/drawable-xxhdpi/assign.png
new file mode 100644
index 000000000..bf0578c8c
Binary files /dev/null and b/Habitica/res/drawable-xxhdpi/assign.png differ
diff --git a/Habitica/res/layout/reward_item_card.xml b/Habitica/res/layout/reward_item_card.xml
index af9d3a58e..ddfeb32f9 100644
--- a/Habitica/res/layout/reward_item_card.xml
+++ b/Habitica/res/layout/reward_item_card.xml
@@ -49,7 +49,7 @@
android:paddingBottom="2dp"/>
24dp
20dp
- 10dp
+ 8dp
8dp
8dp
6dp
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt
index 57bf84801..d7b66a56c 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmTaskLocalRepository.kt
@@ -45,7 +45,15 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
.beginGroup()
.equalTo("userId", ownerID)
.or()
+ .beginGroup()
.`in`("group.groupID", includedGroupIDs)
+ .and()
+ .beginGroup()
+ .contains("group.assignedUsers", ownerID)
+ .or()
+ .isEmpty("group.assignedUsers")
+ .endGroup()
+ .endGroup()
.or()
.equalTo("group.groupID", ownerID)
.endGroup()
@@ -129,14 +137,13 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
return taskList
}
- private fun removeOldTasks(userID: String, onlineTaskList: List) {
- val groupIDs = onlineTaskList.map { it.group?.groupID }.distinct().toTypedArray()
+ private fun removeOldTasks(ownerID: String, onlineTaskList: List) {
if (realm.isClosed) return
val localTasks = realm.where(Task::class.java)
.beginGroup()
- .equalTo("userId", userID)
+ .equalTo("userId", ownerID)
.or()
- .`in`("group.groupID", groupIDs)
+ .equalTo("group.groupID", ownerID)
.endGroup()
.beginGroup()
.beginGroup()
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AssignedTextProvider.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AssignedTextProvider.kt
deleted file mode 100644
index 4d97ad970..000000000
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AssignedTextProvider.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.habitrpg.android.habitica.helpers
-
-import android.content.res.Resources
-
-interface AssignedTextProvider {
- fun textForTask(resources: Resources, assignedUsers: List): String
-}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/GroupPlanInfoProvider.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/GroupPlanInfoProvider.kt
new file mode 100644
index 000000000..60d608130
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/GroupPlanInfoProvider.kt
@@ -0,0 +1,10 @@
+package com.habitrpg.android.habitica.helpers
+
+import android.content.res.Resources
+import com.habitrpg.android.habitica.models.tasks.Task
+
+interface GroupPlanInfoProvider {
+ fun assignedTextForTask(resources: Resources, assignedUsers: List): String
+ fun canScoreTask(task: Task): Boolean
+ fun canEditTask(task: Task): Boolean
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RewardsRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RewardsRecyclerViewAdapter.kt
index 7983d1261..cdd5ee55f 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RewardsRecyclerViewAdapter.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/RewardsRecyclerViewAdapter.kt
@@ -96,7 +96,7 @@ class RewardsRecyclerViewAdapter(
if (customRewards != null && position < customRewardCount) {
val reward = customRewards?.get(position) ?: return
val gold = user?.stats?.gp ?: 0.0
- (holder as? RewardViewHolder)?.isLocked = false
+ (holder as? RewardViewHolder)?.isLocked = !viewModel.canScoreTask(reward)
(holder as? RewardViewHolder)?.bind(reward, position, reward.value <= gold, taskDisplayMode, viewModel.ownerID.value)
} else if (inAppRewards != null) {
val item = inAppRewards?.get(position - customRewardCount) ?: return
@@ -122,7 +122,9 @@ class RewardsRecyclerViewAdapter(
override fun getItemCount(): Int {
var rewardCount = customRewardCount
- rewardCount += inAppRewardCount
+ if (viewModel.isPersonalBoard) {
+ rewardCount += inAppRewardCount
+ }
return rewardCount
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt
index ac7d3c293..82854c32a 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/RewardsRecyclerviewFragment.kt
@@ -16,15 +16,14 @@ import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
import com.habitrpg.android.habitica.helpers.ExceptionHandler
import com.habitrpg.android.habitica.models.shops.ShopItem
-import com.habitrpg.shared.habitica.models.tasks.TaskType
import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity
import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
+import com.habitrpg.shared.habitica.models.tasks.TaskType
import io.reactivex.rxjava3.functions.Consumer
import kotlinx.coroutines.launch
-import java.util.*
class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() {
@@ -45,7 +44,7 @@ class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() {
(layoutManager as? GridLayoutManager)?.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
- return if (recyclerAdapter?.getItemViewType(position) ?: 0 < 2) {
+ return if ((recyclerAdapter?.getItemViewType(position) ?: 0) < 2) {
(layoutManager as? GridLayoutManager)?.spanCount ?: 1
} else {
1
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt
index f4552970b..6cf2c14f1 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TaskRecyclerViewFragment.kt
@@ -214,7 +214,6 @@ open class TaskRecyclerViewFragment : BaseFragment Unit),
var openTaskFunc: ((Pair) -> Unit),
var brokenTaskFunc: ((Task) -> Unit),
- var assignedTextProvider: AssignedTextProvider?
+ var assignedTextProvider: GroupPlanInfoProvider?
) : BindableViewHolder(itemView), View.OnTouchListener {
private val scope = MainScope()
@@ -254,7 +254,7 @@ abstract class BaseTaskViewHolder constructor(
}
if (data.group?.assignedUsers?.isNotEmpty() == true) {
- assignedTextView.text = assignedTextProvider?.textForTask(context.resources, data.group?.assignedUsers ?: emptyList())
+ assignedTextView.text = assignedTextProvider?.assignedTextForTask(context.resources, data.group?.assignedUsers ?: emptyList())
assignedTextView.visibility = View.VISIBLE
} else {
assignedTextView.visibility = View.GONE
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt
index 211c293df..58b3a27ad 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.kt
@@ -12,7 +12,7 @@ import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.helpers.AssignedTextProvider
+import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider
import com.habitrpg.android.habitica.helpers.ExceptionHandler
import com.habitrpg.android.habitica.models.tasks.ChecklistItem
import com.habitrpg.android.habitica.models.tasks.Task
@@ -32,7 +32,7 @@ abstract class ChecklistedViewHolder(
var scoreChecklistItemFunc: ((Task, ChecklistItem) -> Unit),
openTaskFunc: ((Pair) -> Unit),
brokenTaskFunc: ((Task) -> Unit),
- assignedTextProvider: AssignedTextProvider?
+ assignedTextProvider: GroupPlanInfoProvider?
) : BaseTaskViewHolder(itemView, scoreTaskFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) {
private val checkboxHolder: ViewGroup = itemView.findViewById(R.id.checkBoxHolder)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt
index 26ab150a7..04a2147aa 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/DailyViewHolder.kt
@@ -1,7 +1,7 @@
package com.habitrpg.android.habitica.ui.viewHolders.tasks
import android.view.View
-import com.habitrpg.android.habitica.helpers.AssignedTextProvider
+import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider
import com.habitrpg.android.habitica.models.tasks.ChecklistItem
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.shared.habitica.models.responses.TaskDirection
@@ -15,7 +15,7 @@ class DailyViewHolder(
scoreChecklistItemFunc: ((Task, ChecklistItem) -> Unit),
openTaskFunc: ((Pair) -> Unit),
brokenTaskFunc: ((Task) -> Unit),
- assignedTextProvider: AssignedTextProvider?
+ assignedTextProvider: GroupPlanInfoProvider?
) : ChecklistedViewHolder(itemView, scoreTaskFunc, scoreChecklistItemFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) {
override val taskIconWrapperIsVisible: Boolean
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt
index e31f0337d..b56939f23 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.kt
@@ -6,9 +6,8 @@ import android.widget.Button
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.core.content.ContextCompat
-import androidx.lifecycle.MutableLiveData
import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.helpers.AssignedTextProvider
+import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.shared.habitica.models.responses.TaskDirection
@@ -17,7 +16,7 @@ class HabitViewHolder(
scoreTaskFunc: ((Task, TaskDirection) -> Unit),
openTaskFunc: ((Pair) -> Unit),
brokenTaskFunc: ((Task) -> Unit),
- assignedTextProvider: AssignedTextProvider?
+ assignedTextProvider: GroupPlanInfoProvider?
) : BaseTaskViewHolder(itemView, scoreTaskFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) {
private val btnPlusWrapper: FrameLayout = itemView.findViewById(R.id.btnPlusWrapper)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt
index 06f778ecb..c083240b7 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.kt
@@ -4,12 +4,14 @@ import android.view.MotionEvent
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
+import androidx.core.graphics.drawable.toDrawable
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.RewardItemCardBinding
-import com.habitrpg.android.habitica.helpers.AssignedTextProvider
+import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.ItemDetailDialog
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
+import com.habitrpg.common.habitica.extensions.dpToPx
import com.habitrpg.common.habitica.helpers.NumberAbbreviator
import com.habitrpg.shared.habitica.models.responses.TaskDirection
@@ -18,8 +20,14 @@ class RewardViewHolder(
scoreTaskFunc: ((Task, TaskDirection) -> Unit),
openTaskFunc: ((Pair) -> Unit),
brokenTaskFunc: ((Task) -> Unit),
- assignedTextProvider: AssignedTextProvider?
-) : BaseTaskViewHolder(itemView, scoreTaskFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) {
+ assignedTextProvider: GroupPlanInfoProvider?
+) : BaseTaskViewHolder(
+ itemView,
+ scoreTaskFunc,
+ openTaskFunc,
+ brokenTaskFunc,
+ assignedTextProvider
+) {
private val binding = RewardItemCardBinding.bind(itemView)
private val isItem: Boolean
@@ -29,6 +37,7 @@ class RewardViewHolder(
binding.buyButton.setOnClickListener {
buyReward()
}
+ binding.goldIcon.setImageBitmap(HabiticaIconsHelper.imageOfGold())
}
override fun canContainMarkdown(): Boolean {
@@ -67,25 +76,44 @@ class RewardViewHolder(
this.task = reward
streakTextView.visibility = View.GONE
super.bind(reward, position, displayMode, ownerID)
- binding.priceLabel.text = NumberAbbreviator.abbreviate(itemView.context, this.task?.value ?: 0.0)
+ binding.priceLabel.text =
+ NumberAbbreviator.abbreviate(itemView.context, this.task?.value ?: 0.0)
if (isLocked) {
- binding.goldIcon.setImageResource(R.drawable.task_lock)
- binding.goldIcon.drawable.setTint(ContextCompat.getColor(context, R.color.reward_buy_button_text))
- binding.goldIcon.alpha = 1.0f
- binding.priceLabel.setTextColor(ContextCompat.getColor(context, R.color.reward_buy_button_text))
- binding.buyButton.setBackgroundColor(ContextCompat.getColor(context, R.color.reward_buy_button_bg))
+ binding.priceLabel.setCompoundDrawablesWithIntrinsicBounds(
+ HabiticaIconsHelper.imageOfLocked(
+ ContextCompat.getColor(context, R.color.gray_1_30), 10, 12
+ ).toDrawable(context.resources), null, null, null
+ )
+ binding.priceLabel.compoundDrawablePadding = 2.dpToPx(context)
} else {
- binding.goldIcon.setImageBitmap(HabiticaIconsHelper.imageOfGold())
- if (canBuy) {
- binding.goldIcon.alpha = 1.0f
- binding.priceLabel.setTextColor(ContextCompat.getColor(context, R.color.reward_buy_button_text))
- binding.buyButton.setBackgroundColor(ContextCompat.getColor(context, R.color.reward_buy_button_bg))
- } else {
- binding.goldIcon.alpha = 0.6f
- binding.priceLabel.setTextColor(ContextCompat.getColor(context, R.color.text_quad))
- binding.buyButton.setBackgroundColor(ColorUtils.setAlphaComponent(ContextCompat.getColor(context, R.color.offset_background), 127))
- }
+ binding.priceLabel.setCompoundDrawables(null, null, null, null)
+ }
+ if (canBuy && !isLocked) {
+ binding.goldIcon.alpha = 1.0f
+ binding.priceLabel.setTextColor(
+ ContextCompat.getColor(
+ context,
+ R.color.reward_buy_button_text
+ )
+ )
+ binding.buyButton.setBackgroundColor(
+ ContextCompat.getColor(
+ context,
+ R.color.reward_buy_button_bg
+ )
+ )
+ } else {
+ binding.goldIcon.alpha = 0.6f
+ binding.priceLabel.setTextColor(ContextCompat.getColor(context, R.color.text_quad))
+ binding.buyButton.setBackgroundColor(
+ ColorUtils.setAlphaComponent(
+ ContextCompat.getColor(
+ context,
+ R.color.offset_background
+ ), 127
+ )
+ )
}
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt
index b7bf10b2a..2370a4ad4 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/TodoViewHolder.kt
@@ -1,7 +1,7 @@
package com.habitrpg.android.habitica.ui.viewHolders.tasks
import android.view.View
-import com.habitrpg.android.habitica.helpers.AssignedTextProvider
+import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider
import com.habitrpg.android.habitica.models.tasks.ChecklistItem
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.shared.habitica.models.responses.TaskDirection
@@ -13,7 +13,7 @@ class TodoViewHolder(
scoreChecklistItemFunc: ((Task, ChecklistItem) -> Unit),
openTaskFunc: ((Pair) -> Unit),
brokenTaskFunc: ((Task) -> Unit),
- assignedTextProvider: AssignedTextProvider?
+ assignedTextProvider: GroupPlanInfoProvider?
) : ChecklistedViewHolder(itemView, scoreTaskFunc, scoreChecklistItemFunc, openTaskFunc, brokenTaskFunc, assignedTextProvider) {
private val dateFormatter: DateFormat = android.text.format.DateFormat.getDateFormat(context)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainUserViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainUserViewModel.kt
index dcf766b42..c86726f30 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainUserViewModel.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainUserViewModel.kt
@@ -7,6 +7,7 @@ import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.helpers.ExceptionHandler
import com.habitrpg.android.habitica.models.TeamPlan
import com.habitrpg.android.habitica.models.invitations.PartyInvite
+import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.models.user.User
import io.reactivex.rxjava3.disposables.CompositeDisposable
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -43,10 +44,12 @@ class MainUserViewModel(private val providedUserID: String, val userRepository:
.filterNotNull()
.distinctUntilChanged { old, new -> old.id == new.id }
.flatMapLatest { socialRepository.getGroup(it.id) }
- var currentTeamPlanMembers = currentTeamPlan
+ @OptIn(ExperimentalCoroutinesApi::class)
+ var currentTeamPlanMembers: LiveData> = currentTeamPlan
.filterNotNull()
.distinctUntilChanged { old, new -> old.id == new.id }
.flatMapLatest { socialRepository.getGroupMembers(it.id) }
+ .asLiveData()
fun onCleared() {
userRepository.close()
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt
index fd8850c0c..85a5af08b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt
@@ -12,8 +12,8 @@ import com.habitrpg.android.habitica.data.TagRepository
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.AssignedTextProvider
import com.habitrpg.android.habitica.helpers.ExceptionHandler
+import com.habitrpg.android.habitica.helpers.GroupPlanInfoProvider
import com.habitrpg.android.habitica.models.TeamPlan
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.shared.habitica.models.responses.TaskDirection
@@ -28,7 +28,7 @@ import kotlinx.coroutines.launch
import java.util.Date
import javax.inject.Inject
-class TasksViewModel : BaseViewModel(), AssignedTextProvider {
+class TasksViewModel : BaseViewModel(), GroupPlanInfoProvider {
private var compositeSubscription: CompositeDisposable = CompositeDisposable()
override fun inject(component: UserComponent) {
@@ -305,14 +305,21 @@ class TasksViewModel : BaseViewModel(), AssignedTextProvider {
return query
}
- fun canScoreTask(item: Task): Boolean {
- if (!item.isGroupTask) {
+ override fun canScoreTask(task: Task): Boolean {
+ if (!task.isGroupTask) {
return true
}
- return item.isAssignedToUser(userViewModel.userID) || item.group?.assignedUsers?.isEmpty() != false
+ return task.isAssignedToUser(userViewModel.userID) || task.group?.assignedUsers?.isEmpty() != false
}
- override fun textForTask(resources: Resources, assignedUsers: List): String {
+ override fun canEditTask(task: Task): Boolean {
+ if (!task.isGroupTask) {
+ return true
+ }
+ return false
+ }
+
+ override fun assignedTextForTask(resources: Resources, assignedUsers: List): String {
return if (assignedUsers.contains(userViewModel.userID)) {
if (assignedUsers.size == 1) {
resources.getString(R.string.you)
@@ -320,7 +327,11 @@ class TasksViewModel : BaseViewModel(), AssignedTextProvider {
resources.getQuantityString(R.plurals.you_x_others, assignedUsers.size - 1, assignedUsers.size - 1)
}
} else {
- resources.getQuantityString(R.plurals.people, assignedUsers.size, assignedUsers.size)
+ if (assignedUsers.size == 1) {
+ userViewModel.currentTeamPlanMembers.value?.firstOrNull { it.id == assignedUsers.first() }?.displayName ?: ""
+ } else {
+ resources.getQuantityString(R.plurals.people, assignedUsers.size, assignedUsers.size)
+ }
}
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt
index efcd3b6aa..6d7a86ca8 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt
@@ -112,7 +112,7 @@ fun AppHeaderView(
) {
val user by viewModel.user.observeAsState(null)
val teamPlan by viewModel.currentTeamPlan.collectAsState(null)
- val teamPlanMembers by viewModel.currentTeamPlanMembers.collectAsState(null)
+ val teamPlanMembers by viewModel.currentTeamPlanMembers.observeAsState()
Column {
Row {
ComposableAvatarView(
@@ -207,7 +207,10 @@ fun AppHeaderView(
}
) {
for (member in teamPlanMembers?.filter { it.id != user?.id }?.take(6) ?: emptyList()) {
- Box(modifier = Modifier.clip(CircleShape).size(26.dp).padding(end = 6.dp, top = 4.dp)) {
+ Box(modifier = Modifier
+ .clip(CircleShape)
+ .size(26.dp)
+ .padding(end = 6.dp, top = 4.dp)) {
ComposableAvatarView(
avatar = member,
Modifier
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/HabiticaBottomNavigationView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/HabiticaBottomNavigationView.kt
index d7e94af1f..03e3d67fd 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/HabiticaBottomNavigationView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/HabiticaBottomNavigationView.kt
@@ -5,7 +5,6 @@ import android.content.Context
import android.graphics.PorterDuff
import android.util.AttributeSet
import android.view.MotionEvent
-import android.view.View
import android.view.animation.Animation
import android.view.animation.BounceInterpolator
import android.view.animation.LinearInterpolator
@@ -68,28 +67,11 @@ class HabiticaBottomNavigationView @JvmOverloads constructor(
field = value
val animator = ObjectAnimator.ofFloat(0f, 1.0f)
if (field) {
- val params = binding.cutoutFill.layoutParams
- // add some additional height because otherwise there is a weird white line
- params.height = binding.cutoutBackground.height + 10
- binding.cutoutFill.layoutParams = params
- animator.addUpdateListener {
- val reversed = 1.0f - it.animatedFraction
- binding.cutoutFill.translationY = -(reversed) * binding.cutoutBackground.height
- }
- binding.cutoutSpace.visibility = View.VISIBLE
binding.addButtonBackground.animate()
.translationY(0f)
.alpha(1f)
.setDuration(200)
} else {
- val params = binding.cutoutFill.layoutParams
- // add some additional height because otherwise there is a weird white line
- params.height = binding.cutoutBackground.height + 10
- binding.cutoutFill.layoutParams = params
- animator.addUpdateListener {
- binding.cutoutFill.translationY = -it.animatedFraction * (binding.cutoutBackground.height)
- }
- binding.cutoutSpace.visibility = View.INVISIBLE
binding.addButtonBackground.animate()
.translationY(-binding.addButtonBackground.height.toFloat() / 2)
.alpha(0.0f)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/StatsView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/StatsView.kt
index 8a3455f0d..d6624df74 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/StatsView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/stats/StatsView.kt
@@ -5,13 +5,126 @@ import android.graphics.PorterDuff
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.Text
+import androidx.compose.material.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.StatsViewBinding
-import com.habitrpg.common.habitica.extensions.layoutInflater
import com.habitrpg.android.habitica.extensions.setTintWith
import com.habitrpg.android.habitica.helpers.HapticFeedbackManager
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
+import com.habitrpg.common.habitica.extensions.layoutInflater
+
+@Composable
+fun StatsViewComposable(
+ statText: String,
+ statColor: Color,
+ levelValue: Int,
+ equipmentValue: Int,
+ buffValue: Int,
+ allocatedValue: Int,
+ canAllocate: Boolean,
+ allocateAction: () -> Unit
+) {
+ Column(
+ Modifier
+ .background(colorResource(R.color.window_background))
+ .clip(RoundedCornerShape(12.dp))) {
+ Row(
+ Modifier
+ .height(43.dp)
+ .fillMaxWidth()
+ .background(statColor)
+ .padding(horizontal = 12.dp),
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically) {
+ Text(statText, color = colorResource(R.color.white))
+ Text("${levelValue + equipmentValue + buffValue + allocatedValue}", color = colorResource(R.color.white))
+ }
+ Row(Modifier.height(61.dp),
+ horizontalArrangement = Arrangement.SpaceEvenly,
+ verticalAlignment = Alignment.CenterVertically ) {
+ Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.Center, Alignment.CenterHorizontally) {
+ Text(text = "$levelValue", fontSize = 20.sp)
+ Text(text = stringResource(R.string.level), color = colorResource(R.color.text_quad), fontSize = 12.sp)
+ }
+ Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.Center, Alignment.CenterHorizontally) {
+ Text(text = "$equipmentValue", fontSize = 20.sp)
+ Text(text = stringResource(R.string.sidebar_equipment), color = colorResource(R.color.text_quad), fontSize = 12.sp)
+ }
+ Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.Center, Alignment.CenterHorizontally) {
+ Text(text = "$buffValue", fontSize = 20.sp)
+ Text(text = stringResource(R.string.buffs), color = colorResource(R.color.text_quad), fontSize = 12.sp)
+ }
+ Column(modifier = Modifier
+ .weight(1f)
+ .fillMaxHeight()
+ .background(colorResource(if (canAllocate) R.color.offset_background_30 else R.color.window_background)), verticalArrangement = Arrangement.Center, Alignment.CenterHorizontally) {
+ Text(text = "$allocatedValue", fontSize = 20.sp, color = if (canAllocate) statColor else colorResource(R.color.text_primary))
+ Text(text = stringResource(R.string.allocated), color = if (canAllocate) statColor else colorResource(R.color.text_quad), fontSize = 12.sp)
+ }
+ AnimatedVisibility(visible = canAllocate) {
+ TextButton(onClick = allocateAction,
+ Modifier
+ .width(48.dp)
+ .fillMaxHeight()
+ .background(
+ colorResource(id = R.color.offset_background_30)
+ )) {
+ Image(HabiticaIconsHelper.imageOfAttributeAllocateButton().asImageBitmap(), null)
+ }
+ }
+ }
+ }
+}
+
+@Preview
+@Composable
+fun StatsViewPreview() {
+ Column(Modifier.background(colorResource(id = R.color.content_background))) {
+ StatsViewComposable(
+ statText = "Strength",
+ statColor = colorResource(id = R.color.red_50),
+ levelValue = 10,
+ equipmentValue = 5,
+ buffValue = 4,
+ allocatedValue = 8,
+ canAllocate = false
+ ) {}
+ StatsViewComposable(
+ statText = "Intelligence",
+ statColor = colorResource(id = R.color.blue_50),
+ levelValue = 10,
+ equipmentValue = 5,
+ buffValue = 4,
+ allocatedValue = 8,
+ canAllocate = true
+ ) {}
+ }
+}
class StatsView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
private val binding = StatsViewBinding.inflate(context.layoutInflater, this, true)
diff --git a/common/src/main/res/values/colors.xml b/common/src/main/res/values/colors.xml
index 994f82a89..1488f6ea8 100644
--- a/common/src/main/res/values/colors.xml
+++ b/common/src/main/res/values/colors.xml
@@ -73,6 +73,8 @@
#edecee
#f9f9f9
+ #4D1A181D
+
#033f5e
#005158
#005737
diff --git a/version.properties b/version.properties
index ce8608982..be277252e 100644
--- a/version.properties
+++ b/version.properties
@@ -1,2 +1,2 @@
NAME=4.0.3
-CODE=4571
\ No newline at end of file
+CODE=4581
\ No newline at end of file