From b71e0c48428069bd10bb51d68ef0d2744689df21 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Mon, 27 Jun 2022 11:20:19 +0200 Subject: [PATCH 1/6] Improve task list display --- Habitica/build.gradle | 6 +++- .../implementation/ChallengeRepositoryImpl.kt | 2 +- .../interactors/ScoreTaskLocallyInteractor.kt | 15 ++++++---- .../android/habitica/models/tasks/Task.kt | 16 ++++++++++- .../habitica/ui/activities/MainActivity.kt | 4 +-- .../ui/activities/MaintenanceActivity.kt | 2 +- .../challenges/ChallengeDetailFragment.kt | 13 +++++---- .../tasks/TaskRecyclerViewFragment.kt | 13 ++++++--- .../ui/viewHolders/tasks/HabitViewHolder.kt | 13 ++------- .../ui/viewmodels/MainActivityViewModel.kt | 6 ++-- .../ui/views/tasks/TaskFilterDialog.kt | 3 ++ .../android/habitica/utils/TaskSerializer.kt | 3 ++ build.gradle | 5 ++-- .../models/responses/MaintenanceResponse.java | 10 ------- .../models/responses/MaintenanceResponse.kt | 9 ++++++ .../res/drawable-hdpi/task_icon_calendar.png | Bin .../res/drawable-hdpi/task_icon_reminder.png | Bin .../res/drawable-hdpi/task_icon_streak.png | Bin .../res/drawable-hdpi/task_icon_team.png | Bin .../src/main}/res/drawable-hdpi/task_lock.png | Bin .../res/drawable-mdpi/task_icon_calendar.png | Bin .../res/drawable-mdpi/task_icon_reminder.png | Bin .../res/drawable-mdpi/task_icon_streak.png | Bin .../res/drawable-mdpi/task_icon_team.png | Bin .../src/main}/res/drawable-mdpi/task_lock.png | Bin .../res/drawable-xhdpi/task_icon_calendar.png | Bin .../res/drawable-xhdpi/task_icon_reminder.png | Bin .../res/drawable-xhdpi/task_icon_streak.png | Bin .../res/drawable-xhdpi/task_icon_team.png | Bin .../main}/res/drawable-xhdpi/task_lock.png | Bin .../drawable-xxhdpi/task_icon_calendar.png | Bin .../drawable-xxhdpi/task_icon_reminder.png | Bin .../res/drawable-xxhdpi/task_icon_streak.png | Bin .../res/drawable-xxhdpi/task_icon_team.png | Bin .../main}/res/drawable-xxhdpi/task_lock.png | Bin wearos/build.gradle | 2 +- .../wearos/habitica/models/tasks/Task.kt | 15 ++++++++++ .../ui/activities/SettingsActivity.kt | 9 +----- .../habitica/ui/adapters/SettingsAdapter.kt | 2 +- .../ui/viewHolders/tasks/DailyViewHolder.kt | 13 +++++++++ .../ui/viewHolders/tasks/HabitViewHolder.kt | 8 ++++++ wearos/src/main/res/layout/row_daily.xml | 20 +++++++++++-- wearos/src/main/res/layout/row_habit.xml | 27 +++++++++++++----- wearos/src/main/res/layout/row_settings.xml | 3 +- wearos/src/main/res/layout/row_todo.xml | 27 +++++++++++++----- 45 files changed, 172 insertions(+), 74 deletions(-) delete mode 100644 common/src/main/java/com/habitrpg/common/habitica/models/responses/MaintenanceResponse.java create mode 100644 common/src/main/java/com/habitrpg/common/habitica/models/responses/MaintenanceResponse.kt rename {Habitica => common/src/main}/res/drawable-hdpi/task_icon_calendar.png (100%) rename {Habitica => common/src/main}/res/drawable-hdpi/task_icon_reminder.png (100%) rename {Habitica => common/src/main}/res/drawable-hdpi/task_icon_streak.png (100%) rename {Habitica => common/src/main}/res/drawable-hdpi/task_icon_team.png (100%) rename {Habitica => common/src/main}/res/drawable-hdpi/task_lock.png (100%) rename {Habitica => common/src/main}/res/drawable-mdpi/task_icon_calendar.png (100%) rename {Habitica => common/src/main}/res/drawable-mdpi/task_icon_reminder.png (100%) rename {Habitica => common/src/main}/res/drawable-mdpi/task_icon_streak.png (100%) rename {Habitica => common/src/main}/res/drawable-mdpi/task_icon_team.png (100%) rename {Habitica => common/src/main}/res/drawable-mdpi/task_lock.png (100%) rename {Habitica => common/src/main}/res/drawable-xhdpi/task_icon_calendar.png (100%) rename {Habitica => common/src/main}/res/drawable-xhdpi/task_icon_reminder.png (100%) rename {Habitica => common/src/main}/res/drawable-xhdpi/task_icon_streak.png (100%) rename {Habitica => common/src/main}/res/drawable-xhdpi/task_icon_team.png (100%) rename {Habitica => common/src/main}/res/drawable-xhdpi/task_lock.png (100%) rename {Habitica => common/src/main}/res/drawable-xxhdpi/task_icon_calendar.png (100%) rename {Habitica => common/src/main}/res/drawable-xxhdpi/task_icon_reminder.png (100%) rename {Habitica => common/src/main}/res/drawable-xxhdpi/task_icon_streak.png (100%) rename {Habitica => common/src/main}/res/drawable-xxhdpi/task_icon_team.png (100%) rename {Habitica => common/src/main}/res/drawable-xxhdpi/task_lock.png (100%) diff --git a/Habitica/build.gradle b/Habitica/build.gradle index 661f8e427..d4baccca6 100644 --- a/Habitica/build.gradle +++ b/Habitica/build.gradle @@ -150,7 +150,7 @@ android { buildConfigField "String", "TESTING_LEVEL", "\"production\"" resConfigs 'en', 'bg', 'de', 'en-rGB', 'es', 'fr', 'hr-rHR', 'in', 'it', 'iw', 'ja', 'ko', 'lt', 'nl', 'pl', 'pt-rBR', 'pt-rPT', 'ru', 'tr', 'zh', 'zh-rTW' - versionCode 4000 + versionCode app_version_code versionName app_version_name targetSdkVersion target_sdk @@ -212,22 +212,26 @@ android { dimension "buildType" buildConfigField "String", "TESTING_LEVEL", "\"staff\"" resValue "string", "app_name", "Habitica Staff" + versionCode app_version_code + 6 } alpha { dimension "buildType" buildConfigField "String", "TESTING_LEVEL", "\"alpha\"" resValue "string", "app_name", "Habitica Alpha" + versionCode app_version_code + 4 } beta { buildConfigField "String", "TESTING_LEVEL", "\"beta\"" dimension "buildType" + versionCode app_version_code + 2 } prod { buildConfigField "String", "TESTING_LEVEL", "\"production\"" dimension "buildType" + versionCode app_version_code } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt index d150e600b..0f0fef56b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt @@ -69,7 +69,7 @@ class ChallengeRepositoryImpl( for ((key, value) in stringListMap) { val taskIdList = value.map { t -> t.id ?: "" } - + if (key == null) continue when (key) { TaskType.HABIT -> tasksOrder.habits = taskIdList TaskType.DAILY -> tasksOrder.dailys = taskIdList diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ScoreTaskLocallyInteractor.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ScoreTaskLocallyInteractor.kt index e59b9180b..f73bce063 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ScoreTaskLocallyInteractor.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/ScoreTaskLocallyInteractor.kt @@ -1,11 +1,11 @@ package com.habitrpg.android.habitica.interactors -import com.habitrpg.common.habitica.models.responses.TaskDirection -import com.habitrpg.common.habitica.models.responses.TaskDirectionData import com.habitrpg.android.habitica.models.tasks.Task -import com.habitrpg.common.habitica.models.tasks.TaskType import com.habitrpg.android.habitica.models.user.Stats import com.habitrpg.android.habitica.models.user.User +import com.habitrpg.common.habitica.models.responses.TaskDirection +import com.habitrpg.common.habitica.models.responses.TaskDirectionData +import com.habitrpg.common.habitica.models.tasks.TaskType import kotlin.math.min import kotlin.math.pow import kotlin.math.roundToLong @@ -46,6 +46,9 @@ class ScoreTaskLocallyInteractor { private fun scoreToDo(user: User, task: Task, direction: TaskDirection) { } + private fun scoreReward(user: User, task: Task, direction: TaskDirection) { + } + fun score(user: User, task: Task, direction: TaskDirection): TaskDirectionData? { return if (task.type == TaskType.HABIT || direction == TaskDirection.UP) { val stats = user.stats ?: return null @@ -67,14 +70,16 @@ class ScoreTaskLocallyInteractor { TaskType.HABIT -> scoreHabit(user, task, direction) TaskType.DAILY -> scoreDaily(user, task, direction) TaskType.TODO -> scoreToDo(user, task, direction) + TaskType.REWARD -> scoreReward(user, task, direction) + else -> {} } if (result.hp <= 0.0) { result.hp = 0.0 } - if (result.exp >= stats.toNextLevel?.toDouble() ?: 0.0) { + if (result.exp >= (stats.toNextLevel?.toDouble() ?: 0.0)) { result.exp = result.exp - (stats.toNextLevel?.toDouble() ?: 0.0) - result.lvl = user.stats?.lvl ?: 0 + 1 + result.lvl = (user.stats?.lvl ?: 0) + 1 result.hp = 50.0 } else { result.lvl = user.stats?.lvl ?: 0 diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt index ebe1b17ce..1e61f956b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt @@ -29,7 +29,6 @@ import java.util.Date import java.util.GregorianCalendar open class Task : RealmObject, BaseMainObject, Parcelable { - override val realmClass: Class get() = Task::class.java override val primaryIdentifier: String? @@ -109,6 +108,21 @@ open class Task : RealmObject, BaseMainObject, Parcelable { val completedChecklistCount: Int get() = checklist?.count { it.completed } ?: 0 + val streakString: String? + get() { + return if (counterUp != null && (counterUp ?: 0) > 0 && counterDown != null && (counterDown ?: 0) > 0) { + "+" + counterUp.toString() + " | -" + counterDown?.toString() + } else if (counterUp != null && (counterUp ?: 0) > 0) { + "+" + counterUp.toString() + } else if (counterDown != null && (counterDown ?: 0) > 0) { + "-" + counterDown.toString() + } else if ((streak ?: 0) > 0) { + return streak.toString() + } else { + null + } + } + val extraLightTaskColor: Int get() { return when { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt index a190fa740..e0d8bd7ab 100755 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt @@ -496,7 +496,7 @@ open class MainActivity : BaseActivity(), SnackbarActivity { private fun checkMaintenance() { viewModel.ifNeedsMaintenance { maintenanceResponse -> - if (maintenanceResponse.activeMaintenance) { + if (maintenanceResponse.activeMaintenance == true) { val intent = createMaintenanceIntent(maintenanceResponse, false) startActivity(intent) } else { @@ -504,7 +504,7 @@ open class MainActivity : BaseActivity(), SnackbarActivity { try { val packageInfo = packageManager.getPackageInfo(packageName, 0) @Suppress("DEPRECATION") - if (packageInfo.versionCode < maintenanceResponse.minBuild) { + if (packageInfo.versionCode < (maintenanceResponse.minBuild ?: 0)) { val intent = createMaintenanceIntent(maintenanceResponse, true) startActivity(intent) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MaintenanceActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MaintenanceActivity.kt index 9a5f4872b..7bef8b85f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MaintenanceActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MaintenanceActivity.kt @@ -72,7 +72,7 @@ class MaintenanceActivity : BaseActivity() { .observeOn(AndroidSchedulers.mainThread()) .subscribe( { maintenanceResponse -> - if (!maintenanceResponse.activeMaintenance) { + if (maintenanceResponse.activeMaintenance == false) { finish() } }, diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailFragment.kt index 8a968cef5..e9569346f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailFragment.kt @@ -24,21 +24,21 @@ import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.members.Member import com.habitrpg.android.habitica.models.social.Challenge import com.habitrpg.android.habitica.models.tasks.Task -import com.habitrpg.common.habitica.models.tasks.TaskType import com.habitrpg.android.habitica.ui.activities.ChallengeFormActivity import com.habitrpg.android.habitica.ui.activities.FullProfileActivity import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment -import com.habitrpg.common.habitica.helpers.EmojiParser -import com.habitrpg.common.habitica.helpers.setMarkdown import com.habitrpg.android.habitica.ui.viewHolders.tasks.DailyViewHolder import com.habitrpg.android.habitica.ui.viewHolders.tasks.HabitViewHolder import com.habitrpg.android.habitica.ui.viewHolders.tasks.RewardViewHolder import com.habitrpg.android.habitica.ui.viewHolders.tasks.TodoViewHolder import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel -import com.habitrpg.common.habitica.views.HabiticaIconsHelper import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog -import javax.inject.Inject +import com.habitrpg.common.habitica.helpers.EmojiParser +import com.habitrpg.common.habitica.helpers.setMarkdown +import com.habitrpg.common.habitica.models.tasks.TaskType +import com.habitrpg.common.habitica.views.HabiticaIconsHelper import retrofit2.HttpException +import javax.inject.Inject class ChallengeDetailFragment : BaseMainFragment() { @@ -117,7 +117,8 @@ class ChallengeDetailFragment : BaseMainFragment val rewards = ArrayList() for (entry in taskList) { - when (entry.type) { + val type = entry.type ?: continue + when (type) { TaskType.TODO -> todos.add(entry) TaskType.HABIT -> habits.add(entry) TaskType.DAILY -> dailies.add(entry) 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 dcc701b40..4626b579b 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 @@ -28,10 +28,7 @@ import com.habitrpg.android.habitica.helpers.MainNavigationController import com.habitrpg.android.habitica.helpers.NotificationsManager import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.helpers.SoundManager -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.ui.activities.MainActivity import com.habitrpg.android.habitica.ui.activities.TaskFormActivity import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter @@ -45,9 +42,12 @@ import com.habitrpg.android.habitica.ui.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 -import com.habitrpg.common.habitica.views.HabiticaIconsHelper import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog +import com.habitrpg.common.habitica.models.responses.TaskDirection +import com.habitrpg.common.habitica.models.responses.TaskScoringResult +import com.habitrpg.common.habitica.models.tasks.TaskType +import com.habitrpg.common.habitica.views.HabiticaIconsHelper import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.disposables.CompositeDisposable import kotlinx.coroutines.Job @@ -471,6 +471,7 @@ open class TaskRecyclerViewFragment : BaseFragment {} } } } @@ -534,6 +535,10 @@ open class TaskRecyclerViewFragment : BaseFragment { + fragment.tutorialStepIdentifier = "rewards" + tutorialTexts = listOf(context.getString(R.string.tutorial_rewards_1), context.getString(R.string.tutorial_rewards_2)) + } } } 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 c5d9788af..381a7b484 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 @@ -7,8 +7,8 @@ import android.widget.FrameLayout import android.widget.ImageView import androidx.core.content.ContextCompat import com.habitrpg.android.habitica.R -import com.habitrpg.common.habitica.models.responses.TaskDirection import com.habitrpg.android.habitica.models.tasks.Task +import com.habitrpg.common.habitica.models.responses.TaskDirection class HabitViewHolder( itemView: View, @@ -110,15 +110,8 @@ class HabitViewHolder( this.btnMinus.isClickable = false } - var streakString = "" - if (data.counterUp != null && data.counterUp ?: 0 > 0 && data.counterDown != null && data.counterDown ?: 0 > 0) { - streakString = streakString + "+" + data.counterUp.toString() + " | -" + data.counterDown?.toString() - } else if (data.counterUp != null && data.counterUp ?: 0 > 0) { - streakString = streakString + "+" + data.counterUp.toString() - } else if (data.counterDown != null && data.counterDown ?: 0 > 0) { - streakString = streakString + "-" + data.counterDown.toString() - } - if (streakString.isNotEmpty()) { + val streakString = task?.streakString + if (streakString?.isNotEmpty() == true) { streakTextView.text = streakString streakTextView.visibility = View.VISIBLE streakIconView.visibility = View.VISIBLE diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainActivityViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainActivityViewModel.kt index 3d147718e..49fdd9f2c 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainActivityViewModel.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/MainActivityViewModel.kt @@ -4,7 +4,6 @@ import android.content.SharedPreferences import androidx.core.content.edit import androidx.lifecycle.viewModelScope import com.habitrpg.android.habitica.R -import com.habitrpg.common.habitica.api.HostConfig import com.habitrpg.android.habitica.api.MaintenanceApiService import com.habitrpg.android.habitica.components.UserComponent import com.habitrpg.android.habitica.data.ContentRepository @@ -16,9 +15,10 @@ import com.habitrpg.android.habitica.helpers.TaskAlarmManager import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager import com.habitrpg.android.habitica.models.TutorialStep import com.habitrpg.android.habitica.models.inventory.Egg -import com.habitrpg.common.habitica.models.responses.MaintenanceResponse import com.habitrpg.android.habitica.proxy.AnalyticsManager import com.habitrpg.android.habitica.ui.TutorialView +import com.habitrpg.common.habitica.api.HostConfig +import com.habitrpg.common.habitica.models.responses.MaintenanceResponse import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.schedulers.Schedulers import io.realm.kotlin.isValid @@ -136,7 +136,7 @@ class MainActivityViewModel : BaseViewModel(), TutorialView.OnTutorialReaction { .observeOn(AndroidSchedulers.mainThread()) .subscribe( { maintenanceResponse -> - if (maintenanceResponse == null) { + if (maintenanceResponse.activeMaintenance == null) { return@subscribe } onResult(maintenanceResponse) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/TaskFilterDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/TaskFilterDialog.kt index 1623d21c7..fa249029c 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/TaskFilterDialog.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/TaskFilterDialog.kt @@ -63,6 +63,9 @@ class TaskFilterDialog(context: Context, component: UserComponent?) : HabiticaBo binding.secondTaskFilter.setText(R.string.dated) binding.thirdTaskFilter.setText(R.string.completed) } + TaskType.REWARD -> { + + } } setActiveFilter(viewModel.getActiveFilter(value)) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/TaskSerializer.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/TaskSerializer.kt index bde20e30b..b4845d870 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/TaskSerializer.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/TaskSerializer.kt @@ -184,6 +184,9 @@ class TaskSerializer : JsonSerializer, JsonDeserializer { } obj.addProperty("completed", task.completed) } + else -> { + + } } return obj diff --git a/build.gradle b/build.gradle index 25a598769..04bbe2395 100644 --- a/build.gradle +++ b/build.gradle @@ -4,9 +4,10 @@ buildscript { ext { target_sdk = 32 app_version_name = '4.0' + app_version_code = 4010 - kotlin_version = '1.6.21' + kotlin_version = '1.7.0' core_ktx_version = '1.8.0' appcompat_version = '1.4.2' lifecycle_version = '2.4.1' @@ -37,7 +38,7 @@ buildscript { classpath "io.realm:realm-gradle-plugin:10.10.1" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.19.0" - classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0-rc01" + classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0-rc02" classpath 'com.google.firebase:perf-plugin:1.4.1' classpath "com.google.dagger:hilt-android-gradle-plugin:$daggerhilt_version" } diff --git a/common/src/main/java/com/habitrpg/common/habitica/models/responses/MaintenanceResponse.java b/common/src/main/java/com/habitrpg/common/habitica/models/responses/MaintenanceResponse.java deleted file mode 100644 index ffcffb8b3..000000000 --- a/common/src/main/java/com/habitrpg/common/habitica/models/responses/MaintenanceResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.habitrpg.common.habitica.models.responses; - -public class MaintenanceResponse { - - public Boolean activeMaintenance; - public Integer minBuild; - public String title; - public String imageUrl; - public String description; -} diff --git a/common/src/main/java/com/habitrpg/common/habitica/models/responses/MaintenanceResponse.kt b/common/src/main/java/com/habitrpg/common/habitica/models/responses/MaintenanceResponse.kt new file mode 100644 index 000000000..034ddc1d3 --- /dev/null +++ b/common/src/main/java/com/habitrpg/common/habitica/models/responses/MaintenanceResponse.kt @@ -0,0 +1,9 @@ +package com.habitrpg.common.habitica.models.responses + +class MaintenanceResponse { + var activeMaintenance: Boolean? = null + var minBuild: Int? = null + var title: String? = null + var imageUrl: String? = null + var description: String? = null +} \ No newline at end of file diff --git a/Habitica/res/drawable-hdpi/task_icon_calendar.png b/common/src/main/res/drawable-hdpi/task_icon_calendar.png similarity index 100% rename from Habitica/res/drawable-hdpi/task_icon_calendar.png rename to common/src/main/res/drawable-hdpi/task_icon_calendar.png diff --git a/Habitica/res/drawable-hdpi/task_icon_reminder.png b/common/src/main/res/drawable-hdpi/task_icon_reminder.png similarity index 100% rename from Habitica/res/drawable-hdpi/task_icon_reminder.png rename to common/src/main/res/drawable-hdpi/task_icon_reminder.png diff --git a/Habitica/res/drawable-hdpi/task_icon_streak.png b/common/src/main/res/drawable-hdpi/task_icon_streak.png similarity index 100% rename from Habitica/res/drawable-hdpi/task_icon_streak.png rename to common/src/main/res/drawable-hdpi/task_icon_streak.png diff --git a/Habitica/res/drawable-hdpi/task_icon_team.png b/common/src/main/res/drawable-hdpi/task_icon_team.png similarity index 100% rename from Habitica/res/drawable-hdpi/task_icon_team.png rename to common/src/main/res/drawable-hdpi/task_icon_team.png diff --git a/Habitica/res/drawable-hdpi/task_lock.png b/common/src/main/res/drawable-hdpi/task_lock.png similarity index 100% rename from Habitica/res/drawable-hdpi/task_lock.png rename to common/src/main/res/drawable-hdpi/task_lock.png diff --git a/Habitica/res/drawable-mdpi/task_icon_calendar.png b/common/src/main/res/drawable-mdpi/task_icon_calendar.png similarity index 100% rename from Habitica/res/drawable-mdpi/task_icon_calendar.png rename to common/src/main/res/drawable-mdpi/task_icon_calendar.png diff --git a/Habitica/res/drawable-mdpi/task_icon_reminder.png b/common/src/main/res/drawable-mdpi/task_icon_reminder.png similarity index 100% rename from Habitica/res/drawable-mdpi/task_icon_reminder.png rename to common/src/main/res/drawable-mdpi/task_icon_reminder.png diff --git a/Habitica/res/drawable-mdpi/task_icon_streak.png b/common/src/main/res/drawable-mdpi/task_icon_streak.png similarity index 100% rename from Habitica/res/drawable-mdpi/task_icon_streak.png rename to common/src/main/res/drawable-mdpi/task_icon_streak.png diff --git a/Habitica/res/drawable-mdpi/task_icon_team.png b/common/src/main/res/drawable-mdpi/task_icon_team.png similarity index 100% rename from Habitica/res/drawable-mdpi/task_icon_team.png rename to common/src/main/res/drawable-mdpi/task_icon_team.png diff --git a/Habitica/res/drawable-mdpi/task_lock.png b/common/src/main/res/drawable-mdpi/task_lock.png similarity index 100% rename from Habitica/res/drawable-mdpi/task_lock.png rename to common/src/main/res/drawable-mdpi/task_lock.png diff --git a/Habitica/res/drawable-xhdpi/task_icon_calendar.png b/common/src/main/res/drawable-xhdpi/task_icon_calendar.png similarity index 100% rename from Habitica/res/drawable-xhdpi/task_icon_calendar.png rename to common/src/main/res/drawable-xhdpi/task_icon_calendar.png diff --git a/Habitica/res/drawable-xhdpi/task_icon_reminder.png b/common/src/main/res/drawable-xhdpi/task_icon_reminder.png similarity index 100% rename from Habitica/res/drawable-xhdpi/task_icon_reminder.png rename to common/src/main/res/drawable-xhdpi/task_icon_reminder.png diff --git a/Habitica/res/drawable-xhdpi/task_icon_streak.png b/common/src/main/res/drawable-xhdpi/task_icon_streak.png similarity index 100% rename from Habitica/res/drawable-xhdpi/task_icon_streak.png rename to common/src/main/res/drawable-xhdpi/task_icon_streak.png diff --git a/Habitica/res/drawable-xhdpi/task_icon_team.png b/common/src/main/res/drawable-xhdpi/task_icon_team.png similarity index 100% rename from Habitica/res/drawable-xhdpi/task_icon_team.png rename to common/src/main/res/drawable-xhdpi/task_icon_team.png diff --git a/Habitica/res/drawable-xhdpi/task_lock.png b/common/src/main/res/drawable-xhdpi/task_lock.png similarity index 100% rename from Habitica/res/drawable-xhdpi/task_lock.png rename to common/src/main/res/drawable-xhdpi/task_lock.png diff --git a/Habitica/res/drawable-xxhdpi/task_icon_calendar.png b/common/src/main/res/drawable-xxhdpi/task_icon_calendar.png similarity index 100% rename from Habitica/res/drawable-xxhdpi/task_icon_calendar.png rename to common/src/main/res/drawable-xxhdpi/task_icon_calendar.png diff --git a/Habitica/res/drawable-xxhdpi/task_icon_reminder.png b/common/src/main/res/drawable-xxhdpi/task_icon_reminder.png similarity index 100% rename from Habitica/res/drawable-xxhdpi/task_icon_reminder.png rename to common/src/main/res/drawable-xxhdpi/task_icon_reminder.png diff --git a/Habitica/res/drawable-xxhdpi/task_icon_streak.png b/common/src/main/res/drawable-xxhdpi/task_icon_streak.png similarity index 100% rename from Habitica/res/drawable-xxhdpi/task_icon_streak.png rename to common/src/main/res/drawable-xxhdpi/task_icon_streak.png diff --git a/Habitica/res/drawable-xxhdpi/task_icon_team.png b/common/src/main/res/drawable-xxhdpi/task_icon_team.png similarity index 100% rename from Habitica/res/drawable-xxhdpi/task_icon_team.png rename to common/src/main/res/drawable-xxhdpi/task_icon_team.png diff --git a/Habitica/res/drawable-xxhdpi/task_lock.png b/common/src/main/res/drawable-xxhdpi/task_lock.png similarity index 100% rename from Habitica/res/drawable-xxhdpi/task_lock.png rename to common/src/main/res/drawable-xxhdpi/task_lock.png diff --git a/wearos/build.gradle b/wearos/build.gradle index 51dea440d..ae270f26b 100644 --- a/wearos/build.gradle +++ b/wearos/build.gradle @@ -13,7 +13,7 @@ android { applicationId "com.habitrpg.android.habitica" minSdk 26 targetSdk target_sdk - versionCode 4001 + versionCode app_version_code + 1 versionName app_version_name } diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/models/tasks/Task.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/models/tasks/Task.kt index 0697073e3..effbfffe4 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/models/tasks/Task.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/models/tasks/Task.kt @@ -92,6 +92,21 @@ open class Task constructor(): Parcelable { val completedChecklistCount: Int get() = checklist?.count { it.completed } ?: 0 + val streakString: String? + get() { + return if (counterUp != null && (counterUp ?: 0) > 0 && counterDown != null && (counterDown ?: 0) > 0) { + "+" + counterUp.toString() + " | -" + counterDown?.toString() + } else if (counterUp != null && (counterUp ?: 0) > 0) { + "+" + counterUp.toString() + } else if (counterDown != null && (counterDown ?: 0) > 0) { + "-" + counterDown.toString() + } else if ((streak ?: 0) > 0) { + return streak.toString() + } else { + null + } + } + val extraLightTaskColor: Int get() { return when { diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/SettingsActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/SettingsActivity.kt index c4f5f7a9e..333405502 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/SettingsActivity.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/SettingsActivity.kt @@ -66,17 +66,10 @@ class SettingsActivity: BaseActivity adapter.data[index].value = viewModel.isTaskResultHidden() adapter.notifyItemChanged(index) }, - SettingsItem( - "spacer", - getString(R.string.settings), - SettingsItem.Types.SPACER, - null - ) { - }, SettingsItem( "logout", getString(R.string.logout), - SettingsItem.Types.DESTRUCTIVE_BUTTON, + SettingsItem.Types.BUTTON, null ) { showLogoutConfirmation() diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/adapters/SettingsAdapter.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/adapters/SettingsAdapter.kt index baa255043..a340e1cdb 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/adapters/SettingsAdapter.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/adapters/SettingsAdapter.kt @@ -80,7 +80,7 @@ class SettingsViewHolder(itemView: View) : BindableViewHolder(item if (data.value as? Boolean == true) { binding.row.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(itemView.context, R.color.watch_purple_100)) - binding.row.background.alpha = 127 + binding.row.background.alpha = 102 } else { binding.row.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(itemView.context, R.color.watch_purple_5)) binding.row.background.alpha = 255 diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/tasks/DailyViewHolder.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/tasks/DailyViewHolder.kt index 94499cc59..370813a38 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/tasks/DailyViewHolder.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/tasks/DailyViewHolder.kt @@ -4,7 +4,9 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView +import androidx.core.view.isVisible import com.habitrpg.android.habitica.databinding.RowDailyBinding +import com.habitrpg.wearos.habitica.models.tasks.Task class DailyViewHolder(itemView: View) : CheckedTaskViewHolder(itemView) { private val binding = RowDailyBinding.bind(itemView) @@ -14,4 +16,15 @@ class DailyViewHolder(itemView: View) : CheckedTaskViewHolder(itemView) { get() = binding.checkbox override val checkboxWrapper: ViewGroup get() = binding.checkboxWrapper + + override fun bind(data: Task) { + super.bind(data) + val streakString = data.streakString + if (streakString?.isNotBlank() == true) { + binding.streakView.text = streakString + binding.streakView.isVisible = true + } else { + binding.streakView.isVisible = false + } + } } \ No newline at end of file diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/tasks/HabitViewHolder.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/tasks/HabitViewHolder.kt index db7dacdcc..e828837c1 100644 --- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/tasks/HabitViewHolder.kt +++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/viewHolders/tasks/HabitViewHolder.kt @@ -3,6 +3,7 @@ package com.habitrpg.wearos.habitica.ui.viewHolders.tasks import android.content.res.ColorStateList import android.view.View import android.widget.TextView +import androidx.core.view.isVisible import androidx.core.content.ContextCompat import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.databinding.RowHabitBinding @@ -42,5 +43,12 @@ class HabitViewHolder(itemView: View) : TaskViewHolder(itemView) { binding.habitButtonIcon.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(itemView.context, data.mediumTaskColor)) binding.habitButtonIcon.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(itemView.context, R.color.white)) } + val streakString = data.streakString + if (streakString?.isNotBlank() == true) { + binding.streakView.text = streakString + binding.streakView.isVisible = true + } else { + binding.streakView.isVisible = false + } } } \ No newline at end of file diff --git a/wearos/src/main/res/layout/row_daily.xml b/wearos/src/main/res/layout/row_daily.xml index ed6996735..b2d3fa0b3 100644 --- a/wearos/src/main/res/layout/row_daily.xml +++ b/wearos/src/main/res/layout/row_daily.xml @@ -2,7 +2,8 @@ + android:layout_height="wrap_content" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + tools:text="Task Title" + style="@style/Text.Body2"/> + + \ No newline at end of file diff --git a/wearos/src/main/res/layout/row_habit.xml b/wearos/src/main/res/layout/row_habit.xml index 9cbeeeb01..b06dc6489 100644 --- a/wearos/src/main/res/layout/row_habit.xml +++ b/wearos/src/main/res/layout/row_habit.xml @@ -2,7 +2,8 @@ + android:layout_height="wrap_content" + xmlns:app="http://schemas.android.com/apk/res-auto"> - + android:orientation="vertical"> + + + \ No newline at end of file diff --git a/wearos/src/main/res/layout/row_settings.xml b/wearos/src/main/res/layout/row_settings.xml index ae01d67d7..cbcad5dfb 100644 --- a/wearos/src/main/res/layout/row_settings.xml +++ b/wearos/src/main/res/layout/row_settings.xml @@ -10,7 +10,8 @@ android:id="@+id/row" android:layout_width="match_parent" android:layout_height="wrap_content" - style="@style/Chip"> + style="@style/Chip" + android:paddingHorizontal="20dp"> + android:layout_height="wrap_content" + xmlns:app="http://schemas.android.com/apk/res-auto"> - + android:orientation="vertical"> + + + \ No newline at end of file From 0d0c4e403845fa3f2ebfcc1aba0bd01169a7b846 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Mon, 27 Jun 2022 15:23:00 +0200 Subject: [PATCH 2/6] Various minor improvements --- .../baseline_error_outline_black_36dp.png | Bin 746 -> 0 bytes .../baseline_error_outline_black_36dp.png | Bin 499 -> 0 bytes .../baseline_error_outline_black_36dp.png | Bin 954 -> 0 bytes .../baseline_error_outline_black_36dp.png | Bin 1790 -> 0 bytes .../baseline_error_outline_black_36dp.png | Bin 2631 -> 0 bytes Habitica/res/values/dimens.xml | 3 +- Habitica/res/values/strings.xml | 3 - .../ui/activities/FullProfileActivity.kt | 2 +- .../equipment/EquipmentDetailFragment.kt | 2 +- .../inventory/items/ItemDialogFragment.kt | 2 +- .../inventory/items/ItemRecyclerFragment.kt | 2 +- .../fragments/inventory/shops/ShopFragment.kt | 2 +- .../stable/StableRecyclerFragment.kt | 2 +- .../challenges/ChallengeListFragment.kt | 2 +- .../social/guilds/GuildListFragment.kt | 2 +- .../tasks/TaskRecyclerViewFragment.kt | 2 +- .../ui/helpers/RecyclerViewEmptySupport.kt | 133 +++--------------- .../extensions/ViewGroup-Extensions.kt | 0 .../helpers/RecyclerViewEmptySupport.kt | 118 ++++++++++++++++ .../res/drawable-anydpi/failed_loading.xml | 16 +++ .../main/res/drawable-hdpi/failed_loading.png | Bin 0 -> 577 bytes .../main/res/drawable-mdpi/failed_loading.png | Bin 0 -> 424 bytes .../res/drawable-xhdpi/failed_loading.png | Bin 0 -> 904 bytes .../res/drawable-xxhdpi/failed_loading.png | Bin 0 -> 1312 bytes .../src/main}/res/layout/empty_item.xml | 3 +- .../src/main}/res/layout/failed_item.xml | 9 +- .../src/main}/res/layout/loading_item.xml | 0 common/src/main/res/values/dimens.xml | 3 + common/src/main/res/values/strings.xml | 5 + .../data/repositories/TaskLocalRepository.kt | 24 +++- .../data/repositories/TaskRepository.kt | 1 + .../wearos/habitica/models/user/MenuItem.kt | 1 + .../habitica/ui/activities/MainActivity.kt | 26 ++-- .../ui/activities/TaskListActivity.kt | 17 ++- .../habitica/ui/viewHolders/HubViewHolder.kt | 2 + .../habitica/ui/viewmodels/MainViewModel.kt | 2 +- .../ui/viewmodels/TaskListViewModel.kt | 5 + .../wearos/habitica/ui/views/AddTaskButton.kt | 32 +++-- .../habitica/ui/views/HabiticaRecyclerView.kt | 72 +++++++++- wearos/src/main/res/layout/activity_rya.xml | 6 +- .../src/main/res/layout/activity_tasklist.xml | 2 +- wearos/src/main/res/layout/row_hub.xml | 3 +- wearos/src/main/res/values/strings.xml | 1 + 43 files changed, 340 insertions(+), 165 deletions(-) delete mode 100644 Habitica/res/drawable-hdpi/baseline_error_outline_black_36dp.png delete mode 100644 Habitica/res/drawable-mdpi/baseline_error_outline_black_36dp.png delete mode 100644 Habitica/res/drawable-xhdpi/baseline_error_outline_black_36dp.png delete mode 100644 Habitica/res/drawable-xxhdpi/baseline_error_outline_black_36dp.png delete mode 100644 Habitica/res/drawable-xxxhdpi/baseline_error_outline_black_36dp.png rename {Habitica/src/main/java/com/habitrpg/android => common/src/main/java/com/habitrpg/common}/habitica/extensions/ViewGroup-Extensions.kt (100%) create mode 100644 common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt create mode 100644 common/src/main/res/drawable-anydpi/failed_loading.xml create mode 100644 common/src/main/res/drawable-hdpi/failed_loading.png create mode 100644 common/src/main/res/drawable-mdpi/failed_loading.png create mode 100644 common/src/main/res/drawable-xhdpi/failed_loading.png create mode 100644 common/src/main/res/drawable-xxhdpi/failed_loading.png rename {Habitica => common/src/main}/res/layout/empty_item.xml (95%) rename {Habitica => common/src/main}/res/layout/failed_item.xml (76%) rename {Habitica => common/src/main}/res/layout/loading_item.xml (100%) 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 ec4860d026be38f31181fb3ea2a482f16834ed85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 746 zcmVG0rXAX3E}1^c2RK*nOy{);>^D7? z52&`DnD**FankfzK8RTBriWVGqQP`Pi$sC=n>PN34Yq0jSf5NMv}DeizR3^X>9OgQ z^418p^r3I+uhUo4*{(xvnA8vXLD4fUuH;l;4FxJp*c_B8+fr{dTyu;iz736);mIGs^KHe)Y`);r%?~II%sjvGzixFO^-zGq{n1tmv84Wpd6YZy z9XW9-CCK}utrTKO{Sosh%}%V@Td{WXm|NYa1o`+TC6C(azBa|_zV-vUHpCLgHu(V! zHA||R%qpp%W)WO-jm<8Co87iRlN(J~lMkqgqk(1*bD+uNw~i(cOrhB$ZfNqQL`Rda zkvf>%(3R`N19aQH`0LV)k zSs62%s(Tq8FjjY}br}Pc=TL?RAh|Qunrcxs--tH9(dSR#U3DNoC?m;SNH^%CYD+ca z*oD9bTYTIY=aQL}zcQCnuR<#L;OoX>rIOf?dWkK-iPS5W3%h$*6BgD(Cr?AM9iLcAH*W2*>ffI!YrPpb=dB9e@jY2Kuoje zp6XluuN&BmDO=2GN==BE?v~(255nWX3{Snj5UB|PvCW4ugAAlKT=n`wJm{`@n@ prI-&zm!dwUT_|G_e>O}gf=~SVAB2U+kQ4v_002ovPDHLkV1jk2=;Z(a 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 356880514a609db407c37d792989adeb8cacbcde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 954 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 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 0000000000000000000000000000000000000000..92a4bc43bd500f85765e844c5e92bbb7f14997e6 GIT binary patch literal 577 zcmV-H0>1r;P))@TRlPO2YK?(8So@h8{z-Mu@ArKcCk7{YGX z2oc!_9s@rDZ-I}%ZzW#i8rBfA=lsnO#3wDb6t5+6Cf4gl5Ib}lVM61;`b`J|Z;o(G zjOZSCRpNC#LXWRpXB9H#Q9%`(c z62CJij%x)p9NinoB@nx3zNDioIY3J_;~E!^dqRWx4mLBhpt_FOQB{pe(*1Ggbq~;{ zTIuLyKJ?;%Dq*0<5I}k0R9dtx%wWI}kM6oG;A3tVD$#2Qpj>e8&9iFnEEqIoYl}Ti z*AJ@*gNE#MNbtc)YZx&Epk|V9E;M2TLuo^zH*?Dxv4Npv%lu12qa(YhDbW93Du8b2 zIkKTmJqpth8T{Cf0JW(0^J8xhr(c3w+jZFh6+J7PZbs}cjCnee?j!K;zFc*2qQ&x0 z%LoI8xH}UEaF?pu-(v{cRLkaxZ6R1ax>_{V2@CHO_?ZpvfSQ43T%&xLiX9zTHNFyp z#*3qCN5zo*gJRdSIdU|Y_39oJ0X5}yYB6>!iD^D!JR=~qv-w$w-BZl?{~!>rz3#>= z@0m5o-11zvS_qBik!KvH1CriUYkVJi?&8% P00000NkvXXu0mjf;j;l@ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..1e3f3a3ec8eb73b207268f3c27ecf54706dba11a GIT binary patch literal 424 zcmV;Z0ayNsP) zvsr+MG|G47m-3>#8~Mh@T$BBt!UBJWfX|4wE|Cgb@g`8gJ~^F~ zZ&~MH&NR_ypLIRR9z<8=Hfu^iYd-GZW&u6Fh2X`iOTZ^2A=bDjI_N_7*~-zy*W_$OXg&sDPvZsem+K72pDt0;mGg(*;ieE%Lbh03@ZE?99&C z!eMWZ1P-L^r>7NQW-o!ez@LF1f#<-#j(o=0KJa_sv)8#RFcA17@KczbOXlwEp2b+a z+K0ee7%F9L@y@*Xe5)cQA(=O@7VE&h&$}2w^qb``l|O-}M1J<;VJHQTaKgKr3nb zJY_{NL5MWu_OIUd&`jDsU&G4Jk+8U7Yasyhu0#RIA@V{z4eqZm*l@Sm+;eEDgjQ|s3mblU7eS|%P8KjL^oj}qrW?y`Urq*O0<%JI zNdam@$Btxi`S`(0S0WFX6`I8b06YoJ=b`G3ULXgU6`D&6I10^*0o8qqmk+?K&|F%8 zy3l(D)YD+U&t?E&p}DjG&MB{XVxac|?kDF0vtE{=6{*8y3(z)Kme* z{lCG61@xBte_6oUPt3)J1@!l;sdcpwLE{y}j;}s07v86_UrpQ=Ti8ao0G@=;Ya3nt zAlm|X51`@;K4Oj|t3Lj8^vDLuzhPi7IBj%?c^(}t6tCrGTiWo6J zymUN9MBu>+HueKV+!s0UEv183b(Bk5(-rWX4GK){Kxl5}}=Ca4`XIudT$p}}GckJF51<5R9 e#LzZZG5rsq`mrU5j!U}$0000gFKP)_l|FYpN>C*{4HK*TlQH=dq)o!)P>`%|K8oDPE$NNaLR()YR4br1;R21WSN92{?@zHV@0uAmp$ z-u!U9l6n_~6Y!u2J2XB>-OT~NGVu;cF{S)=e0O|wyn`Qw8hMRv*p_{yol;WkGAkau z@Iet_@e96AP2S6}Z?HjI(!Rw3Gkh1pIk-_ATYPRIj5dR9>CfVgv{eN(tT@Y&Q=|E? zrjOuD`p>a$l4wwIGDg;m=82J@&){3?8DpI!!PgvVTqBEU9j7w@U)ZI#G0vO%@ONcU z3`=sAnCGk_s0C$(e88O19s-v}CE4cSw)fOjs$cdk0?G>CK_(}H+JZ)@Tk=u%%>re0 z=b)1lL5)GH)Gt|nEGaN}6v>I8R@gPEY^uTURAuLsT&=1VWW(RRY(Ev$tk{>lll`^; zpXovAn6m0pj)f9Lz}^B3$juB2QaYu4mwo2K@L4rM1Y=PAl=*}`dZzCgMnFM|A6x81 zFb2g>%1_y64cNzt{g%Q)VBrK2un)PrWyJmXsx(Ylee@9MlOSspz3$uLd8||QWG(xfB_H|e^_AGI4s=Qo!Ppd^k(+6T{OZ+OWX}ZUd=Iga zHPo6-F9LaytrKLOIah3yTi(B=(b_=A1QCo;@f&$#39PV`=I6<#ol0yO5BmJb_Rbr7^4z* zbJ#y{&(4KEpE=SnpRTIIOlsHpvJ+wc)_Sxn3%|U*e?RKaHbVv|mQGBJ` zesLH&<(7N0$)*u~5@d~@-B-^9@~atHeH3Bg1i`L7LBP4<}!!)J>GS%2g= ze*T32fXW(0;|3-G3nqx#6(1=X`}hY`1Vt$wC95s_hQDeFqGrXuWZBKf@BD}}w<%o5 zB>Rm5_8H}9l0=O`tJE*K-?Jy=pOYL#lBg|cl)5FSZD9(HA7qlKsZ_u0TMYOer?sk) zoZr<7_gqj*&?I$AGPZepJCxO<$nJlRO$~}JjZ99Rn+p3Fl9C&-d3R+37;Nw@^^8$J zPD}+2Do%2I!UBn+kKjxC&#`WDB4}7~X7LHNhH?Vh47R1e967DpBqsvCCY2O!$@srD zE~U*O4R8k51c?6b^1Cc!^q Wv{^17$9+Hm0000 @@ -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"/>