diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
index dd836b80b..f7ec0a105 100644
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -44,31 +44,31 @@ jobs:
with:
arguments: testProdDebugUnitTest
- ui-test:
- runs-on: macos-latest
- strategy:
- matrix:
- api-level: [24, 26, 28, 29, 30, 31]
- steps:
- - uses: actions/checkout@v2
- - name: set up JDK 11
- uses: actions/setup-java@v2
- with:
- java-version: '11'
- distribution: 'adopt'
- cache: gradle
- - name: Prepare
- run: ./.github/prepare-workflow
- - name: Validate Gradle wrapper
- uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
- - name: run tests
- uses: reactivecircus/android-emulator-runner@v2
- with:
- api-level: ${{ matrix.api-level }}
- arch: x86_64
- emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
- disable-animations: true
- script: ./gradlew connectedProdDebugAndroidTest
+# ui-test:
+# runs-on: macos-latest
+# strategy:
+# matrix:
+# api-level: [24, 26, 28, 29, 30, 31]
+# steps:
+# - uses: actions/checkout@v2
+# - name: set up JDK 11
+# uses: actions/setup-java@v2
+# with:
+# java-version: '11'
+# distribution: 'adopt'
+# cache: gradle
+# - name: Prepare
+# run: ./.github/prepare-workflow
+# - name: Validate Gradle wrapper
+# uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
+# - name: run tests
+# uses: reactivecircus/android-emulator-runner@v2
+# with:
+# api-level: ${{ matrix.api-level }}
+# arch: x86_64
+# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
+# disable-animations: true
+# script: ./gradlew connectedProdDebugAndroidTest
lint:
runs-on: ubuntu-latest
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/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/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/DisplayItemDropUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DisplayItemDropUseCase.kt
index 1d0e34b28..bac4e94fd 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DisplayItemDropUseCase.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/DisplayItemDropUseCase.kt
@@ -5,14 +5,14 @@ import androidx.appcompat.app.AppCompatActivity
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.executors.PostExecutionThread
import com.habitrpg.android.habitica.helpers.SoundManager
-import com.habitrpg.common.habitica.models.responses.TaskScoringResult
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
+import com.habitrpg.common.habitica.models.responses.TaskScoringResult
import io.reactivex.rxjava3.core.Flowable
-import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
+import javax.inject.Inject
class DisplayItemDropUseCase @Inject
constructor(private val soundManager: SoundManager, postExecutionThread: PostExecutionThread) : UseCase(postExecutionThread) {
@@ -22,14 +22,14 @@ constructor(private val soundManager: SoundManager, postExecutionThread: PostExe
val data = requestValues.data
val snackbarText = StringBuilder(data?.drop?.dialog ?: "")
- if (data?.questItemsFound ?: 0 > 0 && requestValues.showQuestItems) {
+ if ((data?.questItemsFound ?: 0) > 0 && requestValues.showQuestItems) {
if (snackbarText.isNotEmpty())
snackbarText.append('\n')
snackbarText.append(requestValues.context.getString(R.string.quest_items_found, data!!.questItemsFound))
}
if (snackbarText.isNotEmpty()) {
- GlobalScope.launch(context = Dispatchers.Main) {
+ MainScope().launch(context = Dispatchers.Main) {
delay(3000L)
HabiticaSnackbar.showSnackbar(
requestValues.snackbarTargetView,
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/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/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/adapter/inventory/ItemRecyclerAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.kt
index 0539b94e6..e66a08d7d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.kt
@@ -8,7 +8,6 @@ import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.ItemItemBinding
-import com.habitrpg.common.habitica.extensions.layoutInflater
import com.habitrpg.android.habitica.models.inventory.Egg
import com.habitrpg.android.habitica.models.inventory.Food
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
@@ -20,10 +19,11 @@ import com.habitrpg.android.habitica.models.user.OwnedItem
import com.habitrpg.android.habitica.models.user.OwnedPet
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
-import com.habitrpg.common.habitica.extensions.loadImage
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem
import com.habitrpg.android.habitica.ui.views.dialogs.DetailDialog
+import com.habitrpg.common.habitica.extensions.layoutInflater
+import com.habitrpg.common.habitica.extensions.loadImage
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.subjects.PublishSubject
@@ -105,7 +105,7 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter 0) {
+ if (specialItem.isMysteryItem && (ownedItem?.numberOwned ?: 0) > 0) {
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.open)))
- } else if (ownedItem?.numberOwned ?: 0 > 0) {
+ } else if ((ownedItem?.numberOwned ?: 0) > 0) {
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.use_item)))
}
}
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/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/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 dcc701b40..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
@@ -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
@@ -41,13 +38,16 @@ 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
-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/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/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/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/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/common/src/main/java/com/habitrpg/common/habitica/models/responses/TaskDirectionDataTemp.kt b/common/src/main/java/com/habitrpg/common/habitica/models/responses/TaskDirectionDataTemp.kt
index ba2d20ce5..6e6186e56 100644
--- a/common/src/main/java/com/habitrpg/common/habitica/models/responses/TaskDirectionDataTemp.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/models/responses/TaskDirectionDataTemp.kt
@@ -1,5 +1,8 @@
package com.habitrpg.common.habitica.models.responses
+import android.os.Parcel
+import android.os.Parcelable
+
class TaskDirectionDataTemp {
var drop: TaskDirectionDataDrop? = null
@@ -12,10 +15,37 @@ class TaskDirectionDataQuest {
var collection: Int = 0
}
-class TaskDirectionDataDrop {
-
+class TaskDirectionDataDrop() : Parcelable {
var value: Int = 0
var key: String? = null
var type: String? = null
var dialog: String? = null
+
+ constructor(parcel: Parcel) : this() {
+ value = parcel.readInt()
+ key = parcel.readString()
+ type = parcel.readString()
+ dialog = parcel.readString()
+ }
+
+ override fun writeToParcel(parcel: Parcel, flags: Int) {
+ parcel.writeInt(value)
+ parcel.writeString(key)
+ parcel.writeString(type)
+ parcel.writeString(dialog)
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ companion object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): TaskDirectionDataDrop {
+ return TaskDirectionDataDrop(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
}
diff --git a/common/src/main/java/com/habitrpg/common/habitica/models/responses/TaskScoringResult.kt b/common/src/main/java/com/habitrpg/common/habitica/models/responses/TaskScoringResult.kt
index 15aad3a07..b3f51dc9f 100644
--- a/common/src/main/java/com/habitrpg/common/habitica/models/responses/TaskScoringResult.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/models/responses/TaskScoringResult.kt
@@ -8,10 +8,10 @@ class TaskScoringResult(): Parcelable {
constructor(data: TaskDirectionData, stats: AvatarStats?) : this() {
hasLeveledUp = data.lvl > (stats?.lvl ?: 0)
healthDelta = data.hp - (stats?.hp ?: 0.0)
- if (hasLeveledUp) {
- experienceDelta = (stats?.toNextLevel ?: 0).toDouble() - (stats?.exp ?: 0.0) + data.exp
+ experienceDelta = if (hasLeveledUp) {
+ (stats?.toNextLevel ?: 0).toDouble() - (stats?.exp ?: 0.0) + data.exp
} else {
- experienceDelta = data.exp - (stats?.exp ?: 0.0)
+ data.exp - (stats?.exp ?: 0.0)
}
manaDelta = data.mp - (stats?.mp ?: 0.0)
goldDelta = data.gp - (stats?.gp ?: 0.0)
@@ -40,6 +40,7 @@ class TaskScoringResult(): Parcelable {
level = parcel.readValue(Int::class.java.classLoader) as? Int
questDamage = parcel.readValue(Double::class.java.classLoader) as? Double
questItemsFound = parcel.readValue(Int::class.java.classLoader) as? Int
+ drop = parcel.readValue(TaskDirectionDataDrop::class.java.classLoader) as? TaskDirectionDataDrop
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
@@ -51,6 +52,7 @@ class TaskScoringResult(): Parcelable {
parcel.writeValue(level)
parcel.writeValue(questDamage)
parcel.writeValue(questItemsFound)
+ parcel.writeValue(drop)
}
override fun describeContents(): Int {
diff --git a/common/src/main/java/com/habitrpg/common/habitica/models/tasks/TasksOrder.kt b/common/src/main/java/com/habitrpg/common/habitica/models/tasks/TasksOrder.kt
index 6b83bc3fc..501a45ac4 100644
--- a/common/src/main/java/com/habitrpg/common/habitica/models/tasks/TasksOrder.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/models/tasks/TasksOrder.kt
@@ -1,6 +1,15 @@
package com.habitrpg.common.habitica.models.tasks
class TasksOrder {
+ fun positionOf(key: String, type: TaskType): Int {
+ return when (type) {
+ TaskType.HABIT -> habits.indexOf(key)
+ TaskType.DAILY -> dailys.indexOf(key)
+ TaskType.TODO -> todos.indexOf(key)
+ TaskType.REWARD -> rewards.indexOf(key)
+ }
+ }
+
var habits: List = listOf()
var dailys: List = listOf()
var todos: List = listOf()
diff --git a/common/src/main/java/com/habitrpg/common/habitica/views/UsernameLabel.kt b/common/src/main/java/com/habitrpg/common/habitica/views/UsernameLabel.kt
index 8bd65580f..6ab09431d 100644
--- a/common/src/main/java/com/habitrpg/common/habitica/views/UsernameLabel.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/views/UsernameLabel.kt
@@ -13,7 +13,9 @@ import androidx.core.content.ContextCompat
import com.habitrpg.common.habitica.R
import com.habitrpg.common.habitica.models.PlayerTier
-class UsernameLabel(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
+class UsernameLabel @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null
+) : LinearLayout(context, attrs) {
private val textView = TextView(context)
private val tierIconView = ImageView(context)
@@ -54,7 +56,7 @@ class UsernameLabel(context: Context?, attrs: AttributeSet?) : LinearLayout(cont
textViewParams.gravity = Gravity.CENTER_VERTICAL
textViewParams.weight = 1.0f
addView(textView, textViewParams)
- val padding = context?.resources?.getDimension(R.dimen.spacing_small)?.toInt() ?: 0
+ val padding = context.resources.getDimension(R.dimen.spacing_small).toInt()
textView.setPadding(0, 0, padding, 0)
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
val iconViewParams = LayoutParams(
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/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/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/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/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/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/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/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/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..4739dc3e2 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
@@ -54,6 +55,12 @@
Create a Task
Complete a Task
Create %s
+ New %s
+ Save %s
Are you sure?
+ Task
+
+ Failed to load
+ Retry
\ No newline at end of file
diff --git a/habitica.properties.example b/habitica.properties.example
new file mode 100644
index 000000000..dd5474b4d
--- /dev/null
+++ b/habitica.properties.example
@@ -0,0 +1,10 @@
+# Habitica Server Port
+# local instance
+# PORT=3000
+PORT=80
+BASE_URL=https://habitica.com
+STAGING_KEY=
+ANDROID_TESTING_UUID=
+APPLE_AUTH_CLIENT_ID=
+DEBUG_USER_ID=
+DEBUG_API_KEY=
diff --git a/habitica.resources.example b/habitica.resources.example
new file mode 100644
index 000000000..0e27e320f
--- /dev/null
+++ b/habitica.resources.example
@@ -0,0 +1,4 @@
+fabric_key=
+facebook_app_id=
+amplitude_app_id=
+application_ad_id=
diff --git a/wearos/build.gradle b/wearos/build.gradle
index 51dea440d..b4fd08bc1 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
}
@@ -79,6 +79,8 @@ dependencies {
implementation "com.google.dagger:hilt-android:$daggerhilt_version"
kapt "com.google.dagger:hilt-compiler:$daggerhilt_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
+
}
repositories {
mavenCentral()
diff --git a/wearos/src/main/AndroidManifest.xml b/wearos/src/main/AndroidManifest.xml
index 69aefbe0f..943e9543a 100644
--- a/wearos/src/main/AndroidManifest.xml
+++ b/wearos/src/main/AndroidManifest.xml
@@ -2,6 +2,7 @@
+
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/MainApplication.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/MainApplication.kt
index 6570ecbb8..fa5c92fd4 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/MainApplication.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/MainApplication.kt
@@ -5,11 +5,13 @@ import android.content.Intent
import com.habitrpg.common.habitica.extensions.setupCoil
import com.habitrpg.common.habitica.helpers.MarkdownParser
import com.habitrpg.common.habitica.views.HabiticaIconsHelper
+import com.habitrpg.wearos.habitica.data.repositories.TaskRepository
import com.habitrpg.wearos.habitica.data.repositories.UserRepository
import com.habitrpg.wearos.habitica.ui.activities.BaseActivity
import com.habitrpg.wearos.habitica.ui.activities.FaintActivity
import com.habitrpg.wearos.habitica.ui.activities.RYAActivity
import dagger.hilt.android.HiltAndroidApp
+import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach
@@ -20,6 +22,7 @@ import javax.inject.Inject
class MainApplication : Application() {
@Inject lateinit var userRepository: UserRepository
+ @Inject lateinit var taskRepository: TaskRepository
override fun onCreate() {
super.onCreate()
@@ -40,5 +43,13 @@ class MainApplication : Application() {
}
}.collect()
}
+ if (userRepository.hasAuthentication) {
+ MainScope().launch(CoroutineExceptionHandler { coroutineContext, throwable ->
+
+ }) {
+ val user = userRepository.retrieveUser()
+ taskRepository.retrieveTasks(user?.tasksOrder)
+ }
+ }
}
}
\ No newline at end of file
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiClient.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiClient.kt
index d30b1865e..5bee82645 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiClient.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/ApiClient.kt
@@ -1,6 +1,8 @@
package com.habitrpg.wearos.habitica.data
import android.content.Context
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
import com.amplitude.api.Amplitude
import com.habitrpg.common.habitica.BuildConfig
import com.habitrpg.common.habitica.api.HostConfig
@@ -10,6 +12,7 @@ import com.habitrpg.common.habitica.models.auth.UserAuthSocial
import com.habitrpg.wearos.habitica.models.WearableHabitResponse
import com.habitrpg.wearos.habitica.models.tasks.Task
import okhttp3.Cache
+import okhttp3.CacheControl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.logging.HttpLoggingInterceptor
@@ -34,7 +37,21 @@ class ApiClient @Inject constructor(
buildRetrofit()
}
- fun buildRetrofit() {
+ private fun hasNetwork(context: Context): Boolean {
+ val connectivityManager =
+ context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ val networkCapabilities = connectivityManager.activeNetwork ?: return false
+ val actNw =
+ connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
+ return when {
+ actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
+ actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
+ actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
+ else -> false
+ }
+ }
+
+ private fun buildRetrofit() {
val logging = HttpLoggingInterceptor()
if (BuildConfig.DEBUG) {
logging.level = HttpLoggingInterceptor.Level.BODY
@@ -44,15 +61,36 @@ class ApiClient @Inject constructor(
val calendar = GregorianCalendar()
val timeZone = calendar.timeZone
- val timezoneOffset = -TimeUnit.MINUTES.convert(timeZone.getOffset(calendar.timeInMillis).toLong(), TimeUnit.MILLISECONDS)
-
- val cacheSize: Long = 10 * 1024 * 1024 // 10 MB
+ val timezoneOffset = -TimeUnit.MINUTES.convert(
+ timeZone.getOffset(calendar.timeInMillis).toLong(),
+ TimeUnit.MILLISECONDS
+ )
+ val cacheSize = (5 * 1024 * 1024).toLong()
val cache = Cache(File(context.cacheDir, "http_cache"), cacheSize)
val client = OkHttpClient.Builder()
.cache(cache)
.addInterceptor(logging)
+ .addInterceptor { chain ->
+ val request = chain.request()
+ var cacheContol = CacheControl.Builder()
+ cacheContol = if (request.method == "GET") {
+ if (hasNetwork(context)) {
+ cacheContol.maxAge(5, TimeUnit.MINUTES)
+ } else {
+ cacheContol.maxAge(1, TimeUnit.DAYS)
+ .onlyIfCached()
+ }
+ } else {
+ cacheContol.noCache()
+ .noStore()
+ }
+ chain.proceed(request.newBuilder().header(
+ "Cache-Control",
+ cacheContol.build().toString()
+ ).build())
+ }
.addNetworkInterceptor { chain ->
val original = chain.request()
var builder: Request.Builder = original.newBuilder()
@@ -70,8 +108,16 @@ class ApiClient @Inject constructor(
builder = builder.header("Authorization", "Basic " + BuildConfig.STAGING_KEY)
}
val request = builder.method(original.method, original.body)
+ .removeHeader("Pragma")
.build()
- chain.proceed(request)
+ val response = chain.proceed(request)
+ if (request.method == "GET") {
+ response.newBuilder()
+ .header("Cache-Control", request.header("Cache-Control") ?: "")
+ .build()
+ } else {
+ response
+ }
}
.readTimeout(2400, TimeUnit.SECONDS)
.build()
@@ -111,6 +157,9 @@ class ApiClient @Inject constructor(
suspend fun runCron() = process(apiService.runCron())
suspend fun getTasks() = process(apiService.getTasks())
- suspend fun scoreTask(id: String, direction: String) = process(apiService.scoreTask(id, direction))
+ suspend fun scoreTask(id: String, direction: String) =
+ process(apiService.scoreTask(id, direction))
+
suspend fun createTask(task: Task) = process(apiService.createTask(task))
+ fun hasAuthentication() = hostConfig.hasAuthentication()
}
\ 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..d4ce7c5b3 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
@@ -3,11 +3,14 @@ package com.habitrpg.wearos.habitica.data.repositories
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asFlow
import com.habitrpg.common.habitica.models.tasks.TaskType
+import com.habitrpg.common.habitica.models.tasks.TasksOrder
import com.habitrpg.wearos.habitica.models.tasks.Task
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,25 +22,45 @@ 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()
}
- fun saveTasks(tasks: TaskList) {
+ fun saveTasks(tasks: TaskList, order: TasksOrder?) {
val taskMap = mutableMapOf(
- TaskType.HABIT to mutableListOf(),
- TaskType.DAILY to mutableListOf(),
- TaskType.TODO to mutableListOf(),
- TaskType.REWARD to mutableListOf()
+ TaskType.HABIT to sortTasks(tasks.tasks, order?.habits ?: emptyList(), TaskType.HABIT),
+ TaskType.DAILY to sortTasks(tasks.tasks, order?.dailys ?: emptyList(), TaskType.DAILY),
+ TaskType.TODO to sortTasks(tasks.tasks, order?.todos ?: emptyList(), TaskType.TODO),
+ TaskType.REWARD to sortTasks(tasks.tasks, order?.rewards ?: emptyList(), TaskType.REWARD)
)
- for (task in tasks.tasks) {
- if (task.value.type != null) {
- taskMap[task.value.type]?.add(task.value)
- }
- }
for (type in taskMap) {
this.tasks[type.key]?.value = type.value
}
+ taskCountHelperValue.value = Date().time
+ }
+
+ private fun sortTasks(taskMap: MutableMap, taskOrder: List, type: TaskType): List {
+ val taskList = ArrayList()
+ var position = 0
+ for (taskId in taskOrder) {
+ val task = taskMap[taskId]
+ if (task != null) {
+ task.position = position
+ taskList.add(task)
+ position++
+ taskMap.remove(taskId)
+ }
+ }
+ for (task in taskMap.values) {
+ if (task.type != type) continue
+ task.position = position
+ taskList.add(task)
+ position++
+ }
+ return taskList
}
fun updateTask(task: Task) {
@@ -51,6 +74,7 @@ class TaskLocalRepository @Inject constructor() {
oldList?.let {
tasks[task.type]?.value = it
}
+ taskCountHelperValue.value = Date().time
}
fun getTask(taskID: String): Flow {
@@ -63,10 +87,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..363c584e3 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
@@ -3,6 +3,7 @@ package com.habitrpg.wearos.habitica.data.repositories
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.models.tasks.TasksOrder
import com.habitrpg.wearos.habitica.data.ApiClient
import com.habitrpg.wearos.habitica.models.tasks.Task
import com.habitrpg.wearos.habitica.models.tasks.TaskList
@@ -11,11 +12,11 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import javax.inject.Inject
-class TaskRepository @Inject constructor(val apiClient: ApiClient, val localRepository: TaskLocalRepository) {
+class TaskRepository @Inject constructor(val apiClient: ApiClient, val localRepository: TaskLocalRepository, val userLocalRepository: UserLocalRepository) {
- suspend fun retrieveTasks(): TaskList? {
+ suspend fun retrieveTasks(order: TasksOrder?): TaskList? {
val tasks = apiClient.getTasks()
- tasks?.let { localRepository.saveTasks(tasks) }
+ tasks?.let { localRepository.saveTasks(tasks, order) }
return tasks
}
fun getTasks(taskType: TaskType) = localRepository.getTasks(taskType)
@@ -25,9 +26,36 @@ class TaskRepository @Inject constructor(val apiClient: ApiClient, val localRepo
val result = apiClient.scoreTask(id, direction.text)
if (result != null) {
task.completed = direction == TaskDirection.UP
+ task.value += result.delta
+ if (task.type == TaskType.HABIT) {
+ if (direction == TaskDirection.UP) {
+ task.counterUp = task.counterUp?.plus(1) ?: 1
+ } else {
+ task.counterUp = task.counterDown?.plus(1) ?: 1
+ }
+ } else if (task.type == TaskType.DAILY) {
+ if (direction == TaskDirection.UP) {
+ task.streak = task.streak?.plus(1) ?: 1
+ } else {
+ task.streak = task.streak?.minus(1) ?: 0
+ }
+ }
localRepository.updateTask(task)
}
- return result?.let { TaskScoringResult(it, user?.stats) }
+ val scoringResult = result?.let { TaskScoringResult(it, user?.stats) }
+ if (user != null) {
+ user.stats?.hp = result?.hp
+ user.stats?.exp = result?.exp
+ user.stats?.mp = result?.mp
+ user.stats?.gp = result?.gp
+ user.stats?.lvl = result?.lvl
+ /*user?.party?.quest?.progress?.up = (
+ user?.party?.quest?.progress?.up
+ ?: 0F
+ ) + (result?._tmp?.quest?.progressDelta?.toFloat() ?: 0F)*/
+ userLocalRepository.saveUser(user)
+ }
+ return scoringResult
}
fun getTask(taskID: String?): Flow {
@@ -43,4 +71,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/data/repositories/UserRepository.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserRepository.kt
index e3e3a80db..dc785bcf4 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserRepository.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/data/repositories/UserRepository.kt
@@ -5,7 +5,8 @@ import com.habitrpg.wearos.habitica.models.user.User
import javax.inject.Inject
class UserRepository @Inject constructor(val apiClient: ApiClient, val localRepository: UserLocalRepository) {
-
+ val hasAuthentication: Boolean
+ get() = apiClient.hasAuthentication()
fun getUser() = localRepository.getUser()
suspend fun retrieveUser(): User? {
@@ -21,5 +22,8 @@ class UserRepository @Inject constructor(val apiClient: ApiClient, val localRepo
suspend fun sleep() = apiClient.sleep()
suspend fun revive() = apiClient.revive()
- suspend fun runCron() = apiClient.runCron()
+ suspend fun runCron() {
+ apiClient.runCron()
+ retrieveUser()
+ }
}
\ No newline at end of file
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/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/models/user/User.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/models/user/User.kt
index 551328668..2d7d75575 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/models/user/User.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/models/user/User.kt
@@ -1,10 +1,12 @@
package com.habitrpg.wearos.habitica.models.user
import com.habitrpg.common.habitica.models.Avatar
+import com.habitrpg.common.habitica.models.tasks.TasksOrder
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
class User: Avatar {
+ val tasksOrder: TasksOrder? = null
val isDead: Boolean
get() = (stats?.hp ?: 0.0) <= 0.0
override val currentMount: String?
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..63a2a5f4f 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,13 +111,18 @@ 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+1)
}
viewModel.taskCounts.observe(this) {
adapter.data.forEach { menuItem ->
- if (it.containsKey(menuItem.identifier) && it[menuItem.identifier]!! > 0) {
- menuItem.detailText = it[menuItem.identifier].toString()
- } else {
- menuItem.detailText = null
+ if (it.containsKey(menuItem.identifier)) {
+ if (it[menuItem.identifier]!! > 0) {
+ menuItem.detailText = it[menuItem.identifier].toString()
+ } else {
+ menuItem.detailText = null
+ }
}
}
adapter.notifyDataSetChanged()
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 375e6574e..a3c471005 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
@@ -69,17 +69,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/activities/TaskDetailActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskDetailActivity.kt
index 03e9f282e..632fdb977 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskDetailActivity.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskDetailActivity.kt
@@ -2,14 +2,16 @@ package com.habitrpg.wearos.habitica.ui.activities
import android.os.Bundle
import androidx.activity.viewModels
+import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
+import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.ActivityTaskDetailBinding
import com.habitrpg.wearos.habitica.ui.viewmodels.TaskDetailViewModel
import dagger.hilt.android.AndroidEntryPoint
import java.util.Locale
@AndroidEntryPoint
-class TaskDetailActivity: BaseActivity() {
+class TaskDetailActivity : BaseActivity() {
override val viewModel: TaskDetailViewModel by viewModels()
@@ -29,15 +31,21 @@ class TaskDetailActivity: BaseActivity
+ binding.taskTypeView.text = task?.type?.value?.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(
Locale.getDefault()
) else it.toString()
}
- binding.taskTextView.text = it?.text
- if (it?.notes?.isNotBlank() == true) {
- binding.taskNotesView.text = it.notes
+ binding.taskTypeView.setTextColor(
+ ContextCompat.getColor(
+ this,
+ task?.extraLightTaskColor ?: R.color.white
+ )
+ )
+ binding.taskTextView.text = task?.text
+ if (task?.notes?.isNotBlank() == true) {
+ binding.taskNotesView.text = task.notes
binding.taskNotesView.isVisible = true
} else {
binding.taskNotesView.isVisible = false
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskFormActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskFormActivity.kt
index 4e9fdbe3f..3cb3bcd00 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskFormActivity.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskFormActivity.kt
@@ -1,13 +1,16 @@
package com.habitrpg.wearos.habitica.ui.activities
+import android.content.Context
import android.content.Intent
import android.content.res.ColorStateList
import android.os.Bundle
import android.view.inputmethod.EditorInfo
+import android.view.inputmethod.InputMethodManager
import android.widget.TextView
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
+import androidx.core.view.postDelayed
import androidx.lifecycle.lifecycleScope
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.ActivityTaskFormBinding
@@ -25,7 +28,15 @@ class TaskFormActivity : BaseActivity R.string.habit
+ TaskType.DAILY -> R.string.daily
+ TaskType.TODO -> R.string.todo
+ TaskType.REWARD -> R.string.reward
+ else -> R.string.task
+ })
+ binding.confirmationTitle.text = getString(R.string.new_task_x, typeName)
+ binding.saveButton.text = getString(R.string.save_task_x, typeName)
}
override val viewModel: TaskFormViewModel by viewModels()
@@ -72,13 +83,24 @@ class TaskFormActivity : 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/activities/TaskResultActivity.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskResultActivity.kt
index ee759ede2..dbe766bb1 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskResultActivity.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/activities/TaskResultActivity.kt
@@ -12,6 +12,7 @@ import androidx.preference.PreferenceManager
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.ActivityTaskResultBinding
import com.habitrpg.android.habitica.databinding.TaskRewardDropBinding
+import com.habitrpg.android.habitica.extensions.localizedCapitalize
import com.habitrpg.common.habitica.extensions.dpToPx
import com.habitrpg.common.habitica.extensions.loadImage
import com.habitrpg.common.habitica.models.responses.TaskScoringResult
@@ -155,14 +156,16 @@ class TaskResultActivity : BaseActivity elements[0]
2 -> getString(R.string.x_and_y, elements[0], elements[1])
else -> elements.joinToString(", ")
- }
+ }.localizedCapitalize()
}
}
diff --git a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/adapters/HubAdapter.kt b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/adapters/HubAdapter.kt
index a80e0c627..ad6e00c22 100644
--- a/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/adapters/HubAdapter.kt
+++ b/wearos/src/main/java/com/habitrpg/wearos/habitica/ui/adapters/HubAdapter.kt
@@ -2,9 +2,9 @@ package com.habitrpg.wearos.habitica.ui.adapters
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
-import com.habitrpg.common.habitica.extensions.layoutInflater
import com.habitrpg.android.habitica.databinding.RowHeaderBinding
import com.habitrpg.android.habitica.databinding.RowHubBinding
+import com.habitrpg.common.habitica.extensions.layoutInflater
import com.habitrpg.wearos.habitica.models.user.MenuItem
import com.habitrpg.wearos.habitica.ui.viewHolders.HeaderViewHolder
import com.habitrpg.wearos.habitica.ui.viewHolders.HubViewHolder
@@ -27,19 +27,14 @@ class HubAdapter: RecyclerView.Adapter() {
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is HubViewHolder) {
- val item = data[position - 1]
- holder.bind(item)
+ holder.bind(getItemAt(position - 1))
} else if (holder is HeaderViewHolder){
holder.bind(title)
}
}
- override fun getItemViewType(position: Int): Int {
- return if (position == 0) 0 else 1
- }
-
- override fun getItemCount(): Int {
- return data.size + 1
- }
+ private fun getItemAt(position: Int) = data.filter { !it.isHidden }[position]
+ override fun getItemViewType(position: Int) = if (position == 0) 0 else 1
+ override fun getItemCount() = data.filter { !it.isHidden }.size + 1
}
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 4516d9bc9..33893c8f8 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
@@ -90,7 +90,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/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