diff --git a/Habitica/res/drawable-hdpi/baseline_error_outline_black_36dp.png b/Habitica/res/drawable-hdpi/baseline_error_outline_black_36dp.png
deleted file mode 100644
index ec4860d02..000000000
Binary files a/Habitica/res/drawable-hdpi/baseline_error_outline_black_36dp.png and /dev/null differ
diff --git a/Habitica/res/drawable-mdpi/baseline_error_outline_black_36dp.png b/Habitica/res/drawable-mdpi/baseline_error_outline_black_36dp.png
deleted file mode 100644
index 8994911fa..000000000
Binary files a/Habitica/res/drawable-mdpi/baseline_error_outline_black_36dp.png and /dev/null differ
diff --git a/Habitica/res/drawable-xhdpi/baseline_error_outline_black_36dp.png b/Habitica/res/drawable-xhdpi/baseline_error_outline_black_36dp.png
deleted file mode 100644
index 356880514..000000000
Binary files a/Habitica/res/drawable-xhdpi/baseline_error_outline_black_36dp.png and /dev/null differ
diff --git a/Habitica/res/drawable-xxhdpi/baseline_error_outline_black_36dp.png b/Habitica/res/drawable-xxhdpi/baseline_error_outline_black_36dp.png
deleted file mode 100644
index a65cafc82..000000000
Binary files a/Habitica/res/drawable-xxhdpi/baseline_error_outline_black_36dp.png and /dev/null differ
diff --git a/Habitica/res/drawable-xxxhdpi/baseline_error_outline_black_36dp.png b/Habitica/res/drawable-xxxhdpi/baseline_error_outline_black_36dp.png
deleted file mode 100644
index 0a0d146a4..000000000
Binary files a/Habitica/res/drawable-xxxhdpi/baseline_error_outline_black_36dp.png and /dev/null differ
diff --git a/Habitica/res/values/dimens.xml b/Habitica/res/values/dimens.xml
index 9b3247235..ad847cc41 100644
--- a/Habitica/res/values/dimens.xml
+++ b/Habitica/res/values/dimens.xml
@@ -4,8 +4,7 @@
16dp
8dp
- 18.0sp
- 14.0sp
+
12dp
6dp
6dp
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index aec444b80..8314dbe93 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -270,7 +270,6 @@
• Bosses won’t do damage for your missed Dailies\n
• Your boss damage or collection quest items will stay pending until check-out
You don\'t have any %s
- Lvl %d
Lvl %1$d %2$s
Level %1$d %2$s
Warrior
@@ -1138,9 +1137,7 @@
You must purchase the previous items in this sequence to unlock
You caused damage to the boss
Style
- Failed to load
Daily Checkbox
- Retry
Nothing here yet
You don\'t have any equipment of this type yet. You can purchase equipment from the market using the gold you earned.
Todo Checkbox
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
index 3bdd27755..a715cabf1 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
@@ -31,7 +31,7 @@ import com.habitrpg.android.habitica.models.user.Outfit
import com.habitrpg.android.habitica.models.user.Stats
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel
import com.habitrpg.android.habitica.ui.adapter.social.AchievementProfileAdapter
-import com.habitrpg.android.habitica.ui.helpers.RecyclerViewState
+import com.habitrpg.common.habitica.helpers.RecyclerViewState
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentDetailFragment.kt
index 597073473..68275bca6 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentDetailFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentDetailFragment.kt
@@ -15,7 +15,7 @@ import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.ui.adapter.inventory.EquipmentRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
-import com.habitrpg.android.habitica.ui.helpers.EmptyItem
+import com.habitrpg.common.habitica.helpers.EmptyItem
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import javax.inject.Inject
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemDialogFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemDialogFragment.kt
index 24bfc8ab3..985f5f2bc 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemDialogFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemDialogFragment.kt
@@ -31,7 +31,7 @@ import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.adapter.inventory.ItemRecyclerAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseDialogFragment
-import com.habitrpg.android.habitica.ui.helpers.EmptyItem
+import com.habitrpg.common.habitica.helpers.EmptyItem
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.common.habitica.extensions.loadImage
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.kt
index 5e7186238..47c5353d1 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.kt
@@ -37,7 +37,7 @@ import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity
import com.habitrpg.android.habitica.ui.adapter.inventory.ItemRecyclerAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
-import com.habitrpg.android.habitica.ui.helpers.EmptyItem
+import com.habitrpg.common.habitica.helpers.EmptyItem
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.common.habitica.extensions.loadImage
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt
index e1d66a087..1741c70dd 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/shops/ShopFragment.kt
@@ -21,7 +21,7 @@ import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.ui.adapter.inventory.ShopRecyclerAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
-import com.habitrpg.android.habitica.ui.helpers.RecyclerViewState
+import com.habitrpg.common.habitica.helpers.RecyclerViewState
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.CurrencyViews
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt
index c3a1a63d8..5433ec79a 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt
@@ -19,7 +19,7 @@ import com.habitrpg.android.habitica.models.inventory.Egg
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
import com.habitrpg.android.habitica.ui.adapter.inventory.StableRecyclerAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
-import com.habitrpg.android.habitica.ui.helpers.EmptyItem
+import com.habitrpg.common.habitica.helpers.EmptyItem
import com.habitrpg.android.habitica.ui.helpers.MarginDecoration
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.kt
index caa1844ca..a85a6e613 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.kt
@@ -18,7 +18,7 @@ import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.ui.adapter.social.ChallengesListViewAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
-import com.habitrpg.android.habitica.ui.helpers.EmptyItem
+import com.habitrpg.common.habitica.helpers.EmptyItem
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.kotlin.Flowables
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/guilds/GuildListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/guilds/GuildListFragment.kt
index 774ece179..7b090ab0a 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/guilds/GuildListFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/guilds/GuildListFragment.kt
@@ -13,7 +13,7 @@ import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBind
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.ui.adapter.social.GuildListAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
-import com.habitrpg.android.habitica.ui.helpers.EmptyItem
+import com.habitrpg.common.habitica.helpers.EmptyItem
import com.habitrpg.android.habitica.ui.helpers.KeyboardUtil
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import javax.inject.Inject
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 4626b579b..80033e1a9 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
@@ -38,7 +38,7 @@ import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.adapter.tasks.TaskRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.adapter.tasks.TodosRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
-import com.habitrpg.android.habitica.ui.helpers.EmptyItem
+import com.habitrpg.common.habitica.helpers.EmptyItem
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.viewHolders.tasks.BaseTaskViewHolder
import com.habitrpg.android.habitica.ui.viewmodels.TasksViewModel
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/RecyclerViewEmptySupport.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/RecyclerViewEmptySupport.kt
index e2ad593c6..9d95f282b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/RecyclerViewEmptySupport.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/RecyclerViewEmptySupport.kt
@@ -2,34 +2,18 @@ package com.habitrpg.android.habitica.ui.helpers
import android.content.Context
import android.util.AttributeSet
-import android.view.View
-import android.view.ViewGroup
-import android.view.animation.AlphaAnimation
-import android.widget.ProgressBar
-import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
-import com.habitrpg.android.habitica.R
-import com.habitrpg.android.habitica.databinding.EmptyItemBinding
-import com.habitrpg.android.habitica.databinding.FailedItemBinding
-import com.habitrpg.android.habitica.extensions.inflate
+import com.habitrpg.common.habitica.helpers.EmptyItem
+import com.habitrpg.common.habitica.helpers.RecyclerViewState
+import com.habitrpg.common.habitica.helpers.RecyclerViewStateAdapter
-data class EmptyItem(
- var title: String,
- var text: String? = null,
- var iconResource: Int? = null,
- var buttonLabel: String? = null,
- var onButtonTap: (() -> Unit)? = null
-)
+class RecyclerViewEmptySupport @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null
+) : RecyclerView(context, attrs) {
+ var onRefresh: (() -> Unit)?
+ get() = emptyAdapter.onRefresh
+ set(value) { emptyAdapter.onRefresh = value }
-enum class RecyclerViewState {
- LOADING,
- EMPTY,
- DISPLAYING_DATA,
- FAILED
-}
-
-class RecyclerViewEmptySupport : RecyclerView {
- var onRefresh: (() -> Unit)? = null
var state: RecyclerViewState = RecyclerViewState.LOADING
set(value) {
field = value
@@ -37,7 +21,7 @@ class RecyclerViewEmptySupport : RecyclerView {
RecyclerViewState.DISPLAYING_DATA -> updateAdapter(actualAdapter)
else -> {
updateAdapter(emptyAdapter)
- emptyAdapter.notifyDataSetChanged()
+ emptyAdapter.state = value
}
}
}
@@ -48,53 +32,16 @@ class RecyclerViewEmptySupport : RecyclerView {
}
}
- var emptyItem: EmptyItem? = null
+ var emptyItem: EmptyItem?
+ get() = emptyAdapter.emptyItem
set(value) {
- field = value
- emptyAdapter.notifyDataSetChanged()
+ emptyAdapter.emptyItem = value
}
private var actualAdapter: Adapter<*>? = null
- private val emptyAdapter: Adapter = object : Adapter() {
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- return when (viewType) {
- 0 -> {
- val view = parent.inflate(R.layout.loading_item)
- val animation1 = AlphaAnimation(0.0f, 1.0f)
- animation1.duration = 300
- animation1.startOffset = 500
- animation1.fillAfter = true
- view.findViewById(R.id.loading_indicator).startAnimation(animation1)
- object : ViewHolder(view) {}
- }
- 1 -> FailedViewHolder(parent.inflate(R.layout.failed_item))
- else -> EmptyViewHolder(parent.inflate(R.layout.empty_item))
- }
- }
+ private val emptyAdapter = RecyclerViewStateAdapter()
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- if (holder is EmptyViewHolder) {
- holder.bind(emptyItem)
- } else if (holder is FailedViewHolder) {
- holder.bind(onRefresh)
- }
- (holder as? EmptyViewHolder)?.bind(emptyItem)
- }
-
- override fun getItemCount(): Int {
- return 1
- }
-
- override fun getItemViewType(position: Int): Int {
- return when (state) {
- RecyclerViewState.LOADING -> 0
- RecyclerViewState.FAILED -> 1
- else -> 2
- }
- }
- }
-
- private val observer = object : RecyclerView.AdapterDataObserver() {
+ private val observer = object : AdapterDataObserver() {
override fun onChanged() {
updateState()
}
@@ -108,22 +55,16 @@ class RecyclerViewEmptySupport : RecyclerView {
}
}
- constructor(context: Context) : super(context)
-
- constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
-
- constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
-
internal fun updateState(isInitial: Boolean = false) {
- if (actualAdapter != null && !isInitial) {
+ state = if (actualAdapter != null && !isInitial) {
val emptyViewVisible = actualAdapter?.itemCount == 0
if (emptyViewVisible) {
- state = RecyclerViewState.EMPTY
+ RecyclerViewState.EMPTY
} else {
- state = RecyclerViewState.DISPLAYING_DATA
+ RecyclerViewState.DISPLAYING_DATA
}
} else {
- state = RecyclerViewState.LOADING
+ RecyclerViewState.LOADING
}
}
@@ -135,38 +76,4 @@ class RecyclerViewEmptySupport : RecyclerView {
actualAdapter = adapter
updateState(true)
}
-}
-
-class FailedViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
- private val binding = FailedItemBinding.bind(itemView)
-
- fun bind(onRefresh: (() -> Unit)?) {
- if (onRefresh != null) {
- binding.refreshButton.visibility = View.VISIBLE
- binding.refreshButton.setOnClickListener { onRefresh() }
- } else {
- binding.refreshButton.visibility = View.GONE
- }
- }
-}
-
-class EmptyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
-
- private val binding = EmptyItemBinding.bind(itemView)
-
- fun bind(emptyItem: EmptyItem?) {
- binding.emptyIconView.setColorFilter(ContextCompat.getColor(itemView.context, R.color.text_dimmed), android.graphics.PorterDuff.Mode.MULTIPLY)
- emptyItem?.iconResource?.let { binding.emptyIconView.setImageResource(it) }
- binding.emptyViewTitle.text = emptyItem?.title
- binding.emptyViewDescription.text = emptyItem?.text
-
- val buttonLabel = emptyItem?.buttonLabel
- if (buttonLabel != null) {
- binding.button.visibility = View.VISIBLE
- binding.button.text = buttonLabel
- binding.button.setOnClickListener { emptyItem.onButtonTap?.invoke() }
- } else {
- binding.button.visibility = View.GONE
- }
- }
-}
+}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/ViewGroup-Extensions.kt b/common/src/main/java/com/habitrpg/common/habitica/extensions/ViewGroup-Extensions.kt
similarity index 100%
rename from Habitica/src/main/java/com/habitrpg/android/habitica/extensions/ViewGroup-Extensions.kt
rename to common/src/main/java/com/habitrpg/common/habitica/extensions/ViewGroup-Extensions.kt
diff --git a/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt b/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt
new file mode 100644
index 000000000..e88db2736
--- /dev/null
+++ b/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt
@@ -0,0 +1,118 @@
+package com.habitrpg.common.habitica.helpers
+
+import android.view.View
+import android.view.ViewGroup
+import android.view.animation.AlphaAnimation
+import android.widget.ProgressBar
+import androidx.core.content.ContextCompat
+import androidx.recyclerview.widget.RecyclerView
+import com.habitrpg.android.habitica.extensions.inflate
+import com.habitrpg.common.habitica.R
+import com.habitrpg.common.habitica.databinding.EmptyItemBinding
+import com.habitrpg.common.habitica.databinding.FailedItemBinding
+
+data class EmptyItem(
+ var title: String,
+ var text: String? = null,
+ var iconResource: Int? = null,
+ var buttonLabel: String? = null,
+ var onButtonTap: (() -> Unit)? = null
+)
+
+enum class RecyclerViewState {
+ LOADING,
+ EMPTY,
+ DISPLAYING_DATA,
+ FAILED
+}
+
+class FailedViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ private val binding = FailedItemBinding.bind(itemView)
+
+ fun bind(onRefresh: (() -> Unit)?) {
+ if (onRefresh != null) {
+ binding.refreshButton.visibility = View.VISIBLE
+ binding.refreshButton.setOnClickListener { onRefresh() }
+ } else {
+ binding.refreshButton.visibility = View.GONE
+ }
+ }
+}
+
+class EmptyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+
+ private val binding = EmptyItemBinding.bind(itemView)
+
+ fun bind(emptyItem: EmptyItem?) {
+ binding.emptyIconView.setColorFilter(
+ ContextCompat.getColor(
+ itemView.context,
+ R.color.text_dimmed
+ ), android.graphics.PorterDuff.Mode.MULTIPLY)
+ emptyItem?.iconResource?.let { binding.emptyIconView.setImageResource(it) }
+ binding.emptyViewTitle.text = emptyItem?.title
+ binding.emptyViewDescription.text = emptyItem?.text
+
+ val buttonLabel = emptyItem?.buttonLabel
+ if (buttonLabel != null) {
+ binding.button.visibility = View.VISIBLE
+ binding.button.text = buttonLabel
+ binding.button.setOnClickListener { emptyItem.onButtonTap?.invoke() }
+ } else {
+ binding.button.visibility = View.GONE
+ }
+ }
+}
+
+class RecyclerViewStateAdapter(val showLoadingAsEmpty: Boolean = false) : RecyclerView.Adapter() {
+ var onRefresh: (() -> Unit)? = null
+ var emptyItem: EmptyItem? = null
+ set(value) {
+ field = value
+ notifyItemChanged(0)
+ }
+
+ var state: RecyclerViewState = RecyclerViewState.LOADING
+ set(value) {
+ field = value
+ notifyItemChanged(0)
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ return when (viewType) {
+ 0 -> {
+ val view = parent.inflate(R.layout.loading_item)
+ val animation1 = AlphaAnimation(0.0f, 1.0f)
+ animation1.duration = 300
+ animation1.startOffset = 500
+ animation1.fillAfter = true
+ view.findViewById(R.id.loading_indicator).startAnimation(animation1)
+ object : RecyclerView.ViewHolder(view) {}
+ }
+ 1 -> FailedViewHolder(parent.inflate(R.layout.failed_item))
+ else -> EmptyViewHolder(parent.inflate(R.layout.empty_item))
+ }
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ if (holder is EmptyViewHolder) {
+ holder.bind(emptyItem)
+ } else if (holder is FailedViewHolder) {
+ holder.bind(onRefresh)
+ }
+ (holder as? EmptyViewHolder)?.bind(emptyItem)
+ }
+
+ override fun getItemCount(): Int {
+ return 1
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return when {
+ state == RecyclerViewState.LOADING && !showLoadingAsEmpty -> 0
+ state == RecyclerViewState.FAILED -> 1
+ else -> 2
+ }
+ }
+}
+
diff --git a/common/src/main/res/drawable-anydpi/failed_loading.xml b/common/src/main/res/drawable-anydpi/failed_loading.xml
new file mode 100644
index 000000000..a2abd198b
--- /dev/null
+++ b/common/src/main/res/drawable-anydpi/failed_loading.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/common/src/main/res/drawable-hdpi/failed_loading.png b/common/src/main/res/drawable-hdpi/failed_loading.png
new file mode 100644
index 000000000..92a4bc43b
Binary files /dev/null and b/common/src/main/res/drawable-hdpi/failed_loading.png differ
diff --git a/common/src/main/res/drawable-mdpi/failed_loading.png b/common/src/main/res/drawable-mdpi/failed_loading.png
new file mode 100644
index 000000000..1e3f3a3ec
Binary files /dev/null and b/common/src/main/res/drawable-mdpi/failed_loading.png differ
diff --git a/common/src/main/res/drawable-xhdpi/failed_loading.png b/common/src/main/res/drawable-xhdpi/failed_loading.png
new file mode 100644
index 000000000..29dbf8210
Binary files /dev/null and b/common/src/main/res/drawable-xhdpi/failed_loading.png differ
diff --git a/common/src/main/res/drawable-xxhdpi/failed_loading.png b/common/src/main/res/drawable-xxhdpi/failed_loading.png
new file mode 100644
index 000000000..9710e0ab7
Binary files /dev/null and b/common/src/main/res/drawable-xxhdpi/failed_loading.png differ
diff --git a/Habitica/res/layout/empty_item.xml b/common/src/main/res/layout/empty_item.xml
similarity index 95%
rename from Habitica/res/layout/empty_item.xml
rename to common/src/main/res/layout/empty_item.xml
index e439f0418..b3d38777a 100644
--- a/Habitica/res/layout/empty_item.xml
+++ b/common/src/main/res/layout/empty_item.xml
@@ -26,10 +26,10 @@
@@ -37,7 +37,6 @@
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="@style/HabiticaButton.Primary"
android:visibility="gone"
tools:visibility="visible"
android:layout_marginTop="@dimen/spacing_large"/>
diff --git a/Habitica/res/layout/failed_item.xml b/common/src/main/res/layout/failed_item.xml
similarity index 76%
rename from Habitica/res/layout/failed_item.xml
rename to common/src/main/res/layout/failed_item.xml
index 9944a2a90..d43be218c 100644
--- a/Habitica/res/layout/failed_item.xml
+++ b/common/src/main/res/layout/failed_item.xml
@@ -2,24 +2,23 @@
-
+ android:src="@drawable/failed_loading"
+ app:tint="@color/text_quad"/>
\ No newline at end of file
diff --git a/Habitica/res/layout/loading_item.xml b/common/src/main/res/layout/loading_item.xml
similarity index 100%
rename from Habitica/res/layout/loading_item.xml
rename to common/src/main/res/layout/loading_item.xml
diff --git a/common/src/main/res/values/dimens.xml b/common/src/main/res/values/dimens.xml
index 6ec8e61fc..18f41656c 100644
--- a/common/src/main/res/values/dimens.xml
+++ b/common/src/main/res/values/dimens.xml
@@ -12,4 +12,7 @@
32dp
18dp
+
+ 18.0sp
+ 14.0sp
\ No newline at end of file
diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml
index 4e8ec2384..3f92d5bef 100644
--- a/common/src/main/res/values/strings.xml
+++ b/common/src/main/res/values/strings.xml
@@ -27,6 +27,7 @@
Settings
New Task
Avatar
+ Lvl. %d
Edit
Cancel
@@ -56,4 +57,8 @@
Create %s
Are you sure?
+ Task
+
+ Failed to load
+ Retry
\ No newline at end of file
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskLocalRepository.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskLocalRepository.kt
index 1268a5947..f0ba3b420 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskLocalRepository.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskLocalRepository.kt
@@ -8,6 +8,8 @@ import com.habitrpg.wearos.habitica.models.tasks.TaskList
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import java.util.Date
import javax.inject.Inject
import javax.inject.Singleton
@@ -19,6 +21,9 @@ class TaskLocalRepository @Inject constructor() {
TaskType.TODO to MutableLiveData>(),
TaskType.REWARD to MutableLiveData>()
)
+
+ private val taskCountHelperValue = MutableLiveData()
+
fun getTasks(type: TaskType): Flow> {
return tasks[type]?.asFlow() ?: emptyFlow()
}
@@ -38,6 +43,7 @@ class TaskLocalRepository @Inject constructor() {
for (type in taskMap) {
this.tasks[type.key]?.value = type.value
}
+ taskCountHelperValue.value = Date().time
}
fun updateTask(task: Task) {
@@ -51,6 +57,7 @@ class TaskLocalRepository @Inject constructor() {
oldList?.let {
tasks[task.type]?.value = it
}
+ taskCountHelperValue.value = Date().time
}
fun getTask(taskID: String): Flow {
@@ -63,10 +70,23 @@ class TaskLocalRepository @Inject constructor() {
return emptyFlow()
}
- fun getTaskCounts() = flowOf(mapOf(
+ fun getTaskCounts() = taskCountHelperValue.asFlow().map {
+ mapOf(
TaskType.HABIT.value to (tasks[TaskType.HABIT]?.value?.size ?: 0),
TaskType.DAILY.value to (tasks[TaskType.DAILY]?.value?.size ?: 0),
TaskType.TODO.value to (tasks[TaskType.TODO]?.value?.size ?: 0),
TaskType.REWARD.value to (tasks[TaskType.REWARD]?.value?.size ?: 0),
- ))
+ )
+ }
+
+ fun getActiveTaskCounts() = taskCountHelperValue.asFlow().map {
+ mapOf(
+ TaskType.HABIT.value to (tasks[TaskType.HABIT]?.value?.size ?: 0),
+ TaskType.DAILY.value to (tasks[TaskType.DAILY]?.value?.filter { it.isDue == true && !it.completed }?.size
+ ?: 0),
+ TaskType.TODO.value to (tasks[TaskType.TODO]?.value?.filter { !it.completed }?.size
+ ?: 0),
+ TaskType.REWARD.value to (tasks[TaskType.REWARD]?.value?.size ?: 0),
+ )
+ }
}
\ No newline at end of file
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskRepository.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskRepository.kt
index 14504050e..f87ac8842 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskRepository.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/TaskRepository.kt
@@ -43,4 +43,5 @@ class TaskRepository @Inject constructor(val apiClient: ApiClient, val localRepo
}
fun getTaskCounts() = localRepository.getTaskCounts()
+ fun getActiveTaskCounts() = localRepository.getActiveTaskCounts()
}
\ No newline at end of file
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/models/user/MenuItem.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/models/user/MenuItem.kt
index ab787fcbf..72c8abddc 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/models/user/MenuItem.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/models/user/MenuItem.kt
@@ -9,6 +9,7 @@ data class MenuItem(
val color: Int,
val textColor: Int,
val isProminent: Boolean = false,
+ val isHidden: Boolean = false,
var detailText: String? = null,
val onClick: () -> Unit
)
\ No newline at end of file
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/MainActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/MainActivity.kt
index a15220cec..f73bdfb52 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/MainActivity.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/MainActivity.kt
@@ -43,15 +43,6 @@ class MainActivity : BaseActivity() {
) {
openTaskFormActivity()
},
- MenuItem(
- TaskType.HABIT.value,
- getString(R.string.habits),
- AppCompatResources.getDrawable(this, R.drawable.icon_habits),
- ContextCompat.getColor(this, R.color.watch_purple_200),
- ContextCompat.getColor(this, R.color.watch_purple_700)
- ) {
- openTasklist(TaskType.HABIT)
- },
MenuItem(
TaskType.DAILY.value,
getString(R.string.dailies),
@@ -70,17 +61,27 @@ class MainActivity : BaseActivity() {
) {
openTasklist(TaskType.TODO)
},
+ MenuItem(
+ TaskType.HABIT.value,
+ getString(R.string.habits),
+ AppCompatResources.getDrawable(this, R.drawable.icon_habits),
+ ContextCompat.getColor(this, R.color.watch_purple_200),
+ ContextCompat.getColor(this, R.color.watch_purple_700)
+ ) {
+ openTasklist(TaskType.HABIT)
+ },
MenuItem(
TaskType.REWARD.value,
getString(R.string.rewards),
AppCompatResources.getDrawable(this, R.drawable.icon_rewards),
ContextCompat.getColor(this, R.color.watch_purple_200),
- ContextCompat.getColor(this, R.color.watch_purple_700)
+ ContextCompat.getColor(this, R.color.watch_purple_700),
+ isHidden = true
) {
openTasklist(TaskType.REWARD)
},
MenuItem(
- "Stats",
+ "stats",
getString(R.string.stats),
AppCompatResources.getDrawable(this, R.drawable.icon_stats),
ContextCompat.getColor(this, R.color.watch_purple_200),
@@ -110,6 +111,9 @@ class MainActivity : BaseActivity() {
viewModel.user.observe(this) {
adapter.title = it.profile?.name ?: ""
adapter.notifyItemChanged(0)
+ val index = adapter.data.indexOfFirst { it.identifier == "stats" }
+ adapter.data[index].detailText = getString(R.string.user_level, it.stats?.lvl ?: 0)
+ adapter.notifyItemChanged(index)
}
viewModel.taskCounts.observe(this) {
adapter.data.forEach { menuItem ->
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskListActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskListActivity.kt
index e389d4797..3922b3716 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskListActivity.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskListActivity.kt
@@ -6,6 +6,7 @@ import androidx.activity.viewModels
import androidx.wear.widget.WearableLinearLayoutManager
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.ActivityTasklistBinding
+import com.habitrpg.common.habitica.helpers.EmptyItem
import com.habitrpg.common.habitica.models.responses.TaskDirection
import com.habitrpg.common.habitica.models.responses.TaskScoringResult
import com.habitrpg.common.habitica.models.tasks.TaskType
@@ -32,6 +33,18 @@ class TaskListActivity: BaseActivity
layoutManager =
WearableLinearLayoutManager(this@TaskListActivity, HabiticaScrollingLayoutCallback())
adapter = this@TaskListActivity.adapter
+ emptyItem = EmptyItem(
+ getString(R.string.no_tasks, getString(when(viewModel.taskType) {
+ TaskType.HABIT -> R.string.habit
+ TaskType.DAILY -> R.string.daily
+ TaskType.TODO -> R.string.todo
+ TaskType.REWARD -> R.string.reward
+ else -> R.string.task
+ }))
+ )
+ onRefresh = {
+ viewModel.retrieveTasks()
+ }
}
viewModel.tasks.observe(this) {
@@ -46,10 +59,6 @@ class TaskListActivity: BaseActivity
openTaskDetailActivity(it)
}
- viewModel.user.observe(this) {
-
- }
-
binding.addTaskButton.setOnClickListener { openTaskFormActivity() }
}
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/HubViewHolder.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/HubViewHolder.kt
index 8c07f4419..3f94e168e 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/HubViewHolder.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/HubViewHolder.kt
@@ -19,9 +19,11 @@ class HubViewHolder(itemView: View): BindableViewHolder